From 8f02e3e462dc7d4bd3ba781592a1a5fa7c3152cf Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sat, 2 Jan 2021 12:40:59 +0100 Subject: [PATCH 001/478] Fix PRIdS define for Windows MINGW64 and DJGPP Make the PRIdS define into "zu" instead of "Iu" for MINGW64 Fix checking for "DJGPP" instead of "__DJGPP__" --- src/m_misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_misc.c b/src/m_misc.c index 42890cb08..ef48dde00 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -62,9 +62,9 @@ typedef off_t off64_t; #if defined(__MINGW32__) && ((__GNUC__ > 7) || (__GNUC__ == 6 && __GNUC_MINOR__ >= 3)) && (__GNUC__ < 8) #define PRIdS "u" -#elif defined (_WIN32) +#elif defined(_WIN32) && !defined(__MINGW64__) #define PRIdS "Iu" -#elif defined (DJGPP) +#elif defined(__DJGPP__) #define PRIdS "u" #else #define PRIdS "zu" From a1a58143ec3e39b9cf76cdaeb84c6a07646a73e4 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 31 Aug 2021 19:00:05 -0700 Subject: [PATCH 002/478] Fix IPv6 address checks - SOCK_cmpaddr returned inverted truth for IPv6 addresses. This would prevent making a connection. - Account for IPv6 address resolution. (bug: 5a627482) --- src/i_tcp.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index cae97a7d1..3d5d302f8 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -427,7 +427,7 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) && (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port)); #ifdef HAVE_IPV6 else if (b->any.sa_family == AF_INET6) - return memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) + return !memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr)) && (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port)); #endif else @@ -1156,6 +1156,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) SINT8 newnode = -1; struct my_addrinfo *ai = NULL, *runp, hints; int gaie; + size_t i; if (!port || !port[0]) port = DEFAULTPORT; @@ -1183,13 +1184,20 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) while (runp != NULL) { - // find ip of the server - if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0) + // test ip address of server + for (i = 0; i < mysocketses; ++i) { - memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); - break; + if (runp->ai_addr->sa_family == myfamily[i]) + { + memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); + break; + } } - runp = runp->ai_next; + + if (i < mysocketses) + runp = runp->ai_next; + else + break; } I_freeaddrinfo(ai); return newnode; From f8a749be091176d1548fd2dc09eda4901d152d29 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 31 Aug 2021 19:03:23 -0700 Subject: [PATCH 003/478] Correctly set IPV6_V6ONLY setsockopt level for v6 options is IPPROTO_IPV6. --- src/i_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 3d5d302f8..50d1a57fa 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -788,7 +788,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen // make it IPv6 ony opt = true; opts = (socklen_t)sizeof(opt); - if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts)) + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts)) { CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore } From 0422870df85932748d8166b3ce46dde3f87f0417 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 31 Aug 2021 19:54:27 -0700 Subject: [PATCH 004/478] Use RFC2732 notation for IPv6 addresses This fixes keepbody and the connect command (also '-connect' parameter). connect ::1 connect [::1]:5029 --- src/d_clisrv.c | 19 ++++++++----------- src/d_net.c | 26 +++++++++++++++++--------- src/i_net.h | 11 +++++++++++ src/i_tcp.c | 21 +++++++++++++++++---- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index aa7bc8a6c..e9a70c8ec 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1171,9 +1171,9 @@ static boolean CL_SendJoin(void) static INT32 FindRejoinerNum(SINT8 node) { - char strippednodeaddress[64]; + char addressbuffer[64]; const char *nodeaddress; - char *port; + const char *strippednodeaddress; INT32 i; // Make sure there is no dead dress before proceeding to the stripping @@ -1184,10 +1184,8 @@ static INT32 FindRejoinerNum(SINT8 node) return -1; // Strip the address of its port - strcpy(strippednodeaddress, nodeaddress); - port = strchr(strippednodeaddress, ':'); - if (port) - *port = '\0'; + strcpy(addressbuffer, nodeaddress); + strippednodeaddress = I_NetSplitAddress(addressbuffer, NULL); // Check if any player matches the stripped address for (i = 0; i < MAXPLAYERS; i++) @@ -3426,14 +3424,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) if (server && I_GetNodeAddress) { + char addressbuffer[64]; const char *address = I_GetNodeAddress(node); - char *port = NULL; if (address) // MI: fix msvcrt.dll!_mbscat crash? { - strcpy(playeraddress[newplayernum], address); - port = strchr(playeraddress[newplayernum], ':'); - if (port) - *port = '\0'; + strcpy(addressbuffer, address); + strcpy(playeraddress[newplayernum], + I_NetSplitAddress(addressbuffer, NULL)); } } } diff --git a/src/d_net.c b/src/d_net.c index 9e5abe24a..6906ac123 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1200,26 +1200,34 @@ static void Internal_FreeNodenum(INT32 nodenum) (void)nodenum; } +char *I_NetSplitAddress(char *host, char **port) +{ + boolean v4 = (strchr(host, '.') != NULL); + + host = strtok(host, v4 ? ":" : "[]"); + + if (port) + *port = strtok(NULL, ":"); + + return host; +} + SINT8 I_NetMakeNode(const char *hostname) { SINT8 newnode = -1; if (I_NetMakeNodewPort) { char *localhostname = strdup(hostname); - char *t = localhostname; - const char *port; + char *port; if (!localhostname) return newnode; + // retrieve portnum from address! - strtok(localhostname, ":"); - port = strtok(NULL, ":"); + hostname = I_NetSplitAddress(localhostname, &port); - // remove the port in the hostname as we've it already - while ((*t != ':') && (*t != '\0')) - t++; - *t = '\0'; + CONS_Printf("%s %s\n", hostname, port); - newnode = I_NetMakeNodewPort(localhostname, port); + newnode = I_NetMakeNodewPort(hostname, port); free(localhostname); } return newnode; diff --git a/src/i_net.h b/src/i_net.h index dbc82db65..2d09af750 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -109,6 +109,17 @@ extern boolean (*I_NetCanSend)(void); */ extern void (*I_NetFreeNodenum)(INT32 nodenum); +/** + \brief split a string into address and port + + \param address string to split + + \param port double pointer to hold port component (optional) + + \return address component +*/ +extern char *I_NetSplitAddress(char *address, char **port); + /** \brief open a connection with specified address \param address address to connect to diff --git a/src/i_tcp.c b/src/i_tcp.c index 50d1a57fa..ca55515ab 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -340,8 +340,14 @@ static inline void I_UPnP_rem(const char *port, const char * servicetype) static const char *SOCK_AddrToStr(mysockaddr_t *sk) { - static char s[64]; // 255.255.255.255:65535 or IPv6:65535 + static char s[64]; // 255.255.255.255:65535 or + // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 #ifdef HAVE_NTOP +#ifdef HAVE_IPV6 + int v6 = (sk->any.sa_family == AF_INET6); +#else + int v6 = 0; +#endif void *addr; if(sk->any.sa_family == AF_INET) @@ -355,14 +361,21 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) if(addr == NULL) sprintf(s, "No address"); - else if(inet_ntop(sk->any.sa_family, addr, s, sizeof (s)) == NULL) + else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL) sprintf(s, "Unknown family type, error #%u", errno); #ifdef HAVE_IPV6 - else if(sk->any.sa_family == AF_INET6 && sk->ip6.sin6_port != 0) - strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); + else if(sk->any.sa_family == AF_INET6) + { + s[0] = '['; + strcat(s, "]"); + + if (sk->ip6.sin6_port != 0) + strcat(s, va(":%d", ntohs(sk->ip6.sin6_port))); + } #endif else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); + #else if (sk->any.sa_family == AF_INET) { From 44bafe0a325768e8cf8cf04e7802804961751865 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 31 Aug 2021 20:00:20 -0700 Subject: [PATCH 005/478] Remove debug print --- src/d_net.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/d_net.c b/src/d_net.c index 6906ac123..ecf446529 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1225,8 +1225,6 @@ SINT8 I_NetMakeNode(const char *hostname) // retrieve portnum from address! hostname = I_NetSplitAddress(localhostname, &port); - CONS_Printf("%s %s\n", hostname, port); - newnode = I_NetMakeNodewPort(hostname, port); free(localhostname); } From 32ad1f2067d05d2e82a233b67c68d649e4ceaabe Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 31 Aug 2021 20:02:09 -0700 Subject: [PATCH 006/478] Make IPv6 default An IPv4 socket is still made. The '-ipv6' parameter is replaced with '-noipv6', self explanatory. --- src/i_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index ca55515ab..7878d1fbb 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -857,7 +857,7 @@ static boolean UDP_Socket(void) struct my_addrinfo *ai, *runp, hints; int gaie; #ifdef HAVE_IPV6 - const INT32 b_ipv6 = M_CheckParm("-ipv6"); + const INT32 b_ipv6 = !M_CheckParm("-noipv6"); #endif const char *serv; From c9631565d62f6899b8f052bba698ebe13e4db69e Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 1 Sep 2021 17:35:41 -0700 Subject: [PATCH 007/478] Fix address structure handling in UDP_Bind Fixed instances of copying only sizeof (struct sockaddr) bytes (not enough for struct sockaddr_in6), as well as trying to getsockname into an insufficient buffer. --- src/i_tcp.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 7878d1fbb..9cdcc6ec4 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -748,8 +748,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen unsigned long trueval = true; #endif mysockaddr_t straddr; - struct sockaddr_in sin; - socklen_t len = sizeof(sin); + socklen_t len = sizeof(straddr); if (s == (SOCKET_TYPE)ERRSOCKET) return (SOCKET_TYPE)ERRSOCKET; @@ -767,14 +766,12 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen } #endif - straddr.any = *addr; + memcpy(&straddr, addr, addrlen); I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr)); if (family == AF_INET) { - mysockaddr_t tmpaddr; - tmpaddr.any = *addr ; - if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) + if (straddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY)) { opt = true; opts = (socklen_t)sizeof(opt); @@ -791,7 +788,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen #ifdef HAVE_IPV6 else if (family == AF_INET6) { - if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL + if (memcmp(&straddr.ip6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL { opt = true; opts = (socklen_t)sizeof(opt); @@ -843,10 +840,17 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10); } - if (getsockname(s, (struct sockaddr *)&sin, &len) == -1) + if (getsockname(s, &straddr.any, &len) == -1) CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n")); else - current_port = (UINT16)ntohs(sin.sin_port); + { + if (family == AF_INET) + current_port = (UINT16)ntohs(straddr.ip4.sin_port); +#ifdef HAVE_IPV6 + else if (family == AF_INET6) + current_port = (UINT16)ntohs(straddr.ip6.sin6_port); +#endif + } return s; } From 7976d0476d9ab3148c1e4dd24c477c686aa35b14 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 1 Sep 2021 18:02:39 -0700 Subject: [PATCH 008/478] Enbiglarge ip field of server list to fit IPv6 addresses --- src/mserv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mserv.h b/src/mserv.h index 7a3b3d8ec..b97abb634 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -33,7 +33,7 @@ typedef union typedef struct { msg_header_t header; - char ip[16]; + char ip[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"]; char port[8]; char name[32]; INT32 room; From 31943f30a1829a51620f8d7d3437634105185cde Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 1 Sep 2021 18:32:18 -0700 Subject: [PATCH 009/478] Support connecting by IPv6 address in the menu Font will shrink once exceeding a certain number of characters. --- src/m_menu.c | 56 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index db2aa09c6..35dae1d03 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -968,7 +968,7 @@ static menuitem_t MP_MainMenu[] = { {IT_HEADER, NULL, "Join a game", NULL, 0}, {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenuModChecks, 12}, - {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 22}, + {IT_STRING|IT_KEYHANDLER, NULL, "Specify server address:", M_HandleConnectIP, 22}, {IT_HEADER, NULL, "Host a game", NULL, 54}, {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 66}, {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 76}, @@ -11605,7 +11605,35 @@ static void M_StartServerMenu(INT32 choice) // CONNECT VIA IP // ============== -static char setupm_ip[28]; +static char setupm_ip[sizeof "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535"]; + +static void M_DrawConnectIP(void) +{ + INT32 x = currentMenu->x; + INT32 y = currentMenu->y + 22; + + INT32 opt = V_ALLOWLOWERCASE; + INT32 width; + + V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); + + // draw name string + if (strlen(setupm_ip) > 30)/* w stands for wide boi */ + { + V_DrawThinString(x+8,y+12, opt, setupm_ip); + width = V_ThinStringWidth(setupm_ip, opt); + } + else + { + V_DrawString(x+8,y+12, opt, setupm_ip); + width = V_StringWidth(setupm_ip, opt); + } + + // draw text cursor for name + if (itemOn == 2 //0 + && skullAnimCounter < 4) //blink cursor + V_DrawCharacter(x+8+width,y+12,'_',false); +} // Draw the funky Connect IP menu. Tails 11-19-2002 // So much work for such a little thing! @@ -11626,17 +11654,7 @@ static void M_DrawMPMainMenu(void) V_DrawRightAlignedString(BASEVIDWIDTH-x, y+116, ((itemOn == 8) ? V_YELLOWMAP : 0), "(splitscreen)"); - y += 22; - - V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); - - // draw name string - V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip); - - // draw text cursor for name - if (itemOn == 2 //0 - && skullAnimCounter < 4) //blink cursor - V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false); + M_DrawConnectIP(); } // Tails 11-19-2002 @@ -11719,7 +11737,7 @@ static void M_HandleConnectIP(INT32 choice) const char *paste = I_ClipboardPaste(); if (paste != NULL) { - strncat(setupm_ip, paste, 28-1 - l); // Concat the ip field with clipboard + strncat(setupm_ip, paste, (sizeof setupm_ip)-1 - l); // Concat the ip field with clipboard if (strlen(paste) != 0) // Don't play sound if nothing was pasted S_StartSound(NULL,sfx_menu1); // Tails } @@ -11753,7 +11771,7 @@ static void M_HandleConnectIP(INT32 choice) const char *paste = I_ClipboardPaste(); if (paste != NULL) { - strncat(setupm_ip, paste, 28-1 - l); // Concat the ip field with clipboard + strncat(setupm_ip, paste, (sizeof setupm_ip)-1 - l); // Concat the ip field with clipboard if (strlen(paste) != 0) // Don't play sound if nothing was pasted S_StartSound(NULL,sfx_menu1); // Tails } @@ -11770,11 +11788,15 @@ static void M_HandleConnectIP(INT32 choice) } } - if (l >= 28-1) + if (l >= (sizeof setupm_ip)-1) break; // Rudimentary number and period enforcing - also allows letters so hostnames can be used instead - if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z')) + // and square brackets for RFC 2732 IPv6 addresses + if ((choice >= '-' && choice <= ':') || + (choice == '[' || choice == ']') || + (choice >= 'A' && choice <= 'Z') || + (choice >= 'a' && choice <= 'z')) { S_StartSound(NULL,sfx_menu1); // Tails setupm_ip[l] = (char)choice; From 46a5ce4325fbe23234a8167bd16bc4ef6bf7ceee Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 1 Sep 2021 18:41:41 -0700 Subject: [PATCH 010/478] Only restrict master server connection to IPv4 if -noipv6 --- src/http-mserv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/http-mserv.c b/src/http-mserv.c index f9134ba50..a0912a81e 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -196,7 +196,9 @@ HMS_connect (const char *format, ...) curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + + if (M_CheckParm("-noipv6")) + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read); From 39fdbac2ace76cc1ead1b92b4f32d2aa17ad99d2 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 3 Sep 2021 16:41:08 -0700 Subject: [PATCH 011/478] Only test -noipv6 if enabled at compile time --- src/http-mserv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/http-mserv.c b/src/http-mserv.c index a0912a81e..0ab16f989 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -197,7 +197,9 @@ HMS_connect (const char *format, ...) curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); +#ifndef NO_IPV6 if (M_CheckParm("-noipv6")) +#endif curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value); From b2fe36fe5b504ae2221a4306f76e663fff38090f Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 3 Sep 2021 16:48:29 -0700 Subject: [PATCH 012/478] Add back address resolution test Mistakenly removed by a1a58143e --- src/i_tcp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/i_tcp.c b/src/i_tcp.c index 9cdcc6ec4..48a65faae 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1204,7 +1204,11 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) // test ip address of server for (i = 0; i < mysocketses; ++i) { - if (runp->ai_addr->sa_family == myfamily[i]) + /* sendto tests that there is a network to this + address */ + if (runp->ai_addr->sa_family == myfamily[i] && + sendto(mysockets[i], NULL, 0, 0, + runp->ai_addr, runp->ai_addrlen) == 0) { memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); break; From 4424f6ba9a59b06c10d0bb683c8e00cded1d90db Mon Sep 17 00:00:00 2001 From: tertu marybig Date: Tue, 28 Sep 2021 08:31:14 -0500 Subject: [PATCH 013/478] Remove FixedMul and FixedDiv2 asm implementations Actually works this time --- src/m_fixed.c | 44 ---------------- src/m_fixed.h | 136 ++++++++------------------------------------------ 2 files changed, 22 insertions(+), 158 deletions(-) diff --git a/src/m_fixed.c b/src/m_fixed.c index d40ccd98e..315ac0bde 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -21,50 +21,6 @@ #include "doomdef.h" #include "m_fixed.h" -#ifdef __USE_C_FIXEDMUL__ - -/** \brief The FixedMul function - - \param a fixed_t number - \param b fixed_t number - - \return a*b>>FRACBITS - -*/ -fixed_t FixedMul(fixed_t a, fixed_t b) -{ - // Need to cast to unsigned before shifting to avoid undefined behaviour - // for negative integers - return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS); -} - -#endif //__USE_C_FIXEDMUL__ - -#ifdef __USE_C_FIXEDDIV__ -/** \brief The FixedDiv2 function - - \param a fixed_t number - \param b fixed_t number - - \return a/b * FRACUNIT - -*/ -fixed_t FixedDiv2(fixed_t a, fixed_t b) -{ - INT64 ret; - - if (b == 0) - I_Error("FixedDiv: divide by zero"); - - ret = (((INT64)a * FRACUNIT)) / b; - - if ((ret > INT32_MAX) || (ret < INT32_MIN)) - I_Error("FixedDiv: divide by zero"); - return (fixed_t)ret; -} - -#endif // __USE_C_FIXEDDIV__ - fixed_t FixedSqrt(fixed_t x) { #ifdef HAVE_SQRT diff --git a/src/m_fixed.h b/src/m_fixed.h index 1cf2f00d1..83b1710f7 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -53,127 +53,35 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f) #define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT)) #define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT)) +/** \brief The FixedMul function -#if defined (__WATCOMC__) && FRACBITS == 16 - #pragma aux FixedMul = \ - "imul ebx", \ - "shrd eax,edx,16" \ - parm [eax] [ebx] \ - value [eax] \ - modify exact [eax edx] + \param a fixed_t number + \param b fixed_t number - #pragma aux FixedDiv2 = \ - "cdq", \ - "shld edx,eax,16", \ - "sal eax,16", \ - "idiv ebx" \ - parm [eax] [ebx] \ - value [eax] \ - modify exact [eax edx] -#elif defined (__GNUC__) && defined (__i386__) && !defined (NOASM) - // i386 linux, cygwin or mingw - FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // asm - { - fixed_t ret; - asm - ( - "imull %2;" // a*b - "shrdl %3,%%edx,%0;" // shift logical right FRACBITS bits - :"=a" (ret) // eax is always the result and the first operand (%0,%1) - :"0" (a), "r" (b) // and %2 is what we use imull on with what in %1 - , "I" (FRACBITS) // %3 holds FRACBITS (normally 16) - :"cc", "%edx" // edx and condition codes clobbered - ); - return ret; - } + \return a*b>>FRACBITS - FUNCMATH FUNCINLINE static inline fixed_t FixedDiv2(fixed_t a, fixed_t b) - { - fixed_t ret; - asm - ( - "movl %1,%%edx;" // these two instructions allow the next two to pair, on the Pentium processor. - "sarl $31,%%edx;" // shift arithmetic right 31 on EDX - "shldl %3,%1,%%edx;" // DP shift logical left FRACBITS on EDX - "sall %3,%0;" // shift arithmetic left FRACBITS on EAX - "idivl %2;" // EDX/b = EAX - : "=a" (ret) - : "0" (a), "r" (b) - , "I" (FRACBITS) - : "%edx" - ); - return ret; - } -#elif defined (__GNUC__) && defined (__arm__) && !defined(__thumb__) && !defined(NOASM) //ARMv4 ASM - FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // let abuse smull - { - fixed_t ret; - asm - ( - "smull %[lo], r1, %[a], %[b];" - "mov %[lo], %[lo], lsr %3;" - "orr %[lo], %[lo], r1, lsl %3;" - : [lo] "=&r" (ret) // rhi, rlo and rm must be distinct registers - : [a] "r" (a), [b] "r" (b) - , "i" (FRACBITS) - : "r1" - ); - return ret; - } +*/ +FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedMul(fixed_t a, fixed_t b) +{ + // Need to cast to unsigned before shifting to avoid undefined behaviour + // for negative integers + return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS); +} - #define __USE_C_FIXEDDIV__ // no double or asm div in ARM land -#elif defined (__GNUC__) && defined (__ppc__) && !defined(NOASM) && 0 // WII: PPC CPU - FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // asm - { - fixed_t ret, hi, lo; - asm - ( - "mullw %0, %2, %3;" - "mulhw %1, %2, %3" - : "=r" (hi), "=r" (lo) - : "r" (a), "r" (b) - , "I" (FRACBITS) - ); - ret = (INT64)((hi>>FRACBITS)+lo)<>FRACBITS)+b)< Date: Tue, 7 Dec 2021 17:10:38 -0600 Subject: [PATCH 014/478] fix spike ring catapult --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 836e75c4e..7e754bed9 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1144,7 +1144,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } // When solid spikes move, assume they just popped up and teleport things on top of them to hurt. - if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID) + if (tmthing->type == MT_SPIKE && (thing->flags & MF_SOLID) && (tmthing->flags & MF_SOLID)) { if (thing->z > tmthing->z + tmthing->height) return true; // overhead From d764d68d02c1f7609c65534f7cfa07da724c42cd Mon Sep 17 00:00:00 2001 From: lachablock Date: Thu, 13 Jan 2022 18:53:26 +1100 Subject: [PATCH 015/478] Turn dispoffset into a mobj field --- src/hardware/hw_glob.h | 2 +- src/hardware/hw_main.c | 2 +- src/lua_mobjlib.c | 10 +++++++++- src/p_mobj.c | 2 ++ src/p_mobj.h | 1 + src/p_saveg.c | 9 +++++++++ src/r_things.c | 2 +- src/r_things.h | 2 +- 8 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 37d77b467..68c5dd14d 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -84,7 +84,7 @@ typedef struct gl_vissprite_s //Hurdler: 25/04/2000: now support colormap in hardware mode UINT8 *colormap; - INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing + INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing patch_t *gpatch; mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d2982afe4..ab2b7cae2 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5052,7 +5052,7 @@ static void HWR_ProjectSprite(mobj_t *thing) return; } - dispoffset = thing->info->dispoffset; + dispoffset = thing->dispoffset; this_scale = FIXED_TO_FLOAT(thing->scale); spritexscale = FIXED_TO_FLOAT(thing->spritexscale); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index cf8ccab2c..ffdfe999d 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -96,7 +96,8 @@ enum mobj_e { mobj_standingslope, mobj_colorized, mobj_mirrored, - mobj_shadowscale + mobj_shadowscale, + mobj_dispoffset }; static const char *const mobj_opt[] = { @@ -173,6 +174,7 @@ static const char *const mobj_opt[] = { "colorized", "mirrored", "shadowscale", + "dispoffset", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -439,6 +441,9 @@ static int mobj_get(lua_State *L) case mobj_shadowscale: lua_pushfixed(L, mo->shadowscale); break; + case mobj_dispoffset: + lua_pushinteger(L, mo->dispoffset); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -803,6 +808,9 @@ static int mobj_set(lua_State *L) case mobj_shadowscale: mo->shadowscale = luaL_checkfixed(L, 3); break; + case mobj_dispoffset: + mo->dispoffset = luaL_checkinteger(L, 3); + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/p_mobj.c b/src/p_mobj.c index 87e20fd4a..10a01dbaa 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10499,6 +10499,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->reactiontime = info->reactiontime; + mobj->dispoffset = info->dispoffset; + mobj->lastlook = -1; // stuff moved in P_enemy.P_LookForPlayer // do not set the state with P_SetMobjState, diff --git a/src/p_mobj.h b/src/p_mobj.h index 2d096385b..d078137d8 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -390,6 +390,7 @@ typedef struct mobj_s boolean colorized; // Whether the mobj uses the rainbow colormap boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius + INT32 dispoffset; // copy of info->dispoffset, so mobjs can be sorted independently of their type // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index 722340f41..17c47c7a1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1486,6 +1486,7 @@ typedef enum MD2_SPRITEXOFFSET = 1<<20, MD2_SPRITEYOFFSET = 1<<21, MD2_FLOORSPRITESLOPE = 1<<22, + MD2_DISPOFFSET = 1<<23 } mobj_diff2_t; typedef enum @@ -1720,6 +1721,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) || (slope->normal.z != FRACUNIT)) diff2 |= MD2_FLOORSPRITESLOPE; } + if (mobj->dispoffset != mobj->info->dispoffset) + diff2 |= MD2_DISPOFFSET; if (diff2 != 0) diff |= MD_MORE; @@ -1895,6 +1898,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, slope->normal.y); WRITEFIXED(save_p, slope->normal.z); } + if (diff2 & MD2_DISPOFFSET) + WRITEINT32(save_p, mobj->dispoffset); WRITEUINT32(save_p, mobj->mobjnum); } @@ -2942,6 +2947,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) slope->normal.y = READFIXED(save_p); slope->normal.z = READFIXED(save_p); } + if (diff2 & MD2_DISPOFFSET) + mobj->dispoffset = READINT32(save_p); + else + mobj->dispoffset = mobj->info->dispoffset; if (diff & MD_REDFLAG) { diff --git a/src/r_things.c b/src/r_things.c index accd1e2b3..1dee17356 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1437,7 +1437,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; - INT32 dispoffset = thing->info->dispoffset; + INT32 dispoffset = thing->dispoffset; //SoM: 3/17/2000 fixed_t gz = 0, gzt = 0; diff --git a/src/r_things.h b/src/r_things.h index b1ff32b1e..6a6ff3042 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -209,7 +209,7 @@ typedef struct vissprite_s INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; - INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing + INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing } vissprite_t; extern UINT32 visspritecount; From 3bff9011d8a7baed3281a3be3c664fc7d0bdc41c Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Fri, 21 Jan 2022 16:16:13 +0200 Subject: [PATCH 016/478] LUA_EnumLib optimizations for constant value access - constants are stored into _G after first use - made LUA_EvalMath's dedicated Lua state permanent so it can also benefit from these optimizations --- src/deh_lua.c | 169 +++++++++++++++++++++++++++++------------------ src/deh_lua.h | 15 +++++ src/deh_soc.c | 3 + src/lua_script.c | 23 ++++--- 4 files changed, 134 insertions(+), 76 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index a2ffca95b..0bd906c13 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -10,20 +10,7 @@ /// \file deh_lua.c /// \brief Lua SOC library -#include "g_game.h" -#include "s_sound.h" -#include "z_zone.h" -#include "m_menu.h" -#include "m_misc.h" -#include "p_local.h" -#include "st_stuff.h" -#include "fastcmp.h" -#include "lua_script.h" -#include "lua_libs.h" - -#include "dehacked.h" #include "deh_lua.h" -#include "deh_tables.h" // freeslot takes a name (string only!) // and allocates it to the appropriate free slot. @@ -89,6 +76,8 @@ static inline int lib_freeslot(lua_State *L) strncpy(sprnames[j],word,4); //sprnames[j][4] = 0; used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now. + // Lua needs to update the value in _G if it exists + LUA_UpdateSprName(word, j); lua_pushinteger(L, j); r++; break; @@ -216,18 +205,27 @@ static int lib_dummysuper(lua_State *L) return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;; } -static inline int lib_getenum(lua_State *L) +static void CacheAndPushConstant(lua_State *L, const char *name, lua_Integer value) { - const char *word, *p; + // "cache" into _G + lua_pushstring(L, name); + lua_pushinteger(L, value); + lua_rawset(L, LUA_GLOBALSINDEX); + // push + lua_pushinteger(L, value); +} + +// Search for a matching constant variable. +// Result is stored into _G for faster subsequent use. (Except for SPR_ in the SOC parser) +static int ScanConstants(lua_State *L, boolean mathlib, const char *word) +{ + const char *p; fixed_t i; - boolean mathlib = lua_toboolean(L, lua_upvalueindex(1)); - if (lua_type(L,2) != LUA_TSTRING) - return 0; - word = lua_tostring(L,2); + if (strlen(word) == 1) { // Assume sprite frame if length 1. if (*word >= 'A' && *word <= '~') { - lua_pushinteger(L, *word-'A'); + CacheAndPushConstant(L, word, *word-'A'); return 1; } if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word); @@ -237,7 +235,7 @@ static inline int lib_getenum(lua_State *L) p = word+3; for (i = 0; MOBJFLAG_LIST[i]; i++) if (fastcmp(p, MOBJFLAG_LIST[i])) { - lua_pushinteger(L, ((lua_Integer)1< Date: Tue, 25 Jan 2022 00:43:38 +0200 Subject: [PATCH 017/478] Fix Lua stack overflow in LUA_UpdateSprName --- src/deh_lua.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 0bd906c13..1f6a0659c 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -590,11 +590,12 @@ void LUA_UpdateSprName(const char *name, lua_Integer value) if (!lua_isnil(gL, -1)) { - lua_pop(gL, 1); lua_pushstring(gL, name); lua_pushinteger(gL, value); lua_rawset(gL, LUA_GLOBALSINDEX); } + + lua_pop(gL, 1); // pop the rawget result } int LUA_EnumLib(lua_State *L) From f5d4eb3e7aa6de763c2dda58800a2702a5da36e4 Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 31 Jan 2022 14:39:51 +0100 Subject: [PATCH 018/478] Turn F11 into a fullscreen toggle, and process it inside menus as well. --- src/m_menu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3c1d8d7ca..7d4e4b8ae 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1347,7 +1347,7 @@ static menuitem_t OP_VideoOptionsMenu[] = #endif {IT_HEADER, NULL, "Color Profile", NULL, 30}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness (F11)", &cv_globalgamma,36}, + {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness", &cv_globalgamma,36}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_globalsaturation, 41}, {IT_SUBMENU|IT_STRING, NULL, "Advanced Settings...", &OP_ColorOptionsDef, 46}, @@ -3399,8 +3399,8 @@ boolean M_Responder(event_t *ev) M_QuitSRB2(0); return true; - case KEY_F11: // Gamma Level - CV_AddValue(&cv_globalgamma, 1); + case KEY_F11: // Fullscreen toggle, also processed inside menus + CV_SetValue(&cv_fullscreen, !cv_fullscreen.value); return true; // Spymode on F12 handled in game logic @@ -3579,6 +3579,10 @@ boolean M_Responder(event_t *ev) // M_SetupNextMenu(currentMenu->prevMenu); return false; + case KEY_F11: // Fullscreen toggle, also processed outside menus + CV_SetValue(&cv_fullscreen, !cv_fullscreen.value); + return true; + default: CON_Responder(ev); break; From 020ce6a1ddda6d185ade732197c165f99a2c4931 Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 31 Jan 2022 14:40:41 +0100 Subject: [PATCH 019/478] Rudimentary support for separate fullscreen/windowed resolutions. --- src/d_netcmd.c | 4 ++++ src/screen.c | 9 ++++++++- src/screen.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index fe7e7678f..4ad6c8c51 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -872,6 +872,10 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_height); + CV_RegisterVar(&cv_usewindowedres); + CV_RegisterVar(&cv_scr_width_w); + CV_RegisterVar(&cv_scr_height_w); + CV_RegisterVar(&cv_soundtest); CV_RegisterVar(&cv_perfstats); diff --git a/src/screen.c b/src/screen.c index 770f1c802..19e6bf1bd 100644 --- a/src/screen.c +++ b/src/screen.c @@ -69,6 +69,10 @@ consvar_t cv_scr_height = CVAR_INIT ("scr_height", "800", CV_SAVE, CV_Unsigned, consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); +consvar_t cv_usewindowedres = CVAR_INIT ("usewindowedres", "No", CV_SAVE, CV_YesNo, NULL); +consvar_t cv_scr_width_w = CVAR_INIT ("scr_width_w", "640", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_scr_height_w = CVAR_INIT ("scr_height_w", "400", CV_SAVE, CV_Unsigned, NULL); + CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER @@ -405,7 +409,10 @@ void SCR_ChangeFullscreen(void) if (graphics_started) { VID_PrepareModeList(); - setmodeneeded = VID_GetModeForSize(vid.width, vid.height) + 1; + if (cv_usewindowedres.value == 1 && cv_fullscreen.value == 0) + setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; + else + setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; } return; #endif diff --git a/src/screen.h b/src/screen.h index 67880e2b9..3077973d2 100644 --- a/src/screen.h +++ b/src/screen.h @@ -190,6 +190,7 @@ extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen; +extern consvar_t cv_scr_width_w, cv_scr_height_w, cv_usewindowedres; // wait for page flipping to end or not extern consvar_t cv_vidwait; From 0cfc75070d92fa9e636a0e970c813d7d25bf1e11 Mon Sep 17 00:00:00 2001 From: spherallic Date: Fri, 4 Feb 2022 14:42:10 +0100 Subject: [PATCH 020/478] Improved support for separate resolutions: - Windowed mode resolution can now be changed via the resolutions menu. - F11 can also be used while in this menu. - Removed usewindowedres cvar for ease of use. - When starting in windowed mode, use the correct resolution. --- src/d_netcmd.c | 2 -- src/m_menu.c | 16 ++++++++++++---- src/screen.c | 35 +++++++++++++++++++++++------------ src/screen.h | 4 ++-- 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4ad6c8c51..eda70a170 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -871,8 +871,6 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); CV_RegisterVar(&cv_scr_height); - - CV_RegisterVar(&cv_usewindowedres); CV_RegisterVar(&cv_scr_width_w); CV_RegisterVar(&cv_scr_height_w); diff --git a/src/m_menu.c b/src/m_menu.c index 7d4e4b8ae..f07dffe5c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1337,13 +1337,13 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_STRING | IT_CALL, NULL, "Set Resolution...", M_VideoModeMenu, 6}, #if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 11}, + {IT_STRING|IT_CVAR, NULL, "Fullscreen (F11)", &cv_fullscreen, 11}, #endif {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16}, #ifdef HWRENDER {IT_STRING | IT_CVAR, NULL, "Renderer", &cv_renderer, 21}, #else - {IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 21}, + {IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 21}, #endif {IT_HEADER, NULL, "Color Profile", NULL, 30}, @@ -13217,14 +13217,18 @@ static void M_DrawVideoMode(void) } else { - M_CentreText(OP_VideoModeDef.y + 116, + M_CentreText(OP_VideoModeDef.y + 100, va("Current mode is %c%dx%d", (SCR_IsAspectCorrect(vid.width, vid.height)) ? 0x83 : 0x80, vid.width, vid.height)); - M_CentreText(OP_VideoModeDef.y + 124, + M_CentreText(OP_VideoModeDef.y + 116, va("Default mode is %c%dx%d", (SCR_IsAspectCorrect(cv_scr_width.value, cv_scr_height.value)) ? 0x83 : 0x80, cv_scr_width.value, cv_scr_height.value)); + M_CentreText(OP_VideoModeDef.y + 124, + va("Windowed mode is %c%dx%d", + (SCR_IsAspectCorrect(cv_scr_width_w.value, cv_scr_height_w.value)) ? 0x83 : 0x80, + cv_scr_width_w.value, cv_scr_height_w.value)); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 138, V_GREENMAP, "Green modes are recommended."); @@ -13438,6 +13442,10 @@ static void M_HandleVideoMode(INT32 ch) M_ClearMenus(true); break; + case KEY_F11: + CV_SetValue(&cv_fullscreen, !cv_fullscreen.value); + break; + default: break; } diff --git a/src/screen.c b/src/screen.c index 19e6bf1bd..96e436193 100644 --- a/src/screen.c +++ b/src/screen.c @@ -66,12 +66,10 @@ static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, //added : 03-02-98: default screen mode, as loaded/saved in config consvar_t cv_scr_width = CVAR_INIT ("scr_width", "1280", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_scr_height = CVAR_INIT ("scr_height", "800", CV_SAVE, CV_Unsigned, NULL); -consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); -consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); - -consvar_t cv_usewindowedres = CVAR_INIT ("usewindowedres", "No", CV_SAVE, CV_YesNo, NULL); consvar_t cv_scr_width_w = CVAR_INIT ("scr_width_w", "640", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_scr_height_w = CVAR_INIT ("scr_height_w", "400", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); +consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, @@ -370,10 +368,16 @@ void SCR_CheckDefaultMode(void) } else { - CONS_Printf(M_GetText("Default resolution: %d x %d (%d bits)\n"), cv_scr_width.value, - cv_scr_height.value, cv_scr_depth.value); - // see note above - setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; + if (cv_fullscreen.value == 0) + { + CONS_Printf(M_GetText("Default windowed resolution: %d x %d (%d bits)\n"), cv_scr_width_w.value, cv_scr_height_w.value, cv_scr_depth.value); + setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; // see note above + } + else + { + CONS_Printf(M_GetText("Default resolution: %d x %d (%d bits)\n"), cv_scr_width.value, cv_scr_height.value, cv_scr_depth.value); + setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; // see note above + } } if (cv_renderer.value != (signed)rendermode) @@ -392,9 +396,16 @@ void SCR_CheckDefaultMode(void) void SCR_SetDefaultMode(void) { // remember the default screen size - CV_SetValue(&cv_scr_width, vid.width); - CV_SetValue(&cv_scr_height, vid.height); - CV_SetValue(&cv_scr_depth, vid.bpp*8); + if (cv_fullscreen.value == 0) + { + CV_SetValue(&cv_scr_width_w, vid.width); + CV_SetValue(&cv_scr_height_w, vid.height); + } + else + { + CV_SetValue(&cv_scr_width, vid.width); + CV_SetValue(&cv_scr_height, vid.height); + } } // Change fullscreen on/off according to cv_fullscreen @@ -409,7 +420,7 @@ void SCR_ChangeFullscreen(void) if (graphics_started) { VID_PrepareModeList(); - if (cv_usewindowedres.value == 1 && cv_fullscreen.value == 0) + if (cv_fullscreen.value == 0) setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; else setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; diff --git a/src/screen.h b/src/screen.h index 3077973d2..30582793f 100644 --- a/src/screen.h +++ b/src/screen.h @@ -189,8 +189,8 @@ extern CV_PossibleValue_t cv_renderer_t[]; extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders -extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen; -extern consvar_t cv_scr_width_w, cv_scr_height_w, cv_usewindowedres; +extern consvar_t cv_scr_width, cv_scr_height, cv_scr_width_w, cv_scr_height_w, cv_scr_depth, cv_fullscreen; +extern consvar_t cv_renderview, cv_renderer; // wait for page flipping to end or not extern consvar_t cv_vidwait; From 5fdc0b889bfc5c9429911c5c42d6a1209fc637ec Mon Sep 17 00:00:00 2001 From: spherallic Date: Fri, 4 Feb 2022 14:50:45 +0100 Subject: [PATCH 021/478] Replace F10's near-useless game quit option with a renderer toggle. --- src/m_menu.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f07dffe5c..b54baa9dd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1341,7 +1341,7 @@ static menuitem_t OP_VideoOptionsMenu[] = #endif {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16}, #ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "Renderer", &cv_renderer, 21}, + {IT_STRING | IT_CVAR, NULL, "Renderer (F10)", &cv_renderer, 21}, #else {IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 21}, #endif @@ -3395,8 +3395,11 @@ boolean M_Responder(event_t *ev) // Screenshots on F8 now handled elsewhere // Same with Moviemode on F9 - case KEY_F10: // Quit SRB2 - M_QuitSRB2(0); + case KEY_F10: // Renderer toggle, also processed inside menus + if (cv_renderer.value == render_soft) + CV_SetValue(&cv_renderer, render_opengl); + else if (cv_renderer.value == render_opengl) + CV_SetValue(&cv_renderer, render_soft); return true; case KEY_F11: // Fullscreen toggle, also processed inside menus @@ -3579,6 +3582,13 @@ boolean M_Responder(event_t *ev) // M_SetupNextMenu(currentMenu->prevMenu); return false; + case KEY_F10: // Renderer toggle, also processed outside menus + if (cv_renderer.value == render_soft) + CV_SetValue(&cv_renderer, render_opengl); + else if (cv_renderer.value == render_opengl) + CV_SetValue(&cv_renderer, render_soft); + return true; + case KEY_F11: // Fullscreen toggle, also processed outside menus CV_SetValue(&cv_fullscreen, !cv_fullscreen.value); return true; From 599644e885b9624eb72aecfe67b11939a8f4af46 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 5 Feb 2022 11:32:48 +0100 Subject: [PATCH 022/478] Update resolutions menu, remove M_CentreText. --- src/m_menu.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index b54baa9dd..c034aee48 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4228,15 +4228,6 @@ static void M_DrawSaveLoadBorder(INT32 x,INT32 y) } #endif -// horizontally centered text -static void M_CentreText(INT32 y, const char *string) -{ - INT32 x; - //added : 02-02-98 : centre on 320, because V_DrawString centers on vid.width... - x = (BASEVIDWIDTH - V_StringWidth(string, V_OLDSPACING))>>1; - V_DrawString(x,y,V_OLDSPACING,string); -} - // // M_DrawMapEmblems // @@ -12818,12 +12809,12 @@ static void M_DrawControl(void) if (tutorialmode && tutorialgcs) { if ((gametic / TICRATE) % 2) - M_CentreText(30, "\202EXIT THE TUTORIAL TO CHANGE THE CONTROLS"); + V_DrawCenteredString(BASEVIDWIDTH/2, 30, 0, "\202EXIT THE TUTORIAL TO CHANGE THE CONTROLS"); else - M_CentreText(30, "EXIT THE TUTORIAL TO CHANGE THE CONTROLS"); + V_DrawCenteredString(BASEVIDWIDTH/2, 30, 0, "EXIT THE TUTORIAL TO CHANGE THE CONTROLS"); } else - M_CentreText(30, + V_DrawCenteredString(BASEVIDWIDTH/2, 30, 0, (setupcontrols_secondaryplayer ? "SET CONTROLS FOR SECONDARY PLAYER" : "PRESS ENTER TO CHANGE, BACKSPACE TO CLEAR")); @@ -13188,11 +13179,11 @@ static void M_DrawVideoMode(void) // draw title M_DrawMenuTitle(); - V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y, - V_YELLOWMAP, "Choose mode, reselect to change default"); + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y, V_YELLOWMAP, "Choose mode, reselect to change default"); + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y+8, V_YELLOWMAP, "Press F11 to toggle fullscreen"); row = 41; - col = OP_VideoModeDef.y + 14; + col = OP_VideoModeDef.y + 24; for (i = 0; i < vidm_nummodes; i++) { if (i == vidm_selected) @@ -13205,7 +13196,7 @@ static void M_DrawVideoMode(void) if ((i % vidm_column_size) == (vidm_column_size-1)) { row += 7*13; - col = OP_VideoModeDef.y + 14; + col = OP_VideoModeDef.y + 24; } } @@ -13213,29 +13204,31 @@ static void M_DrawVideoMode(void) { INT32 testtime = (vidm_testingmode/TICRATE) + 1; - M_CentreText(OP_VideoModeDef.y + 116, + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 116, 0, va("Previewing mode %c%dx%d", (SCR_IsAspectCorrect(vid.width, vid.height)) ? 0x83 : 0x80, vid.width, vid.height)); - M_CentreText(OP_VideoModeDef.y + 138, + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 138, 0, "Press ENTER again to keep this mode"); - M_CentreText(OP_VideoModeDef.y + 150, + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 150, 0, va("Wait %d second%s", testtime, (testtime > 1) ? "s" : "")); - M_CentreText(OP_VideoModeDef.y + 158, + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 158, 0, "or press ESC to return"); - } else { - M_CentreText(OP_VideoModeDef.y + 100, + V_DrawFill(60, OP_VideoModeDef.y + 98, 200, 12, 159); + V_DrawFill(60, OP_VideoModeDef.y + 114, 200, 20, 159); + + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 100, 0, va("Current mode is %c%dx%d", (SCR_IsAspectCorrect(vid.width, vid.height)) ? 0x83 : 0x80, vid.width, vid.height)); - M_CentreText(OP_VideoModeDef.y + 116, + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 116, (cv_fullscreen.value ? 0 : V_TRANSLUCENT), va("Default mode is %c%dx%d", (SCR_IsAspectCorrect(cv_scr_width.value, cv_scr_height.value)) ? 0x83 : 0x80, cv_scr_width.value, cv_scr_height.value)); - M_CentreText(OP_VideoModeDef.y + 124, + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 124, (cv_fullscreen.value ? V_TRANSLUCENT : 0), va("Windowed mode is %c%dx%d", (SCR_IsAspectCorrect(cv_scr_width_w.value, cv_scr_height_w.value)) ? 0x83 : 0x80, cv_scr_width_w.value, cv_scr_height_w.value)); @@ -13250,7 +13243,7 @@ static void M_DrawVideoMode(void) // Draw the cursor for the VidMode menu i = 41 - 10 + ((vidm_selected / vidm_column_size)*7*13); - j = OP_VideoModeDef.y + 14 + ((vidm_selected % vidm_column_size)*8); + j = OP_VideoModeDef.y + 24 + ((vidm_selected % vidm_column_size)*8); V_DrawScaledPatch(i - 8, j, 0, W_CachePatchName("M_CURSOR", PU_PATCH)); @@ -13433,11 +13426,14 @@ static void M_HandleVideoMode(INT32 ch) break; case KEY_ENTER: - S_StartSound(NULL, sfx_menu1); if (vid.modenum == modedescs[vidm_selected].modenum) + { + S_StartSound(NULL, sfx_strpst); SCR_SetDefaultMode(); + } else { + S_StartSound(NULL, sfx_menu1); vidm_testingmode = 15*TICRATE; vidm_previousmode = vid.modenum; if (!setmodeneeded) // in case the previous setmode was not finished @@ -13453,6 +13449,7 @@ static void M_HandleVideoMode(INT32 ch) break; case KEY_F11: + S_StartSound(NULL, sfx_menu1); CV_SetValue(&cv_fullscreen, !cv_fullscreen.value); break; From 35f2937fd114d16cf3e5374fa80c1dcca1220fb4 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 6 Feb 2022 16:13:45 +0100 Subject: [PATCH 023/478] Minor code cleanup & remove some unneeded resolution info from logs. --- src/screen.c | 34 +++++++++++----------------------- src/sdl/i_video.c | 4 ++-- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/screen.c b/src/screen.c index 96e436193..f21ea2a93 100644 --- a/src/screen.c +++ b/src/screen.c @@ -368,16 +368,13 @@ void SCR_CheckDefaultMode(void) } else { - if (cv_fullscreen.value == 0) - { - CONS_Printf(M_GetText("Default windowed resolution: %d x %d (%d bits)\n"), cv_scr_width_w.value, cv_scr_height_w.value, cv_scr_depth.value); - setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; // see note above - } - else - { - CONS_Printf(M_GetText("Default resolution: %d x %d (%d bits)\n"), cv_scr_width.value, cv_scr_height.value, cv_scr_depth.value); + CONS_Printf(M_GetText("Default resolution: %d x %d\n"), cv_scr_width.value, cv_scr_height.value); + CONS_Printf(M_GetText("Windowed resolution: %d x %d\n"), cv_scr_width_w.value, cv_scr_height_w.value); + CONS_Printf(M_GetText("Default bit depth: %d bits\n"), cv_scr_depth.value); + if (cv_fullscreen.value) setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; // see note above - } + else + setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; // see note above } if (cv_renderer.value != (signed)rendermode) @@ -395,17 +392,8 @@ void SCR_CheckDefaultMode(void) // sets the modenum as the new default video mode to be saved in the config file void SCR_SetDefaultMode(void) { - // remember the default screen size - if (cv_fullscreen.value == 0) - { - CV_SetValue(&cv_scr_width_w, vid.width); - CV_SetValue(&cv_scr_height_w, vid.height); - } - else - { - CV_SetValue(&cv_scr_width, vid.width); - CV_SetValue(&cv_scr_height, vid.height); - } + CV_SetValue(cv_fullscreen.value ? &cv_scr_width : &cv_scr_width_w, vid.width); + CV_SetValue(cv_fullscreen.value ? &cv_scr_height : &cv_scr_height_w, vid.height); } // Change fullscreen on/off according to cv_fullscreen @@ -420,10 +408,10 @@ void SCR_ChangeFullscreen(void) if (graphics_started) { VID_PrepareModeList(); - if (cv_fullscreen.value == 0) - setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; - else + if (cv_fullscreen.value) setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; + else + setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; } return; #endif diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index ed766ff23..1642695d0 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1795,7 +1795,7 @@ void I_StartupGraphics(void) borderlesswindow = M_CheckParm("-borderless"); //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); - VID_Command_ModeList_f(); + //VID_Command_ModeList_f(); #ifdef HWRENDER if (rendermode == render_opengl) @@ -1843,7 +1843,7 @@ void I_StartupGraphics(void) realwidth = (Uint16)vid.width; realheight = (Uint16)vid.height; - VID_Command_Info_f(); + //VID_Command_Info_f(); SDLdoUngrabMouse(); SDL_RaiseWindow(window); From dcdbdec2bf8fffbc4b2d99ac89612cb9516cfcb9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 6 Feb 2022 15:16:30 -0500 Subject: [PATCH 024/478] Make super for A_Actions act as described --- src/deh_lua.c | 61 +++++++++++++++++++++++++++++++------------- src/deh_tables.h | 1 + src/dehacked.h | 5 ++-- src/info.h | 3 ++- src/lua_infolib.c | 64 ++++++++++++++++++++++++++++++++++------------- src/lua_script.c | 14 ++++++++++- 6 files changed, 109 insertions(+), 39 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index a2ffca95b..43e25a49d 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -195,25 +195,32 @@ static inline int lib_freeslot(lua_State *L) // Arguments: mobj_t actor, int var1, int var2 static int action_call(lua_State *L) { - //actionf_t *action = lua_touserdata(L,lua_upvalueindex(1)); actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + var1 = (INT32)luaL_optinteger(L, 3, 0); var2 = (INT32)luaL_optinteger(L, 4, 0); + if (!actor) + { return LUA_ErrInvalid(L, "mobj_t"); + } + action->acp1(actor); return 0; } // Hardcoded A_Action name to call for super() or NULL if super() would be invalid. // Set in lua_infolib. -const char *superactions[MAXRECURSION]; +const char *luaactions[MAX_ACTION_RECURSION]; +UINT8 luaactionstack = 0; UINT8 superstack = 0; static int lib_dummysuper(lua_State *L) { - return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;; + // TODO: Now that the restriction on only being allowed in state changes was lifted, + // it'd be nice to have super extend to Lua A_ functions too :) + return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions!"); } static inline int lib_getenum(lua_State *L) @@ -500,42 +507,62 @@ static inline int lib_getenum(lua_State *L) } else if (!mathlib && fastncmp("A_",word,2)) { char *caps; - // Try to get a Lua action first. - /// \todo Push a closure that sets superactions[] and superstack. + + // Hardcoded actions come first. + // Trying to call them will invoke LUA_CallAction, which will handle super properly. + // Retrieving them from this metatable allows them to be case-insensitive! + for (i = 0; actionpointers[i].name; i++) + { + if (fasticmp(word, actionpointers[i].name)) + { + // We push the actionf_t* itself as userdata! + LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION); + return 1; + } + } + + // Now try to get Lua actions. + /// \todo Push a closure that sets luaactions[] and luaactionstack. + /// This would be part one of a step to get super functions working for custom A_ functions. + /// Custom functions. lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS); + // actions are stored in all uppercase. caps = Z_StrDup(word); strupr(caps); lua_getfield(L, -1, caps); Z_Free(caps); + if (!lua_isnil(L, -1)) + { return 1; // Success! :D That was easy. + } + // Welp, that failed. lua_pop(L, 2); // pop nil and LREG_ACTIONS - - // Hardcoded actions as callable Lua functions! - // Retrieving them from this metatable allows them to be case-insensitive! - for (i = 0; actionpointers[i].name; i++) - if (fasticmp(word, actionpointers[i].name)) { - // We push the actionf_t* itself as userdata! - LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION); - return 1; - } return 0; } else if (!mathlib && fastcmp("super",word)) { - if (!superstack) + if (!luaactionstack) { + // Not in A_ action routine lua_pushcfunction(L, lib_dummysuper); return 1; } + for (i = 0; actionpointers[i].name; i++) - if (fasticmp(superactions[superstack-1], actionpointers[i].name)) { + { + if (fasticmp(luaactions[luaactionstack-1], actionpointers[i].name)) + { LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION); return 1; } - return 0; + } + + // Not a hardcoded A_ action. + lua_pushcfunction(L, lib_dummysuper); + return 1; } if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release... diff --git a/src/deh_tables.h b/src/deh_tables.h index 1f265cc99..70347f7dd 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -30,6 +30,7 @@ extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\ memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\ memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\ + memset(actionsoverridden, LUA_REFNIL, sizeof(actionsoverridden));\ } struct flickytypes_s { diff --git a/src/dehacked.h b/src/dehacked.h index 1b200e246..e29aef6ff 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -40,8 +40,9 @@ extern boolean gamedataadded; extern boolean titlechanged; extern boolean introchanged; -#define MAXRECURSION 30 -extern const char *superactions[MAXRECURSION]; +#define MAX_ACTION_RECURSION 30 +extern const char *luaactions[MAX_ACTION_RECURSION]; +extern UINT8 luaactionstack; extern UINT8 superstack; // If the dehacked patch does not match this version, we throw a warning diff --git a/src/info.h b/src/info.h index 031a08b43..6e9460bec 100644 --- a/src/info.h +++ b/src/info.h @@ -18,6 +18,7 @@ #include "d_think.h" #include "sounds.h" #include "m_fixed.h" +#include "dehacked.h" // MAX_ACTION_RECURSION // deh_tables.c now has lists for the more named enums! PLEASE keep them up to date! // For great modding!! @@ -554,7 +555,7 @@ void A_DragonWing(); void A_DragonSegment(); void A_ChangeHeight(); -extern boolean actionsoverridden[NUMACTIONS]; +extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION]; // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 512 diff --git a/src/lua_infolib.c b/src/lua_infolib.c index af2d99a0c..e20202495 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -66,7 +66,7 @@ const char *const sfxinfo_wopt[] = { "caption", NULL}; -boolean actionsoverridden[NUMACTIONS] = {false}; +int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION]; // // Sprite Names @@ -645,8 +645,8 @@ static void A_Lua(mobj_t *actor) if (lua_rawequal(gL, -1, -4)) { found = true; - superactions[superstack] = lua_tostring(gL, -2); // "A_ACTION" - ++superstack; + luaactions[luaactionstack] = lua_tostring(gL, -2); // "A_ACTION" + ++luaactionstack; lua_pop(gL, 2); // pop the name and function break; } @@ -661,8 +661,8 @@ static void A_Lua(mobj_t *actor) if (found) { - --superstack; - superactions[superstack] = NULL; + --luaactionstack; + luaactions[luaactionstack] = NULL; } } @@ -816,18 +816,46 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) { I_Assert(actor != NULL); - if (!actionsoverridden[actionnum]) // The action is not overriden, - return false; // action not called. + if (actionsoverridden[actionnum][0] == LUA_REFNIL) + { + // The action was not overridden at all, + // so call the hardcoded version. + return false; + } - if (superstack && fasticmp(actionpointers[actionnum].name, superactions[superstack-1])) // the action is calling itself, - return false; // let it call the hardcoded function instead. + if (luaactionstack && fasticmp(actionpointers[actionnum].name, luaactions[luaactionstack-1])) + { + // The action is calling itself, + // so look up the next Lua reference in its stack. + // 0 is just the reference to the one we're calling, + // so we increment here. + superstack++; + + if (superstack >= MAX_ACTION_RECURSION) + { + CONS_Alert(CONS_WARNING, "Max Lua super recursion reached! Cool it on calling super!\n"); + return false; + } + } + else + { + // Not calling itself, reset the super counter. + superstack = 0; + } + + if (actionsoverridden[actionnum][superstack] == LUA_REFNIL) + { + // No Lua reference beyond this point. + // Let it call the hardcoded function instead. + return false; + } + + // Push error function lua_pushcfunction(gL, LUA_GetErrorMessage); - // grab function by uppercase name. - lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS); - lua_getfield(gL, -1, actionpointers[actionnum].name); - lua_remove(gL, -2); // pop LREG_ACTIONS + // Push function by reference. + lua_getref(gL, actionsoverridden[actionnum][superstack]); if (lua_isnil(gL, -1)) // no match { @@ -835,7 +863,7 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) return false; // action not called. } - if (superstack == MAXRECURSION) + if (luaactionstack >= MAX_ACTION_RECURSION) { CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n"); lua_pop(gL, 2); // pop function and error handler @@ -849,14 +877,14 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) lua_pushinteger(gL, var1); lua_pushinteger(gL, var2); - superactions[superstack] = actionpointers[actionnum].name; - ++superstack; + luaactions[luaactionstack] = actionpointers[actionnum].name; + ++luaactionstack; LUA_Call(gL, 3, 0, -(2 + 3)); lua_pop(gL, -1); // Error handler - --superstack; - superactions[superstack] = NULL; + --luaactionstack; + luaactions[luaactionstack] = NULL; return true; // action successfully called. } diff --git a/src/lua_script.c b/src/lua_script.c index a1376ca2e..5441d315e 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -485,7 +485,19 @@ static int setglobals(lua_State *L) actionnum = LUA_GetActionNumByName(name); if (actionnum < NUMACTIONS) - actionsoverridden[actionnum] = true; + { + int i; + + for (i = MAX_ACTION_RECURSION-1; i > 0; i--) + { + // Move other references deeper. + actionsoverridden[actionnum][i] = actionsoverridden[actionnum][i - 1]; + } + + // Add the new reference. + lua_pushvalue(L, 2); + actionsoverridden[actionnum][0] = luaL_ref(L, LUA_REGISTRYINDEX); + } Z_Free(name); return 0; From c53f57a22fcf5e26164c41b29ba5be8e675d82a9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 6 Feb 2022 18:31:10 -0500 Subject: [PATCH 025/478] Handle super stack more intelligently Counted per action type, and it is decremented after the function is called instead of keeping its old value or even resetting completely when using multiple actions together. --- src/deh_lua.c | 1 - src/dehacked.h | 1 - src/lua_infolib.c | 30 ++++++++++++++++++++---------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 43e25a49d..62a1717a8 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -214,7 +214,6 @@ static int action_call(lua_State *L) // Set in lua_infolib. const char *luaactions[MAX_ACTION_RECURSION]; UINT8 luaactionstack = 0; -UINT8 superstack = 0; static int lib_dummysuper(lua_State *L) { diff --git a/src/dehacked.h b/src/dehacked.h index e29aef6ff..bf4d5c121 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -43,7 +43,6 @@ extern boolean introchanged; #define MAX_ACTION_RECURSION 30 extern const char *luaactions[MAX_ACTION_RECURSION]; extern UINT8 luaactionstack; -extern UINT8 superstack; // If the dehacked patch does not match this version, we throw a warning #define PATCHVERSION 220 diff --git a/src/lua_infolib.c b/src/lua_infolib.c index e20202495..ad7bc7b6f 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -812,6 +812,7 @@ boolean LUA_SetLuaAction(void *stv, const char *action) return true; // action successfully set. } +static UINT8 superstack[NUMACTIONS]; boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) { I_Assert(actor != NULL); @@ -819,7 +820,7 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) if (actionsoverridden[actionnum][0] == LUA_REFNIL) { // The action was not overridden at all, - // so call the hardcoded version. + // so just call the hardcoded version. return false; } @@ -830,24 +831,27 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) // 0 is just the reference to the one we're calling, // so we increment here. - superstack++; + superstack[actionnum]++; - if (superstack >= MAX_ACTION_RECURSION) + if (superstack[actionnum] >= MAX_ACTION_RECURSION) { CONS_Alert(CONS_WARNING, "Max Lua super recursion reached! Cool it on calling super!\n"); + superstack[actionnum] = 0; return false; } } - else - { - // Not calling itself, reset the super counter. - superstack = 0; - } - if (actionsoverridden[actionnum][superstack] == LUA_REFNIL) + if (actionsoverridden[actionnum][superstack[actionnum]] == LUA_REFNIL) { // No Lua reference beyond this point. // Let it call the hardcoded function instead. + + if (superstack[actionnum]) + { + // Decrement super stack + superstack[actionnum]--; + } + return false; } @@ -855,7 +859,7 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) lua_pushcfunction(gL, LUA_GetErrorMessage); // Push function by reference. - lua_getref(gL, actionsoverridden[actionnum][superstack]); + lua_getref(gL, actionsoverridden[actionnum][superstack[actionnum]]); if (lua_isnil(gL, -1)) // no match { @@ -883,6 +887,12 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor) LUA_Call(gL, 3, 0, -(2 + 3)); lua_pop(gL, -1); // Error handler + if (superstack[actionnum]) + { + // Decrement super stack + superstack[actionnum]--; + } + --luaactionstack; luaactions[luaactionstack] = NULL; return true; // action successfully called. From 7d1faf7e2c0f4db8c4d953dd40f7b899b4bfadef Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 19 Feb 2022 12:12:04 +0100 Subject: [PATCH 026/478] Handle invalid resolutions, make Backspace work in resolution menu. --- src/m_menu.c | 16 ++++++++++++++-- src/screen.c | 9 +++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index c034aee48..220d67a3f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -13226,11 +13226,11 @@ static void M_DrawVideoMode(void) vid.width, vid.height)); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 116, (cv_fullscreen.value ? 0 : V_TRANSLUCENT), va("Default mode is %c%dx%d", - (SCR_IsAspectCorrect(cv_scr_width.value, cv_scr_height.value)) ? 0x83 : 0x80, + (SCR_IsAspectCorrect(cv_scr_width.value, cv_scr_height.value)) ? 0x83 : (!(VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value)+1) ? 0x85 : 0x80), cv_scr_width.value, cv_scr_height.value)); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 124, (cv_fullscreen.value ? V_TRANSLUCENT : 0), va("Windowed mode is %c%dx%d", - (SCR_IsAspectCorrect(cv_scr_width_w.value, cv_scr_height_w.value)) ? 0x83 : 0x80, + (SCR_IsAspectCorrect(cv_scr_width_w.value, cv_scr_height_w.value)) ? 0x83 : (!(VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value)+1) ? 0x85 : 0x80), cv_scr_width_w.value, cv_scr_height_w.value)); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 138, @@ -13448,6 +13448,18 @@ static void M_HandleVideoMode(INT32 ch) M_ClearMenus(true); break; + case KEY_BACKSPACE: + S_StartSound(NULL, sfx_menu1); + CV_Set(&cv_scr_width, cv_scr_width.defaultvalue); + CV_Set(&cv_scr_height, cv_scr_height.defaultvalue); + CV_Set(&cv_scr_width_w, cv_scr_width_w.defaultvalue); + CV_Set(&cv_scr_height_w, cv_scr_height_w.defaultvalue); + if (cv_fullscreen.value) + setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value)+1; + else + setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value)+1; + break; + case KEY_F11: S_StartSound(NULL, sfx_menu1); CV_SetValue(&cv_fullscreen, !cv_fullscreen.value); diff --git a/src/screen.c b/src/screen.c index f21ea2a93..3a548bece 100644 --- a/src/screen.c +++ b/src/screen.c @@ -375,6 +375,9 @@ void SCR_CheckDefaultMode(void) setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; // see note above else setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; // see note above + + if (setmodeneeded <= 0) + CONS_Alert(CONS_WARNING, "Invalid resolution given, defaulting to base resolution\n"); } if (cv_renderer.value != (signed)rendermode) @@ -412,6 +415,12 @@ void SCR_ChangeFullscreen(void) setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; else setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value) + 1; + + if (setmodeneeded <= 0) // hacky safeguard + { + CONS_Alert(CONS_WARNING, "Invalid resolution given, defaulting to base resolution.\n"); + setmodeneeded = VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT) + 1; + } } return; #endif From f077021591132c3e9c565169e70e030bd378bbf0 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 19 Feb 2022 15:15:06 +0100 Subject: [PATCH 027/478] Clean up renderer toggle at SteelT's suggestion. --- src/m_menu.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 220d67a3f..c3c7db923 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3396,10 +3396,7 @@ boolean M_Responder(event_t *ev) // Same with Moviemode on F9 case KEY_F10: // Renderer toggle, also processed inside menus - if (cv_renderer.value == render_soft) - CV_SetValue(&cv_renderer, render_opengl); - else if (cv_renderer.value == render_opengl) - CV_SetValue(&cv_renderer, render_soft); + CV_AddValue(&cv_renderer, 1); return true; case KEY_F11: // Fullscreen toggle, also processed inside menus @@ -3583,10 +3580,7 @@ boolean M_Responder(event_t *ev) return false; case KEY_F10: // Renderer toggle, also processed outside menus - if (cv_renderer.value == render_soft) - CV_SetValue(&cv_renderer, render_opengl); - else if (cv_renderer.value == render_opengl) - CV_SetValue(&cv_renderer, render_soft); + CV_AddValue(&cv_renderer, 1); return true; case KEY_F11: // Fullscreen toggle, also processed outside menus From f7b166da07d821c655cc804111d419ab3c14c694 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 27 Feb 2022 07:56:45 -0500 Subject: [PATCH 028/478] Refresh sprite2s Allows for custom characters to be loaded first, then a wad that adds a custom sprite2, and the custom character's sprite2s won't be discarded. --- src/deh_lua.c | 3 + src/deh_soc.c | 2 + src/r_skins.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/r_skins.h | 2 + 4 files changed, 158 insertions(+), 5 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index a2ffca95b..7984a38c8 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -188,6 +188,9 @@ static inline int lib_freeslot(lua_State *L) lua_remove(L, 1); continue; } + + R_RefreshSprite2(); + return r; } diff --git a/src/deh_soc.c b/src/deh_soc.c index 3a611f3ba..dd33594ea 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -513,6 +513,8 @@ void readfreeslots(MYFILE *f) } while (!myfeof(f)); // finish when the line is empty Z_Free(s); + + R_RefreshSprite2(); } void readthing(MYFILE *f, INT32 num) diff --git a/src/r_skins.c b/src/r_skins.c index 86c0bbc54..010280403 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -499,7 +499,7 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) return INT16_MAX; // not found } -static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin) +static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT8 start_spr2) { UINT16 newlastlump; UINT8 sprite2; @@ -521,7 +521,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski { newlastlump++; // load all sprite sets we are aware of... for super! - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); newlastlump--; @@ -529,7 +529,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski } // load all sprite sets we are aware of... for normal stuff. - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); if (skin->sprites[0].numframes == 0) @@ -795,7 +795,7 @@ next_token: free(buf2); // Add sprites - R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin, 0); //ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere R_FlushTranslationColormapCache(); @@ -928,7 +928,7 @@ next_token: } // Patch sprites - R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin, 0); //ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere R_FlushTranslationColormapCache(); @@ -941,3 +941,149 @@ next_token: #undef HUDNAMEWRITE #undef SYMBOLCONVERT + +static UINT16 W_CheckForEitherSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + const char *S_SKIN = "S_SKIN"; + const char *P_SKIN = "P_SKIN"; + lumpinfo_t *lump_p; + + // scan forward, start at + if (startlump < wadfiles[wadid]->numlumps) + { + lump_p = wadfiles[wadid]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name,S_SKIN,6)==0 || memcmp(lump_p->name,P_SKIN,6)==0) + return i; + } + return INT16_MAX; // not found +} + +static void R_RefreshSprite2ForWad(UINT16 wadnum, UINT8 start_spr2) +{ + UINT16 lump, lastlump = 0; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean noskincomplain; + + // + // search for all skin patch markers in pwad + // + + while ((lump = W_CheckForEitherSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + { + INT32 skinnum = 0; + + // advance by default + lastlump = lump + 1; + + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("R_RefreshSprite2ForWad: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + skin = NULL; + noskincomplain = false; + + /* + Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation) + */ + + stoken = strtok(buf2, "\r\n= "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); // skip end of line + goto next_token; // find the real next token + } + + value = strtok(NULL, "\r\n= "); + + if (!value) + I_Error("R_RefreshSprite2ForWad: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + if (!stricmp(stoken, "name")) + { + strlwr(value); + skinnum = R_SkinAvailable(value); + if (skinnum != -1) + skin = &skins[skinnum]; + else + { + CONS_Debug(DBG_SETUP, "R_RefreshSprite2ForWad: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + noskincomplain = true; + } + } + + if (!skin) + break; + +next_token: + stoken = strtok(NULL, "\r\n= "); + } + free(buf2); + + if (!skin) // Didn't include a name parameter? What a waste. + { + if (!noskincomplain) + CONS_Debug(DBG_SETUP, "R_RefreshSprite2ForWad: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename); + continue; + } + + // Update sprites, in the range of (start_spr2 - free_spr2-1) + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin, start_spr2); + //R_FlushTranslationColormapCache(); // I don't think this is needed for what we're doing? + } +} + +static playersprite_t old_spr2 = SPR2_FIRSTFREESLOT; +void R_RefreshSprite2(void) +{ + // Sprite2s being defined by custom wads can create situations where + // a custom character might want to add support, but due to load order, + // might not be defined in time. + + // The trick where you load characters then level packs to keep savedata + // in particular will practically garantuee a level pack can NEVER add custom animations, + // because custom character's Sprite2s will not be added. + + // So, go through every file, and reload the sprite2s that were added. + + INT32 i; + + if (old_spr2 > free_spr2) + { +#ifdef PARANOIA + I_Error("R_RefreshSprite2: old_spr2 is too high?! (old_spr2: %d, free_spr2: %d)\n", old_spr2, free_spr2); +#else + // Just silently fix + old_spr2 = free_spr2; +#endif + } + + if (old_spr2 == free_spr2) + { + // No sprite2s were added since the last time we did freeslots. + return; + } + + for (i = 0; i < numwadfiles; i++) + { + R_RefreshSprite2ForWad(i, old_spr2); + } + + // Update previous value. + old_spr2 = free_spr2; +} diff --git a/src/r_skins.h b/src/r_skins.h index a38997f4d..2ef1bdd65 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -100,4 +100,6 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile); UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); +void R_RefreshSprite2(void); + #endif //__R_SKINS__ From 6a969c163b4f72b98c5d24d1eafe30e02045c044 Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 6 Apr 2022 15:31:25 +0200 Subject: [PATCH 029/478] Make boss 3's shockwave into a customizable action. --- src/deh_tables.c | 1 + src/info.h | 2 ++ src/p_enemy.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index 8dbe314cc..bed81e60c 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -198,6 +198,7 @@ actionpointer_t actionpointers[] = {{A_Boss3TakeDamage}, "A_BOSS3TAKEDAMAGE"}, {{A_Boss3Path}, "A_BOSS3PATH"}, {{A_Boss3ShockThink}, "A_BOSS3SHOCKTHINK"}, + {{A_Shockwave}, "A_SHOCKWAVE"}, {{A_LinedefExecute}, "A_LINEDEFEXECUTE"}, {{A_PlaySeeSound}, "A_PLAYSEESOUND"}, {{A_PlayAttackSound}, "A_PLAYATTACKSOUND"}, diff --git a/src/info.h b/src/info.h index 1b7a201ce..04c048dd8 100644 --- a/src/info.h +++ b/src/info.h @@ -151,6 +151,7 @@ enum actionnum A_BOSS3TAKEDAMAGE, A_BOSS3PATH, A_BOSS3SHOCKTHINK, + A_SHOCKWAVE, A_LINEDEFEXECUTE, A_PLAYSEESOUND, A_PLAYATTACKSOUND, @@ -414,6 +415,7 @@ void A_Boss1Spikeballs(); void A_Boss3TakeDamage(); void A_Boss3Path(); void A_Boss3ShockThink(); +void A_Shockwave(); void A_LinedefExecute(); void A_PlaySeeSound(); void A_PlayAttackSound(); diff --git a/src/p_enemy.c b/src/p_enemy.c index 87aa5ff2f..efa413a44 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -173,6 +173,7 @@ void A_Boss1Spikeballs(mobj_t *actor); void A_Boss3TakeDamage(mobj_t *actor); void A_Boss3Path(mobj_t *actor); void A_Boss3ShockThink(mobj_t *actor); +void A_Shockwave(mobj_t *actor); void A_LinedefExecute(mobj_t *actor); void A_PlaySeeSound(mobj_t *actor); void A_PlayAttackSound(mobj_t *actor); @@ -8326,6 +8327,56 @@ void A_Boss3ShockThink(mobj_t *actor) } } +// Function: A_Shockwave +// +// Description: Spawns a shockwave of objects. Best used to spawn objects that call A_Boss3ShockThink. +// +// var1 = object spawned +// var2 = amount of objects spawned +// +void A_Shockwave(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + INT32 i; + + angle_t ang = 0, interval; + mobj_t *shock = NULL, *sfirst = NULL, *sprev = NULL; + + if (LUA_CallAction(A_SHOCKWAVE, actor)) + return; + + if (locvar2 == 0) + locvar2 = 24; // a sensible default, just in case + + interval = FixedAngle((360 << FRACBITS) / locvar2); + + for (i = 0; i < locvar2; i++) + { + shock = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1); + P_SetTarget(&shock->target, actor); + shock->fuse = shock->info->painchance; + + if (i % 2 == 0) + P_SetMobjState(shock, shock->state->nextstate); + + if (!sprev) + sfirst = shock; + else + { + if (i == locvar2 - 1) + P_SetTarget(&shock->hnext, sfirst); + P_SetTarget(&sprev->hnext, shock); + } + + P_Thrust(shock, ang, shock->info->speed); + ang += interval; + sprev = shock; + } + + S_StartSound(actor, shock->info->seesound); +} + // Function: A_LinedefExecute // // Description: Object's location is used to set the calling sector. The tag used is var1. Optionally, if var2 is set, the actor's angle (multiplied by var2) is added to the tag number as well. From f564090c80c1ea54ebfebcdac0ea64618c5d0c6b Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 7 Sep 2022 14:00:56 +0200 Subject: [PATCH 030/478] Two small renderer switching changes: - Allow renderer switching in resolution menu - Fix "(F10)" suffix not being shown on the renderer option --- src/m_menu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index b527c4c1a..19c5eaeaf 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2157,7 +2157,7 @@ static void M_VideoOptions(INT32 choice) { OP_VideoOptionsMenu[op_video_renderer].status = (IT_STRING | IT_CVAR); OP_VideoOptionsMenu[op_video_renderer].patch = NULL; - OP_VideoOptionsMenu[op_video_renderer].text = "Renderer"; + OP_VideoOptionsMenu[op_video_renderer].text = "Renderer (F10)"; } #endif @@ -13456,6 +13456,10 @@ static void M_HandleVideoMode(INT32 ch) setmodeneeded = VID_GetModeForSize(cv_scr_width_w.value, cv_scr_height_w.value)+1; break; + case KEY_F10: // Renderer toggle, also processed inside menus + CV_AddValue(&cv_renderer, 1); + break; + case KEY_F11: S_StartSound(NULL, sfx_menu1); CV_SetValue(&cv_fullscreen, !cv_fullscreen.value); From 3da9fb636aebd8311e4119f7f6af65a924a0e0df Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 17 Sep 2022 10:51:16 +0200 Subject: [PATCH 031/478] Add plane scroller features to binary map format: - Added actions for scrolling floor + ceiling simultaneously - Added flag to use X offset for speed, instead of line length --- extras/conf/SRB2-22.cfg | 89 +++++++++++++++++++- extras/conf/udb/Includes/SRB222_linedefs.cfg | 47 ++++++++++- src/p_setup.c | 13 ++- 3 files changed, 146 insertions(+), 3 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 969f645f3..0bf009f79 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -2824,36 +2824,63 @@ linedeftypes { title = "Scroll Floor Texture"; prefix = "(510)"; + flags8192text = "[13] Use angle and X offset"; } 511 { title = "Scroll Floor Texture (Accelerative)"; prefix = "(511)"; + flags8192text = "[13] Use angle and X offset"; } 512 { title = "Scroll Floor Texture (Displacement)"; prefix = "(512)"; + flags8192text = "[13] Use angle and X offset"; } 513 { title = "Scroll Ceiling Texture"; prefix = "(513)"; + flags8192text = "[13] Use angle and X offset"; } 514 { title = "Scroll Ceiling Texture (Accelerative)"; prefix = "(514)"; + flags8192text = "[13] Use angle and X offset"; } 515 { title = "Scroll Ceiling Texture (Displacement)"; prefix = "(515)"; + flags8192text = "[13] Use angle and X offset"; + } + + 516 + { + title = "Scroll Floor and Ceiling Texture"; + prefix = "(516)"; + flags8192text = "[13] Use angle and X offset"; + } + + 517 + { + title = "Scroll Floor and Ceiling Texture (Accelerative)"; + prefix = "(517)"; + flags8192text = "[13] Use angle and X offset"; + } + + 518 + { + title = "Scroll Floor and Ceiling Texture (Displacement)"; + prefix = "(518)"; + flags8192text = "[13] Use angle and X offset"; } 520 @@ -2861,6 +2888,7 @@ linedeftypes title = "Carry Objects on Floor"; prefix = "(520)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 521 @@ -2868,6 +2896,7 @@ linedeftypes title = "Carry Objects on Floor (Accelerative)"; prefix = "(521)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 522 @@ -2875,6 +2904,7 @@ linedeftypes title = "Carry Objects on Floor (Displacement)"; prefix = "(522)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 523 @@ -2882,6 +2912,7 @@ linedeftypes title = "Carry Objects on Ceiling"; prefix = "(523)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 524 @@ -2889,6 +2920,7 @@ linedeftypes title = "Carry Objects on Ceiling (Accelerative)"; prefix = "(524)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 525 @@ -2896,6 +2928,31 @@ linedeftypes title = "Carry Objects on Ceiling (Displacement)"; prefix = "(525)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 526 + { + title = "Carry Objects on Floor and Ceiling"; + prefix = "(526)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 527 + { + title = "Carry Objects on Floor and Ceiling (Accelerative)"; + prefix = "(527)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 528 + { + title = "Carry Objects on Floor and Ceiling (Displacement)"; + prefix = "(528)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 530 @@ -2903,6 +2960,7 @@ linedeftypes title = "Scroll Floor Texture and Carry Objects"; prefix = "(530)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 531 @@ -2910,6 +2968,7 @@ linedeftypes title = "Scroll Floor Texture and Carry Objects (Accelerative)"; prefix = "(531)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 532 @@ -2917,6 +2976,7 @@ linedeftypes title = "Scroll Floor Texture and Carry Objects (Displacement)"; prefix = "(532)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 533 @@ -2924,6 +2984,7 @@ linedeftypes title = "Scroll Ceiling Texture and Carry Objects"; prefix = "(533)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 534 @@ -2931,6 +2992,7 @@ linedeftypes title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; prefix = "(534)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } 535 @@ -2938,6 +3000,31 @@ linedeftypes title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; prefix = "(535)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 536 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects"; + prefix = "(536)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 537 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(537)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; + } + + 538 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(538)"; + flags64text = "[6] Exclusive"; + flags8192text = "[13] Use angle and X offset"; } } @@ -6949,7 +7036,7 @@ thingtypes { color = 10; // Green title = "Tutorial"; - + 799 { title = "Tutorial Plant"; diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index fff9edf10..4b9e5fd97 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1286,6 +1286,21 @@ doom title = "Scroll Ceiling Texture (Displacement)"; prefix = "(515)"; } + 516 + { + title = "Scroll Floor and Ceiling Texture"; + prefix = "(516)"; + } + 517 + { + title = "Scroll Floor and Ceiling Texture (Accelerative)"; + prefix = "(517)"; + } + 518 + { + title = "Scroll Floor and Ceiling Texture (Displacement)"; + prefix = "(518)"; + } 520 { title = "Carry Objects on Floor"; @@ -1316,6 +1331,21 @@ doom title = "Carry Objects on Ceiling (Displacement)"; prefix = "(525)"; } + 526 + { + title = "Carry Objects on Floor and Ceiling"; + prefix = "(526)"; + } + 527 + { + title = "Carry Objects on Floor and Ceiling (Accelerative)"; + prefix = "(527)"; + } + 528 + { + title = "Carry Objects on Floor and Ceiling (Displacement)"; + prefix = "(528)"; + } 530 { title = "Scroll Floor Texture and Carry Objects"; @@ -1346,6 +1376,21 @@ doom title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; prefix = "(535)"; } + 536 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects"; + prefix = "(536)"; + } + 537 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(537)"; + } + 538 + { + title = "Scroll Floor and Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(538)"; + } } pusher @@ -2593,7 +2638,7 @@ udmf } } } - + 190 { title = "Rising"; diff --git a/src/p_setup.c b/src/p_setup.c index 146d5d302..9712528ef 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5594,25 +5594,36 @@ static void P_ConvertBinaryLinedefTypes(void) case 513: //Scroll ceiling texture case 514: //Scroll ceiling texture (accelerative) case 515: //Scroll ceiling texture (displacement) + case 516: //Scroll floor and ceiling texture + case 517: //Scroll floor and ceiling texture (accelerative) + case 518: //Scroll floor and ceiling texture (displacement) case 520: //Carry objects on floor case 521: //Carry objects on floor (accelerative) case 522: //Carry objects on floor (displacement) case 523: //Carry objects on ceiling case 524: //Carry objects on ceiling (accelerative) case 525: //Carry objects on ceiling (displacement) + case 526: //Carry objects on floor and ceiling + case 527: //Carry objects on floor and ceiling (accelerative) + case 528: //Carry objects on floor and ceiling (displacement) case 530: //Scroll floor texture and carry objects case 531: //Scroll floor texture and carry objects (accelerative) case 532: //Scroll floor texture and carry objects (displacement) case 533: //Scroll ceiling texture and carry objects case 534: //Scroll ceiling texture and carry objects (accelerative) case 535: //Scroll ceiling texture and carry objects (displacement) + case 536: //Scroll floor and ceiling texture and carry objects + case 537: //Scroll floor and ceiling texture and carry objects (accelerative) + case 538: //Scroll floor and ceiling texture and carry objects (displacement) lines[i].args[0] = tag; - lines[i].args[1] = ((lines[i].special % 10) < 3) ? TMP_FLOOR : TMP_CEILING; + lines[i].args[1] = ((lines[i].special % 10) < 6) ? (((lines[i].special % 10) < 3) ? TMP_FLOOR : TMP_CEILING) : TMP_BOTH; lines[i].args[2] = ((lines[i].special - 510)/10 + 1) % 3; lines[i].args[3] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; lines[i].args[4] = (lines[i].special % 10) % 3; if (lines[i].args[2] != TMS_SCROLLONLY && !(lines[i].flags & ML_NOCLIMB)) lines[i].args[4] |= TMST_NONEXCLUSIVE; + if (lines[i].flags & ML_EFFECT6) + lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].special = 510; break; case 540: //Floor friction From fe8485cc2ffd6ca761e8423f08039ba5672bce29 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 17 Sep 2022 11:20:51 +0200 Subject: [PATCH 032/478] Add flag to set wind/current/push/pull strength using X offset --- extras/conf/SRB2-22.cfg | 19 +++++++++++++------ src/p_setup.c | 9 +++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 0bf009f79..6cd2f0d04 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3036,48 +3036,54 @@ linedeftypes { title = "Wind"; prefix = "(541)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use angle and X offset"; } 542 { title = "Upwards Wind"; prefix = "(542)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 543 { title = "Downwards Wind"; prefix = "(543)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 544 { title = "Current"; prefix = "(544)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use angle and X offset"; } 545 { title = "Upwards Current"; prefix = "(545)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 546 { title = "Downwards Current"; prefix = "(546)"; - flags512text = "[9] Player slides"; flags64text = "[6] Exclusive"; + flags512text = "[9] Player slides"; + flags8192text = "[13] Use X offset"; } 547 @@ -3085,6 +3091,7 @@ linedeftypes title = "Push/Pull"; prefix = "(547)"; flags64text = "[6] Exclusive"; + flags8192text = "[13] Use X offset"; } } diff --git a/src/p_setup.c b/src/p_setup.c index 9712528ef..acee2bb69 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5651,17 +5651,18 @@ static void P_ConvertBinaryLinedefTypes(void) case 544: //Current case 545: //Upwards current case 546: //Downwards current + fixed_t speed = (lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y); lines[i].args[0] = tag; switch ((lines[i].special - 541) % 3) { case 0: - lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[1] = speed >> FRACBITS; break; case 1: - lines[i].args[2] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[2] = speed >> FRACBITS; break; case 2: - lines[i].args[2] = -R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[2] = -speed >> FRACBITS; break; } lines[i].args[3] = (lines[i].special >= 544) ? p_current : p_wind; @@ -6308,7 +6309,7 @@ static void P_ConvertBinaryThingTypes(void) } mapthings[i].args[0] = mapthings[i].angle; - mapthings[i].args[1] = P_AproxDistance(line->dx >> FRACBITS, line->dy >> FRACBITS); + mapthings[i].args[1] = (line->flags & ML_EFFECT6) ? sides[line->sidenum[0]].textureoffset >> FRACBITS : P_AproxDistance(line->dx >> FRACBITS, line->dy >> FRACBITS); if (mapthings[i].type == 755) mapthings[i].args[1] *= -1; if (mapthings[i].options & MTF_OBJECTSPECIAL) From cc3d4acdcdd18d97140b40824c2f46ee71476d4a Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 20 Sep 2022 20:42:19 +0200 Subject: [PATCH 033/478] Fix AppVeyor build failure --- src/p_setup.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index acee2bb69..a85e27e99 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5651,18 +5651,19 @@ static void P_ConvertBinaryLinedefTypes(void) case 544: //Current case 545: //Upwards current case 546: //Downwards current - fixed_t speed = (lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y); + { + fixed_t strength = (lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y); lines[i].args[0] = tag; switch ((lines[i].special - 541) % 3) { case 0: - lines[i].args[1] = speed >> FRACBITS; + lines[i].args[1] = strength >> FRACBITS; break; case 1: - lines[i].args[2] = speed >> FRACBITS; + lines[i].args[2] = strength >> FRACBITS; break; case 2: - lines[i].args[2] = -speed >> FRACBITS; + lines[i].args[2] = -strength >> FRACBITS; break; } lines[i].args[3] = (lines[i].special >= 544) ? p_current : p_wind; @@ -5672,6 +5673,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[4] |= TMPF_NONEXCLUSIVE; lines[i].special = 541; break; + } case 600: //Floor lighting case 601: //Ceiling lighting lines[i].args[0] = tag; From 049bfd7bd4c0b3ba27cfcf3f38fb7653ebeaaf76 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 9 Oct 2022 17:17:16 +0200 Subject: [PATCH 034/478] Minor code cleanup in P_ConvertBinaryLinedefTypes --- src/p_setup.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index a85e27e99..1f8d316a7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5618,12 +5618,10 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = tag; lines[i].args[1] = ((lines[i].special % 10) < 6) ? (((lines[i].special % 10) < 3) ? TMP_FLOOR : TMP_CEILING) : TMP_BOTH; lines[i].args[2] = ((lines[i].special - 510)/10 + 1) % 3; - lines[i].args[3] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS; + lines[i].args[3] = ((lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)) >> FRACBITS; lines[i].args[4] = (lines[i].special % 10) % 3; if (lines[i].args[2] != TMS_SCROLLONLY && !(lines[i].flags & ML_NOCLIMB)) lines[i].args[4] |= TMST_NONEXCLUSIVE; - if (lines[i].flags & ML_EFFECT6) - lines[i].args[3] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].special = 510; break; case 540: //Floor friction From 2714ac44b47af785e3e4d7532731192911ae0879 Mon Sep 17 00:00:00 2001 From: katsy Date: Wed, 12 Oct 2022 20:38:29 -0500 Subject: [PATCH 035/478] reallow score chains from rolling --- src/p_user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 2f522ad4b..bcc9cb20b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8412,12 +8412,12 @@ void P_MovePlayer(player_t *player) } } - // End your chain if you're on the ground or climbing a wall. + // End your chain if you're on the ground while not rolling, or climbing a wall. // But not if invincible! Allow for some crazy long chains with it. // Also keep in mind the PF_JUMPED check. // If we lacked this, stepping up while jumping up would reset score. // (for instance, when climbing up off a wall.) - if ((onground || player->climbing) && !(player->pflags & PF_JUMPED) && player->powers[pw_invulnerability] <= 1) + if ((onground || player->climbing) && ((player->pflags & (PF_STARTDASH|PF_SPINNING)) != PF_SPINNING) && !(player->pflags & PF_JUMPED) && player->powers[pw_invulnerability] <= 1) P_ResetScore(player); // Show the "THOK!" graphic when spinning quickly across the ground. (even applies to non-spinners, in the case of zoom tubes) From 373af010920537ba949c113163ddf0537cb30078 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 14 Oct 2022 18:20:52 -0700 Subject: [PATCH 036/478] Add startswith and endswith, functions that compare the beginning or ending of a string --- src/doomtype.h | 3 +++ src/string.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/doomtype.h b/src/doomtype.h index 5ddd9ae44..95871e98c 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -107,6 +107,9 @@ typedef long ssize_t; char *strcasestr(const char *in, const char *what); #define stristr strcasestr +int startswith (const char *base, const char *tag); +int endswith (const char *base, const char *tag); + #if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap #define true 1 #define false 0 diff --git a/src/string.c b/src/string.c index 5534a3f0c..f48788e35 100644 --- a/src/string.c +++ b/src/string.c @@ -52,3 +52,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz) #endif #include "strcasestr.c" + +int startswith(const char *path, const char *tag) +{ + return !strncmp(path, tag, strlen(tag)); +} + +int endswith(const char *base, const char *tag) +{ + const size_t base_length = strlen(base); + const size_t tag_length = strlen(tag); + + if (tag_length > base_length) + return false; + + return !memcmp(&base[base_length - tag_length], tag, tag_length); +} From b1a86b0b340fce3d0b92493bca6db55878f2eafa Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 14 Oct 2022 17:40:13 -0700 Subject: [PATCH 037/478] Disallow adding files with absolute path or traversing upward (Except as part of srb2home, srb2path or addons_folder -- this lets addons menu work, primarily.) - disallowed when using addfile or addfolder - security check for xcmd receive --- src/d_main.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/d_main.h | 2 ++ src/p_setup.c | 43 +++++++++++++++---------------- 3 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index fa9e21337..6e76672e0 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1689,3 +1689,74 @@ const char *D_Home(void) if (usehome) return userhome; else return NULL; } + +static boolean check_top_dir(const char **path, const char *top) +{ + // empty string does NOT match + if (!strcmp(top, "")) + return false; + + if (!startswith(*path, top)) + return false; + + *path += strlen(top); + + // if it doesn't already end with a path separator, + // check if a separator follows + if (!endswith(top, PATHSEP)) + { + if (startswith(*path, PATHSEP)) + *path += strlen(PATHSEP); + else + return false; + } + + return true; +} + +static int cmp_strlen_desc(const void *a, const void *b) +{ + return ((int)strlen(*(const char*const*)b) - (int)strlen(*(const char*const*)a)); +} + +boolean D_IsPathAllowed(const char *path) +{ + const char *paths[] = { + srb2home, + srb2path, + cv_addons_folder.string + }; + + const size_t n_paths = sizeof paths / sizeof *paths; + + size_t i; + + // Sort folder paths by longest to shortest so + // overlapping paths work. E.g.: + // Path 1: /home/james/.srb2/addons + // Path 2: /home/james/.srb2 + qsort(paths, n_paths, sizeof *paths, cmp_strlen_desc); + + // These paths are allowed to be absolute + // path is offset so ".." can be checked only in the + // rest of the path + for (i = 0; i < n_paths; ++i) + { + if (check_top_dir(&path, paths[i])) + break; + } + + // Only if none of the presets matched + if (i == n_paths) + { + // Cannot be an absolute path + if (M_IsPathAbsolute(path)) + return false; + } + + // Cannot traverse upwards + if (strstr(path, "..")) + return false; + + return true; +} diff --git a/src/d_main.h b/src/d_main.h index 8189a9f2b..7760351f3 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -44,6 +44,8 @@ void D_ProcessEvents(void); const char *D_Home(void); +boolean D_IsPathAllowed(const char *path); + // // BASE LEVEL // diff --git a/src/p_setup.c b/src/p_setup.c index 03a702b30..132dc4259 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7860,8 +7860,10 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l // Add a wadfile to the active wad files, // replace sounds, musics, patches, textures, sprites and maps // -static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) +static boolean P_LoadAddon(UINT16 numlumps) { + const UINT16 wadnum = (UINT16)(numwadfiles-1); + size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; char *name; lumpinfo_t *lumpinfo; @@ -7883,6 +7885,12 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) // UINT16 flaPos, flaNum = 0; // UINT16 mapPos, mapNum = 0; + if (numlumps == INT16_MAX) + { + refreshdirmenu |= REFRESHDIR_NOTLOADED; + return false; + } + switch(wadfiles[wadnum]->type) { case RET_PK3: @@ -8051,34 +8059,25 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) return true; } -boolean P_AddWadFile(const char *wadfilename) +static boolean P_CheckAddonPath(const char *path) { - UINT16 numlumps, wadnum; - - // Init file. - if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX) + if (!D_IsPathAllowed(path)) { - refreshdirmenu |= REFRESHDIR_NOTLOADED; + CONS_Alert(CONS_WARNING, "%s: tried to add file, location is not allowed\n", path); return false; } - else - wadnum = (UINT16)(numwadfiles-1); - return P_LoadAddon(wadnum, numlumps); + return true; +} + +boolean P_AddWadFile(const char *wadfilename) +{ + return P_CheckAddonPath(wadfilename) && + P_LoadAddon(W_InitFile(wadfilename, false, false)); } boolean P_AddFolder(const char *folderpath) { - UINT16 numlumps, wadnum; - - // Init file. - if ((numlumps = W_InitFolder(folderpath, false, false)) == INT16_MAX) - { - refreshdirmenu |= REFRESHDIR_NOTLOADED; - return false; - } - else - wadnum = (UINT16)(numwadfiles-1); - - return P_LoadAddon(wadnum, numlumps); + return P_CheckAddonPath(folderpath) && + P_LoadAddon(W_InitFolder(folderpath, false, false)); } From 3bd3369fdc8b133d2a6a537160cb438749af3349 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 14 Oct 2022 21:56:01 -0700 Subject: [PATCH 038/478] Add fopenfile, alternative to fopen that does not ever open directories --- src/doomdef.h | 2 ++ src/filesrch.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/doomdef.h b/src/doomdef.h index 2b62bcd6e..62afcc6c7 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -104,6 +104,8 @@ #include #endif +FILE *fopenfile(const char*, const char*); + //#define NOMD5 // Uncheck this to compile debugging code diff --git a/src/filesrch.c b/src/filesrch.c index 3f901b695..33d5bc65f 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -39,6 +39,7 @@ #define SUFFIX "*" #define SLASH "\\" +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #ifndef INVALID_FILE_ATTRIBUTES @@ -307,6 +308,39 @@ closedir (DIR * dirp) } #endif +// fopen but it REALLY only works on regular files +// Turns out, on linux, anyway, you can fopen directories +// in read mode. (It's supposed to fail in write mode +// though!!) +FILE *fopenfile(const char *path, const char *mode) +{ + FILE *h = fopen(path, mode); + + if (h != NULL) + { + struct stat st; + int eno; + + if (fstat(fileno(h), &st) == -1) + { + eno = errno; + } + else if (!S_ISREG(st.st_mode)) + { + eno = EACCES; // set some kinda error + } + else + { + return h; // ok + } + + fclose(h); + errno = eno; + } + + return NULL; +} + static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"}, #if 1 {1, "HOME"}, {2, "SRB2"}, From 9761ab52d9d4193aa9fde4c072aa86572d79bccb Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 14 Oct 2022 21:57:14 -0700 Subject: [PATCH 039/478] FIL_ReadFileTag: use fopenfile Fixes exec, for example, crashing the game if given a directory. Test: `exec .` --- src/m_misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_misc.c b/src/m_misc.c index 6c346e5a1..495c40e8b 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -273,8 +273,8 @@ size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag) size_t count, length; UINT8 *buf; - if (FIL_ReadFileOK(name)) - handle = fopen(name, "rb"); + //if (FIL_ReadFileOK(name)) + handle = fopenfile(name, "rb"); if (!handle) return 0; From 76879299f98b2b91f9a7df661e17c137ff2f6598 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 14 Oct 2022 22:10:24 -0700 Subject: [PATCH 040/478] Restrict exec path to srb2 directories --- src/command.c | 4 ++++ src/d_main.c | 11 +++++++++++ src/d_main.h | 1 + src/m_misc.c | 1 + src/p_setup.c | 15 ++------------- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/command.c b/src/command.c index dae4dc7b1..f8b587328 100644 --- a/src/command.c +++ b/src/command.c @@ -34,6 +34,7 @@ #include "lua_script.h" #include "d_netfil.h" // findfile #include "r_data.h" // Color_cons_t +#include "d_main.h" // D_IsPathAllowed //======== // protos. @@ -770,6 +771,9 @@ static void COM_Exec_f(void) return; } + if (!D_CheckPathAllowed(COM_Argv(1), "tried to exec")) + return; + // load file // Try with Argv passed verbatim first, for back compat FIL_ReadFile(COM_Argv(1), &buf); diff --git a/src/d_main.c b/src/d_main.c index 6e76672e0..5b102d623 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1760,3 +1760,14 @@ boolean D_IsPathAllowed(const char *path) return true; } + +boolean D_CheckPathAllowed(const char *path, const char *why) +{ + if (!D_IsPathAllowed(path)) + { + CONS_Alert(CONS_WARNING, "%s: %s, location is not allowed\n", why, path); + return false; + } + + return true; +} diff --git a/src/d_main.h b/src/d_main.h index 7760351f3..cc06f5f61 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -45,6 +45,7 @@ void D_ProcessEvents(void); const char *D_Home(void); boolean D_IsPathAllowed(const char *path); +boolean D_CheckPathAllowed(const char *path, const char *why); // // BASE LEVEL diff --git a/src/m_misc.c b/src/m_misc.c index 6c346e5a1..fca0474eb 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -467,6 +467,7 @@ void Command_SaveConfig_f(void) CONS_Printf(M_GetText("saveconfig [-silent] : save config to a file\n")); return; } + strcpy(tmpstr, COM_Argv(1)); FIL_ForceExtension(tmpstr, ".cfg"); diff --git a/src/p_setup.c b/src/p_setup.c index 132dc4259..45813e04d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8059,25 +8059,14 @@ static boolean P_LoadAddon(UINT16 numlumps) return true; } -static boolean P_CheckAddonPath(const char *path) -{ - if (!D_IsPathAllowed(path)) - { - CONS_Alert(CONS_WARNING, "%s: tried to add file, location is not allowed\n", path); - return false; - } - - return true; -} - boolean P_AddWadFile(const char *wadfilename) { - return P_CheckAddonPath(wadfilename) && + return D_CheckPathAllowed(wadfilename, "tried to add file") && P_LoadAddon(W_InitFile(wadfilename, false, false)); } boolean P_AddFolder(const char *folderpath) { - return P_CheckAddonPath(folderpath) && + return D_CheckPathAllowed(folderpath, "tried to add folder") && P_LoadAddon(W_InitFolder(folderpath, false, false)); } From 1b43cdddd59ebeb6ea76721ba953370476478f0f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 27 Feb 2022 10:11:55 -0500 Subject: [PATCH 041/478] Allow saving in modified games. --- src/d_main.c | 6 ++++ src/d_netcmd.c | 6 ++-- src/f_finale.c | 17 +++------ src/g_game.c | 97 +++++++++++++++++++++++++++++++++----------------- src/hu_stuff.c | 2 +- src/m_cond.c | 3 -- src/m_menu.c | 30 ++++++---------- src/p_inter.c | 2 +- src/p_mobj.c | 6 +--- src/p_setup.c | 6 ++-- src/p_spec.c | 2 +- src/y_inter.c | 4 +-- 12 files changed, 97 insertions(+), 84 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 3566e7f3d..b1f09aaa8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1473,6 +1473,12 @@ void D_SRB2Main(void) //--------------------------------------------------------- CONFIG.CFG M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()" + if (M_CheckParm("-gamedata") && M_IsNextParm()) + { + // Moved from G_LoadGameData itself, as it would cause some crazy + // confusion issues when loading mods. + strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename); + } G_LoadGameData(); #if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4e90db0dc..73bfe9e17 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4613,11 +4613,11 @@ static void Fishcake_OnChange(void) static void Command_Isgamemodified_f(void) { if (savemoddata) - CONS_Printf(M_GetText("modifiedgame is true, but you can save emblem and time data in this mod.\n")); + CONS_Printf(M_GetText("modifiedgame is true, but you can save time data in this mod.\n")); else if (modifiedgame) - CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n")); + CONS_Printf(M_GetText("modifiedgame is true, time data can't be saved\n")); else - CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n")); + CONS_Printf(M_GetText("modifiedgame is false, you can save time data\n")); } static void Command_Cheats_f(void) diff --git a/src/f_finale.c b/src/f_finale.c index bca8e3ba6..73f6281a1 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1575,7 +1575,9 @@ void F_GameEvaluationDrawer(void) { V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); - if (!(netgame) && (!modifiedgame || savemoddata)) + if (netgame) + V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!"); + else { INT32 startcoord = 32; @@ -1590,10 +1592,6 @@ void F_GameEvaluationDrawer(void) } } } - else if (netgame) - V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!"); - else - V_DrawString(8, 96, V_YELLOWMAP, "Modified games\ncan't unlock\nextras!"); } #endif @@ -1657,7 +1655,7 @@ void F_GameEvaluationTicker(void) HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Multiplayer games can't unlock extras!"); S_StartSound(NULL, sfx_s3k68); } - else if (!modifiedgame || savemoddata) + else { ++timesBeaten; @@ -1672,13 +1670,6 @@ void F_GameEvaluationTicker(void) G_SaveGameData(); } - else - { - HU_SetCEchoFlags(V_YELLOWMAP|V_RETURN8); - HU_SetCEchoDuration(6); - HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Modified games can't unlock extras!"); - S_StartSound(NULL, sfx_s3k68); - } } } diff --git a/src/g_game.c b/src/g_game.c index 349d90558..edddcc050 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -755,7 +755,7 @@ void G_SetGameModified(boolean silent) savemoddata = false; if (!silent) - CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to record statistics.\n")); + CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to play Record Attack.\n")); // If in record attack recording, cancel it. if (modeattacking) @@ -3826,8 +3826,7 @@ static void G_UpdateVisited(void) { boolean spec = G_IsSpecialStage(gamemap); // Update visitation flags? - if ((!modifiedgame || savemoddata) // Not modified - && !multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode + if (!multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode && !stagefailed) // Did not fail the stage { UINT8 earnedEmblems; @@ -3895,14 +3894,18 @@ static void G_HandleSaveLevel(void) remove(liveeventbackup); cursaveslot = 0; } - else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking)) + else if (!(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking)) + { G_SaveGame((UINT32)cursaveslot, spstage_start); + } } } // and doing THIS here means you don't lose your progress if you close the game mid-intermission else if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) - && (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + { G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages + } } // @@ -4178,8 +4181,10 @@ static void G_DoContinued(void) tokenlist = 0; token = 0; - if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && (!modifiedgame || savemoddata) && cursaveslot > 0) + if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && cursaveslot > 0) + { G_SaveGameOver((UINT32)cursaveslot, true); + } // Reset # of lives pl->lives = (ultimatemode) ? 1 : startinglivesbalance[numgameovers]; @@ -4244,13 +4249,17 @@ void G_LoadGameSettings(void) S_InitRuntimeSounds(); } +#define GAMEDATA_ID 0x86E4A27C // Change every major version, as usual +#define COMPAT_GAMEDATA_ID 0xFCAFE211 // Can be removed entirely for 2.3 + // G_LoadGameData // Loads the main data file, which stores information such as emblems found, etc. void G_LoadGameData(void) { size_t length; INT32 i, j; - UINT8 modded = false; + + UINT32 versionID; UINT8 rtemp; //For records @@ -4261,6 +4270,9 @@ void G_LoadGameData(void) UINT8 recmares; INT32 curmare; + // Stop saving, until we successfully load it again. + gamedataloaded = false; + // Clear things so previously read gamedata doesn't transfer // to new gamedata G_ClearRecords(); // main and nights records @@ -4268,27 +4280,35 @@ void G_LoadGameData(void) totalplaytime = 0; // total play time (separate from all) if (M_CheckParm("-nodata")) - return; // Don't load. - - // Allow saving of gamedata beyond this point - gamedataloaded = true; - - if (M_CheckParm("-gamedata") && M_IsNextParm()) { - strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename); + // Don't load at all. + return; } if (M_CheckParm("-resetdata")) - return; // Don't load (essentially, reset). + { + // Don't load, but do save. (essentially, reset) + gamedataloaded = true; + return; + } length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer); - if (!length) // Aw, no game data. Their loss! + if (!length) + { + // No gamedata. We can save a new one. + gamedataloaded = true; return; + } save_p = savebuffer; // Version check - if (READUINT32(save_p) != 0xFCAFE211) + versionID = READUINT32(save_p); + if (versionID != GAMEDATA_ID +#ifdef COMPAT_GAMEDATA_ID // backwards compat behavior + && versionID != COMPAT_GAMEDATA_ID +#endif + ) { const char *gdfolder = "the SRB2 folder"; if (strcmp(srb2home,".")) @@ -4301,13 +4321,26 @@ void G_LoadGameData(void) totalplaytime = READUINT32(save_p); - modded = READUINT8(save_p); +#ifdef COMPAT_GAMEDATA_ID + // Ignore for backwards compat, it'll get fixed when saving. + if (versionID == COMPAT_GAMEDATA_ID) + { + // Old files use a UINT8 here. + READUINT8(save_p); + } + else +#endif + { + // Quick & dirty hash for what mod this save file is for. + UINT32 modID = READUINT32(save_p); + UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder); - // Aha! Someone's been screwing with the save file! - if ((modded && !savemoddata)) - goto datacorrupt; - else if (modded != true && modded != false) - goto datacorrupt; + if (modID != expectedID) + { + // Aha! Someone's been screwing with the save file! + goto datacorrupt; + } + } // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) @@ -4393,6 +4426,12 @@ void G_LoadGameData(void) Z_Free(savebuffer); save_p = NULL; + // Don't consider loaded until it's a success! + // It used to do this much earlier, but this would cause the gamedata to + // save over itself when it I_Errors from the corruption landing point below, + // which can accidentally delete players' legitimate data if the code ever has any tiny mistakes! + gamedataloaded = true; + // Silent update unlockables in case they're out of sync with conditions M_SilentUpdateUnlockablesAndEmblems(); @@ -4432,20 +4471,12 @@ void G_SaveGameData(void) return; } - if (modifiedgame && !savemoddata) - { - free(savebuffer); - save_p = savebuffer = NULL; - return; - } - // Version test - WRITEUINT32(save_p, 0xFCAFE211); + WRITEUINT32(save_p, GAMEDATA_ID); WRITEUINT32(save_p, totalplaytime); - btemp = (UINT8)(savemoddata || modifiedgame); - WRITEUINT8(save_p, btemp); + WRITEUINT32(save_p, quickncasehash(timeattackfolder, sizeof timeattackfolder)); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index c037abcd7..ebef02319 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2994,7 +2994,7 @@ static void HU_DrawCoopOverlay(void) V_DrawSmallScaledPatch(148, 172, 0, tokenicon); } - if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata)) + if (LUA_HudEnabled(hud_tabemblems)) { V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems)); V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon); diff --git a/src/m_cond.c b/src/m_cond.c index 1406317c5..58ee71fec 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -200,9 +200,6 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void) char cechoText[992] = ""; UINT8 cechoLines = 0; - if (modifiedgame && !savemoddata) - return false; - M_CheckUnlockConditions(); // Go through extra emblems diff --git a/src/m_menu.c b/src/m_menu.c index 83b788fd5..55733e552 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -757,12 +757,12 @@ static menuitem_t SR_EmblemHintMenu[] = static menuitem_t SP_MainMenu[] = { // Note: If changing the positions here, also change them in M_SinglePlayerMenu() - {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76}, - {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84}, - {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92}, - {IT_SECRET, NULL, "Marathon Run", M_Marathon, 100}, - {IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108}, - {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116} + {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76}, + {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84}, + {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92}, + {IT_SECRET, NULL, "Marathon Run", M_Marathon, 100}, + {IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108}, + {IT_CALL | IT_STRING, NULL, "Statistics", M_Statistics, 116} }; enum @@ -3514,9 +3514,11 @@ boolean M_Responder(event_t *ev) { if (((currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_CALL || (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU) - && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) + && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) { #ifndef DEVELOP + // TODO: Replays are scary, so I left the remaining instances of this alone. + // It'd be nice to get rid of this once and for all though! if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && modifiedgame && !savemoddata) { S_StartSound(NULL, sfx_skid); @@ -8701,12 +8703,6 @@ static void M_DrawLoad(void) loadgameoffset = 0; M_DrawLoadGameData(); - - if (modifiedgame && !savemoddata) - { - V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING: \x80The game is modified."); - V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved."); - } } // @@ -9008,18 +9004,12 @@ static void M_HandleLoadSave(INT32 choice) break; case KEY_ENTER: - if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata && !modifiedgame) + if (ultimate_selectable && saveSlotSelected == NOSAVESLOT) { loadgamescroll = 0; S_StartSound(NULL, sfx_skid); M_StartMessage("Are you sure you want to play\n\x85ultimate mode\x80? It isn't remotely fair,\nand you don't even get an emblem for it.\n\n(Press 'Y' to confirm)\n",M_SaveGameUltimateResponse,MM_YESNO); } - else if (saveSlotSelected != NOSAVESLOT && savegameinfo[saveSlotSelected-1].lives == -42 && !(!modifiedgame || savemoddata)) - { - loadgamescroll = 0; - S_StartSound(NULL, sfx_skid); - M_StartMessage(M_GetText("This cannot be done in a modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING); - } else if (saveSlotSelected == NOSAVESLOT || savegameinfo[saveSlotSelected-1].lives != -666) // don't allow loading of "bad saves" { loadgamescroll = 0; diff --git a/src/p_inter.c b/src/p_inter.c index dd3e0f9c2..1094c3045 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2583,7 +2583,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers) { numgameovers++; - if ((!modifiedgame || savemoddata) && cursaveslot > 0) + if (cursaveslot > 0) G_SaveGameOver((UINT32)cursaveslot, (target->player->continues <= 0)); } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 4533a2ce8..ac91e0f7f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11972,11 +11972,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) break; case MT_EMBLEM: if (netgame || multiplayer) - return false; // Single player - - if (modifiedgame && !savemoddata) - return false; // No cheating!! - + return false; // Single player (You're next on my shit list) break; default: break; diff --git a/src/p_setup.c b/src/p_setup.c index deb308da2..c41a5d94e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7746,7 +7746,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) nextmapoverride = 0; skipstats = 0; - if (!(netgame || multiplayer || demoplayback) && (!modifiedgame || savemoddata)) + if (!(netgame || multiplayer || demoplayback)) mapvisited[gamemap-1] |= MV_VISITED; else if (netgame || multiplayer) mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently @@ -7764,8 +7764,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) { // I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020 if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || marathonmode) - && (!modifiedgame || savemoddata) && cursaveslot > 0) + && cursaveslot > 0) + { G_SaveGame((UINT32)cursaveslot, gamemap); + } // If you're looking for saving sp file progression (distinct from G_SaveGameOver), check G_DoCompleted. } lastmaploaded = gamemap; // HAS to be set after saving!! diff --git a/src/p_spec.c b/src/p_spec.c index 82337d2f6..94659e0d7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2937,7 +2937,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 441: // Trigger unlockable - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) + if (!(netgame || multiplayer)) { INT32 trigid = line->args[0]; diff --git a/src/y_inter.c b/src/y_inter.c index 7faceff50..e0f246eee 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1092,7 +1092,7 @@ void Y_Ticker(void) S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching! // Update when done with tally - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) + if (!(netgame || multiplayer) && !demoplayback) { if (M_UpdateUnlockablesAndExtraEmblems()) S_StartSound(NULL, sfx_s3k68); @@ -1223,7 +1223,7 @@ void Y_Ticker(void) S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching! // Update when done with tally - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) + if (!(netgame || multiplayer) && !demoplayback) { if (M_UpdateUnlockablesAndExtraEmblems()) S_StartSound(NULL, sfx_s3k68); From bcfe0da8fc10ed8b3417a11e2dcdb26aeda9bd1f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 27 Feb 2022 10:22:44 -0500 Subject: [PATCH 042/478] Use old modded behavior when loading old files, instead of ignoring Let's not pretend script-kiddie edited old files are now perfectly A-OK :p --- src/g_game.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index edddcc050..892802d91 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4322,11 +4322,20 @@ void G_LoadGameData(void) totalplaytime = READUINT32(save_p); #ifdef COMPAT_GAMEDATA_ID - // Ignore for backwards compat, it'll get fixed when saving. if (versionID == COMPAT_GAMEDATA_ID) { - // Old files use a UINT8 here. - READUINT8(save_p); + // We'll temporarily use the old condition when loading an older file. + // The proper mod-specific hash will get saved in afterwards. + boolean modded = READUINT8(save_p); + + if (modded && !savemoddata) + { + goto datacorrupt; + } + else if (modded != true && modded != false) + { + goto datacorrupt; + } } else #endif From 4a520e63c67bfe8d9a8320553d1fd71908df3243 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 27 Feb 2022 10:33:58 -0500 Subject: [PATCH 043/478] Don't allow a gamedata named the same as the default time attack folder That'd be kinda scary! --- src/deh_soc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 583776ee7..db427b349 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2901,7 +2901,9 @@ static boolean GoodDataFileName(const char *s) p = s + strlen(s) - strlen(tail); if (p <= s) return false; // too short if (!fasticmp(p, tail)) return false; // doesn't end in .dat - if (fasticmp(s, "gamedata.dat")) return false; + + if (fasticmp(s, "gamedata.dat")) return false; // Don't overwrite default gamedata + if (fasticmp(s, "main.dat")) return false; // Don't overwrite default time attack replays return true; } From a22fa1c455cea774946f7032fd74e2e8155c9d9d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 12:43:00 -0500 Subject: [PATCH 044/478] Compromise on cheats setting modified game Instead of modifying the game, cheats now set a separate "cheats were used in this session" variable, which returns some of the old behavior. HOWEVER, cheats will STILL allow spawning / collecting emblems & unlocking unlockables. Cheats will purely prevent saving progress. (It was always frustrating that devmode would make debugging unlockable features harder...) Lastly, the function to set no-saving was exposed to Lua (`G_SetUsedCheats(silent)`). Just thought it'd be useful for large-scale gamedata-using mods that want to add their own cheat commands. --- src/d_clisrv.c | 3 +++ src/d_clisrv.h | 1 + src/d_main.c | 2 +- src/d_netcmd.c | 20 ++++++++++---------- src/doomstat.h | 1 + src/g_game.c | 31 ++++++++++++++++++++++++++++--- src/g_game.h | 1 + src/lua_baselib.c | 11 +++++++++++ src/lua_script.c | 3 +++ src/m_cheat.c | 20 ++++++++++---------- src/m_menu.c | 20 ++++++++++++++++---- src/p_inter.c | 2 +- src/p_setup.c | 2 +- 13 files changed, 87 insertions(+), 30 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4cd6333c5..f95b952f3 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1448,6 +1448,7 @@ static boolean SV_SendServerConfig(INT32 node) netbuffer->u.servercfg.gamestate = (UINT8)gamestate; netbuffer->u.servercfg.gametype = (UINT8)gametype; netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; + netbuffer->u.servercfg.usedCheats = (UINT8)usedCheats; memcpy(netbuffer->u.servercfg.server_context, server_context, 8); @@ -4341,6 +4342,8 @@ static void HandlePacketFromAwayNode(SINT8 node) maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; + if (netbuffer->u.servercfg.usedCheats) + G_SetUsedCheats(true); memcpy(server_context, netbuffer->u.servercfg.server_context, 8); } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e07864122..f3896c7ea 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -158,6 +158,7 @@ typedef struct UINT8 gametype; UINT8 modifiedgame; + UINT8 usedCheats; char server_context[8]; // Unique context id, generated at server startup. } ATTRPACK serverconfig_pak; diff --git a/src/d_main.c b/src/d_main.c index b1f09aaa8..9df1d8fab 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1506,7 +1506,7 @@ void D_SRB2Main(void) else { if (!M_CheckParm("-server")) - G_SetGameModified(true); + G_SetUsedCheats(true); autostart = true; } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 73bfe9e17..847f97341 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1877,7 +1877,7 @@ static void Command_Map_f(void) const char *gametypename; boolean newresetplayers; - boolean mustmodifygame; + boolean wouldSetCheats; INT32 newmapnum; @@ -1898,11 +1898,11 @@ static void Command_Map_f(void) option_gametype = COM_CheckPartialParm("-g"); newresetplayers = ! COM_CheckParm("-noresetplayers"); - mustmodifygame = - !( netgame || multiplayer ) && - (!modifiedgame || savemoddata ); + wouldSetCheats = + !( netgame || multiplayer ) && + !( usedCheats ); - if (mustmodifygame && !option_force) + if (wouldSetCheats && !option_force) { /* May want to be more descriptive? */ CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); @@ -1956,9 +1956,9 @@ static void Command_Map_f(void) return; } - if (mustmodifygame && option_force) + if (wouldSetCheats && option_force) { - G_SetGameModified(false); + G_SetUsedCheats(false); } // new gametype value @@ -4259,7 +4259,7 @@ static void Ringslinger_OnChange(void) } if (cv_ringslinger.value) // Only if it's been turned on - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void Gravity_OnChange(void) @@ -4280,7 +4280,7 @@ static void Gravity_OnChange(void) #endif if (!CV_IsSetToDefault(&cv_gravity)) - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); gravity = cv_gravity.value; } @@ -4596,7 +4596,7 @@ static void Fishcake_OnChange(void) // so don't make modifiedgame always on! if (cv_debug) { - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } else if (cv_debug != cv_fishcake.value) diff --git a/src/doomstat.h b/src/doomstat.h index bce43416b..490054cf9 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -75,6 +75,7 @@ extern SINT8 startinglivesbalance[maxgameovers+1]; extern boolean modifiedgame; extern UINT16 mainwads; extern boolean savemoddata; // This mod saves time/emblem data. +extern boolean usedCheats; extern boolean disableSpeedAdjust; // Don't alter the duration of player states if true extern boolean imcontinuing; // Temporary flag while continuing extern boolean metalrecording; diff --git a/src/g_game.c b/src/g_game.c index 892802d91..e75bb433e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -96,6 +96,7 @@ SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40 UINT16 mainwads = 0; boolean modifiedgame; // Set if homebrew PWAD stuff has been added. boolean savemoddata = false; +boolean usedCheats = false; // Set when a gamedata-preventing cheat command is used. UINT8 paused; UINT8 modeattacking = ATTACKING_NONE; boolean disableSpeedAdjust = false; @@ -764,6 +765,23 @@ void G_SetGameModified(boolean silent) Command_ExitGame_f(); } +void G_SetUsedCheats(boolean silent) +{ + if (usedCheats) + return; + + usedCheats = true; + + if (!silent) + CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to save progress.\n")); + + // If in record attack recording, cancel it. + if (modeattacking) + M_EndModeAttackRun(); + else if (marathonmode) + Command_ExitGame_f(); +} + /** Builds an original game map name from a map number. * The complexity is due to MAPA0-MAPZZ. * @@ -3894,7 +3912,7 @@ static void G_HandleSaveLevel(void) remove(liveeventbackup); cursaveslot = 0; } - else if (!(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking)) + else if (!usedCheats && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking)) { G_SaveGame((UINT32)cursaveslot, spstage_start); } @@ -3902,7 +3920,7 @@ static void G_HandleSaveLevel(void) } // and doing THIS here means you don't lose your progress if you close the game mid-intermission else if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) - && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + && !usedCheats && cursaveslot > 0 && CanSaveLevel(lastmap+1)) { G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages } @@ -4181,7 +4199,7 @@ static void G_DoContinued(void) tokenlist = 0; token = 0; - if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && cursaveslot > 0) + if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && !usedCheats && cursaveslot > 0) { G_SaveGameOver((UINT32)cursaveslot, true); } @@ -4480,6 +4498,13 @@ void G_SaveGameData(void) return; } + if (usedCheats) + { + free(savebuffer); + save_p = savebuffer = NULL; + return; + } + // Version test WRITEUINT32(save_p, GAMEDATA_ID); diff --git a/src/g_game.h b/src/g_game.h index dca043f2e..a781e23f9 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -243,6 +243,7 @@ void G_LoadGameData(void); void G_LoadGameSettings(void); void G_SetGameModified(boolean silent); +void G_SetUsedCheats(boolean silent); void G_SetGamestate(gamestate_t newstate); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 29adb478a..031a155d2 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3612,6 +3612,16 @@ static int lib_gRemovePlayer(lua_State *L) } +static int lib_gSetUsedCheats(lua_State *L) +{ + // Let large-scale level packs using Lua be able to add cheat commands. + boolean silent = lua_optboolean(L, 1); + //NOHUD + //INLEVEL + G_SetUsedCheats(silent); + return 0; +} + static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) { if (ISINLEVEL) @@ -4213,6 +4223,7 @@ static luaL_Reg lib[] = { {"G_AddGametype", lib_gAddGametype}, {"G_AddPlayer", lib_gAddPlayer}, {"G_RemovePlayer", lib_gRemovePlayer}, + {"G_SetUsedCheats", lib_gSetUsedCheats}, {"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_FindMap",lib_gFindMap}, diff --git a/src/lua_script.c b/src/lua_script.c index 4d4071545..5f16bca8a 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -204,6 +204,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"modifiedgame")) { lua_pushboolean(L, modifiedgame && !savemoddata); return 1; + } else if (fastcmp(word,"usedCheats")) { + lua_pushboolean(L, usedCheats); + return 1; } else if (fastcmp(word,"menuactive")) { lua_pushboolean(L, menuactive); return 1; diff --git a/src/m_cheat.c b/src/m_cheat.c index 89c8009ae..78fb3a505 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -81,7 +81,7 @@ static UINT8 cheatf_warp(void) S_StartSound(0, sfx_itemup); // Temporarily unlock stuff. - G_SetGameModified(false); + G_SetUsedCheats(false); unlockables[31].unlocked = true; // credits unlockables[30].unlocked = true; // sound test unlockables[28].unlocked = true; // level select @@ -106,7 +106,7 @@ static UINT8 cheatf_devmode(void) S_StartSound(0, sfx_itemup); // Just unlock all the things and turn on -debug and console devmode. - G_SetGameModified(false); + G_SetUsedCheats(false); for (i = 0; i < MAXUNLOCKABLES; i++) unlockables[i].unlocked = true; devparm = true; @@ -275,7 +275,7 @@ void Command_CheatNoClip_f(void) plyr->pflags ^= PF_NOCLIP; CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off")); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_CheatGod_f(void) @@ -290,7 +290,7 @@ void Command_CheatGod_f(void) plyr->pflags ^= PF_GODMODE; CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_CheatNoTarget_f(void) @@ -305,7 +305,7 @@ void Command_CheatNoTarget_f(void) plyr->pflags ^= PF_INVIS; CONS_Printf(M_GetText("SEP Field %s\n"), plyr->pflags & PF_INVIS ? M_GetText("On") : M_GetText("Off")); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_Scale_f(void) @@ -879,7 +879,7 @@ void Command_Devmode_f(void) return; } - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } void Command_Setrings_f(void) @@ -905,7 +905,7 @@ void Command_Setrings_f(void) // no totalsphere addition to revert } - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } } @@ -928,7 +928,7 @@ void Command_Setlives_f(void) P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1))); } - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } } @@ -955,7 +955,7 @@ void Command_Setcontinues_f(void) players[consoleplayer].continues = numcontinues; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } } @@ -1446,7 +1446,7 @@ void Command_ObjectPlace_f(void) REQUIRE_SINGLEPLAYER; REQUIRE_NOULTIMATE; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); silent = COM_CheckParm("-silent"); diff --git a/src/m_menu.c b/src/m_menu.c index 55733e552..81567662a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7082,7 +7082,7 @@ static void M_AllowSuper(INT32 choice) M_StartMessage(M_GetText("You are now capable of turning super.\nRemember to get all the emeralds!\n"),NULL,MM_NOTHING); SR_PandorasBox[6].status = IT_GRAYEDOUT; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void M_GetAllEmeralds(INT32 choice) @@ -7093,7 +7093,7 @@ static void M_GetAllEmeralds(INT32 choice) M_StartMessage(M_GetText("You now have all 7 emeralds.\nUse them wisely.\nWith great power comes great ring drain.\n"),NULL,MM_NOTHING); SR_PandorasBox[7].status = IT_GRAYEDOUT; - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void M_DestroyRobotsResponse(INT32 ch) @@ -7104,7 +7104,7 @@ static void M_DestroyRobotsResponse(INT32 ch) // Destroy all robots P_DestroyRobots(); - G_SetGameModified(multiplayer); + G_SetUsedCheats(false); } static void M_DestroyRobots(INT32 choice) @@ -8703,6 +8703,12 @@ static void M_DrawLoad(void) loadgameoffset = 0; M_DrawLoadGameData(); + + if (usedCheats) + { + V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING:\x80 Cheats have been activated."); + V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved."); + } } // @@ -9004,12 +9010,18 @@ static void M_HandleLoadSave(INT32 choice) break; case KEY_ENTER: - if (ultimate_selectable && saveSlotSelected == NOSAVESLOT) + if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !usedCheats) { loadgamescroll = 0; S_StartSound(NULL, sfx_skid); M_StartMessage("Are you sure you want to play\n\x85ultimate mode\x80? It isn't remotely fair,\nand you don't even get an emblem for it.\n\n(Press 'Y' to confirm)\n",M_SaveGameUltimateResponse,MM_YESNO); } + else if (saveSlotSelected != NOSAVESLOT && savegameinfo[saveSlotSelected-1].lives == -42 && usedCheats) + { + loadgamescroll = 0; + S_StartSound(NULL, sfx_skid); + M_StartMessage(M_GetText("This cannot be done in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); + } else if (saveSlotSelected == NOSAVESLOT || savegameinfo[saveSlotSelected-1].lives != -666) // don't allow loading of "bad saves" { loadgamescroll = 0; diff --git a/src/p_inter.c b/src/p_inter.c index 1094c3045..b86bb39a6 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2583,7 +2583,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers) { numgameovers++; - if (cursaveslot > 0) + if (!usedCheats && cursaveslot > 0) G_SaveGameOver((UINT32)cursaveslot, (target->player->continues <= 0)); } } diff --git a/src/p_setup.c b/src/p_setup.c index c41a5d94e..a965c5142 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7764,7 +7764,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) { // I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020 if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || marathonmode) - && cursaveslot > 0) + && !usedCheats && cursaveslot > 0) { G_SaveGame((UINT32)cursaveslot, gamemap); } From f082acbbdbc6dcb535804c4c050f0a95ea3fb773 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 12:48:18 -0500 Subject: [PATCH 045/478] Don't allow Record Attack in cheated games --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 81567662a..6d1dec19e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3519,7 +3519,7 @@ boolean M_Responder(event_t *ev) #ifndef DEVELOP // TODO: Replays are scary, so I left the remaining instances of this alone. // It'd be nice to get rid of this once and for all though! - if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && modifiedgame && !savemoddata) + if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && (modifiedgame && !savemoddata) && !usedCheats) { S_StartSound(NULL, sfx_skid); M_StartMessage(M_GetText("This cannot be done in a modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING); From 947dbda045929e0577a52a898bd40e71a6066ac1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 3 Mar 2022 10:48:44 -0500 Subject: [PATCH 046/478] Use savemoddata for ultimate file check --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6d1dec19e..c5c49a7b8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9010,7 +9010,7 @@ static void M_HandleLoadSave(INT32 choice) break; case KEY_ENTER: - if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !usedCheats) + if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata) { loadgamescroll = 0; S_StartSound(NULL, sfx_skid); From d3ff5342dd4cec3583523a8d53e6d1d6f7b7b591 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 1 May 2022 19:34:18 -0400 Subject: [PATCH 047/478] Minor adjustments --- src/m_cheat.c | 6 ------ src/m_menu.c | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index 78fb3a505..18a5a8609 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -72,9 +72,6 @@ static UINT8 cheatf_ultimate(void) static UINT8 cheatf_warp(void) { - if (modifiedgame) - return 0; - if (menuactive && currentMenu != &MainDef) return 0; // Only on the main menu! @@ -97,9 +94,6 @@ static UINT8 cheatf_devmode(void) { UINT8 i; - if (modifiedgame) - return 0; - if (menuactive && currentMenu != &MainDef) return 0; // Only on the main menu! diff --git a/src/m_menu.c b/src/m_menu.c index c5c49a7b8..d26712f1e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6711,7 +6711,7 @@ static void M_DrawAddons(void) // draw save icon x = BASEVIDWIDTH - x - 16; - V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); + V_DrawSmallScaledPatch(x, y + 4, (!usedCheats ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); if (modifiedgame) V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]); From 5103253e0b3828db68e1d58a6d3d0749d90ba8e2 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 12 Oct 2022 00:57:15 -0400 Subject: [PATCH 048/478] Allow unlockable executors again --- src/p_spec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 94659e0d7..810a7cd3f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1797,7 +1797,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { // Unlockable triggers required INT32 trigid = triggerline->args[1]; - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) + if (netgame || multiplayer) return false; else if (trigid < 0 || trigid > 31) // limited by 32 bit variable { @@ -1812,7 +1812,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { // An unlockable itself must be unlocked! INT32 unlockid = triggerline->args[1]; - if ((modifiedgame && !savemoddata) || (netgame || multiplayer)) + if (netgame || multiplayer) return false; else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count { From 969dc4813a4ebd41e1710e941bbd36f002c1796f Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sat, 19 Nov 2022 19:57:08 +0100 Subject: [PATCH 049/478] Allow cosmetic add-ons mid-save --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index deb308da2..d5e6100b7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8074,7 +8074,7 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps) ST_Start(); // Prevent savefile cheating - if (cursaveslot > 0) + if (modifiedgame && (cursaveslot > 0)) cursaveslot = 0; if (replacedcurrentmap && gamestate == GS_LEVEL && (netgame || multiplayer)) From 256d9b5fdb3411a79278e3ba2ec5000bc889770f Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sun, 20 Nov 2022 11:50:01 +0100 Subject: [PATCH 050/478] Uncap console opening/closing animation --- src/console.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/console.c b/src/console.c index 40fb43121..9af9eb9a8 100644 --- a/src/console.c +++ b/src/console.c @@ -643,33 +643,39 @@ static void CON_ChangeHeight(void) // static void CON_MoveConsole(void) { - fixed_t conspeed; + static fixed_t fracmovement = 0; Lock_state(); - conspeed = FixedDiv(cons_speed.value*vid.fdupy, FRACUNIT); - // instant if (!cons_speed.value) { con_curlines = con_destlines; + Unlock_state(); return; } - // up/down move to dest - if (con_curlines < con_destlines) + // Not instant - Increment fracmovement fractionally + fracmovement += FixedMul(cons_speed.value*vid.fdupy, renderdeltatics); + + if (con_curlines < con_destlines) // Move the console downwards { - con_curlines += FixedInt(conspeed); - if (con_curlines > con_destlines) - con_curlines = con_destlines; + con_curlines += FixedInt(fracmovement); // Move by fracmovement's integer value + if (con_curlines > con_destlines) // If we surpassed the destination... + con_curlines = con_destlines; // ...clamp to it! } - else if (con_curlines > con_destlines) + else // Move the console upwards { - con_curlines -= FixedInt(conspeed); + con_curlines -= FixedInt(fracmovement); if (con_curlines < con_destlines) con_curlines = con_destlines; + + if (con_destlines == 0) // If the console is being closed, not just moved up... + con_tick = 0; // ...don't show the blinking cursor } + fracmovement %= FRACUNIT; // Reset fracmovement's integer value, but keep the fraction + Unlock_state(); } @@ -752,10 +758,6 @@ void CON_Ticker(void) CON_ChangeHeight(); } - // console movement - if (con_destlines != con_curlines) - CON_MoveConsole(); - // clip the view, so that the part under the console is not drawn con_clipviewtop = -1; if (cons_backpic.value) // clip only when using an opaque background @@ -1866,6 +1868,10 @@ void CON_Drawer(void) CON_ClearHUD(); } + // console movement + if (con_curlines != con_destlines) + CON_MoveConsole(); + if (con_curlines > 0) CON_DrawConsole(); else if (gamestate == GS_LEVEL From 435e1f6e7e1fab7e47dfc2df2ab60660583fe53d Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sun, 20 Nov 2022 11:50:57 +0100 Subject: [PATCH 051/478] Make con_height adjustable on the fly --- src/console.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/console.c b/src/console.c index 9af9eb9a8..fb023c67e 100644 --- a/src/console.c +++ b/src/console.c @@ -110,6 +110,7 @@ static void CON_RecalcSize(void); static void CON_ChangeHeight(void); static void CON_DrawBackpic(void); +static void CONS_height_Change(void); static void CONS_hudlines_Change(void); static void CONS_backcolor_Change(void); @@ -136,7 +137,7 @@ static CV_PossibleValue_t speed_cons_t[] = {{0, "MIN"}, {64, "MAX"}, {0, NULL}}; static consvar_t cons_speed = CVAR_INIT ("con_speed", "8", CV_SAVE, speed_cons_t, NULL); // percentage of screen height to use for console -static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_SAVE, CV_Unsigned, NULL); +static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_CALL|CV_SAVE, CV_Unsigned, CONS_height_Change); static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}, {0, NULL}}; // whether to use console background picture, or translucent mode @@ -156,6 +157,18 @@ consvar_t cons_backcolor = CVAR_INIT ("con_backcolor", "Green", CV_CALL|CV_SAVE, static void CON_Print(char *msg); +// Change the console height on demand +// +static void CONS_height_Change(void) +{ + Lock_state(); + + if (con_destlines > 0 && !con_startup) // If the console is open (as in, not using "bind")... + CON_ChangeHeight(); // ...update its height now, not only when it's closed and re-opened + + Unlock_state(); +} + // // static void CONS_hudlines_Change(void) From 396db189e7cf541f325d653ef5be7fa5ed1b2037 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sun, 20 Nov 2022 11:51:40 +0100 Subject: [PATCH 052/478] Draw the input prompt while the console is moving --- src/console.c | 52 +++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/console.c b/src/console.c index fb023c67e..6f85dbf1c 100644 --- a/src/console.c +++ b/src/console.c @@ -61,7 +61,7 @@ static boolean con_started = false; // console has been initialised static boolean con_forcepic = true; // at startup toggle console translucency when first off boolean con_recalc; // set true when screen size has changed -static tic_t con_tick; // console ticker for anim or blinking prompt cursor +static tic_t con_tick; // console ticker for blinking prompt cursor // con_scrollup should use time (currenttime - lasttime).. static boolean consoletoggle; // true when console key pushed, ticker will handle @@ -1824,41 +1824,41 @@ static void CON_DrawConsole(void) } // draw console text lines from top to bottom - if (con_curlines < minheight) - return; - - i = con_cy - con_scrollup; - - // skip the last empty line due to the cursor being at the start of a new line - i--; - - i -= (con_curlines - minheight) / charheight; - - if (rendermode == render_none) return; - - for (y = (con_curlines-minheight) % charheight; y <= con_curlines-minheight; y += charheight, i++) + if (con_curlines >= minheight) { - INT32 x; - size_t c; + i = con_cy - con_scrollup; - p = (UINT8 *)&con_buffer[((i > 0 ? i : 0)%con_totallines)*con_width]; + // skip the last empty line due to the cursor being at the start of a new line + i--; - for (c = 0, x = charwidth; c < con_width; c++, x += charwidth, p++) + i -= (con_curlines - minheight) / charheight; + + if (rendermode == render_none) return; + + for (y = (con_curlines-minheight) % charheight; y <= con_curlines-minheight; y += charheight, i++) { - while (*p & 0x80) + INT32 x; + size_t c; + + p = (UINT8 *)&con_buffer[((i > 0 ? i : 0)%con_totallines)*con_width]; + + for (c = 0, x = charwidth; c < con_width; c++, x += charwidth, p++) { - charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; - p++; - c++; + while (*p & 0x80) + { + charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; + p++; + c++; + } + if (c >= con_width) + break; + V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } - if (c >= con_width) - break; - V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } } // draw prompt if enough place (not while game startup) - if ((con_curlines == con_destlines) && (con_curlines >= minheight) && !con_startup) + if ((con_curlines >= (minheight-charheight)) && !con_startup) CON_DrawInput(); } From 3a2834e781f42137bd17376e3e78da3d479ffbf9 Mon Sep 17 00:00:00 2001 From: ashifolfi Date: Sun, 20 Nov 2022 15:25:53 -0500 Subject: [PATCH 053/478] add R_TextureNameForNum and expose to lua --- src/lua_baselib.c | 18 ++++++++++++++++++ src/r_textures.c | 20 ++++++++++++++++++++ src/r_textures.h | 4 ++++ 3 files changed, 42 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 29adb478a..9cfde9706 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2832,6 +2832,22 @@ static int lib_rTextureNumForName(lua_State *L) return 1; } +static int lib_rCheckTextureNameForNum(lua_State *L) +{ + INT32 num = luaL_checkstring(L, 1); + //HUDSAFE + lua_pushstring(L, R_CheckTextureNameForNum(num)); + return 1; +} + +static int lib_rTextureNameForNum(lua_State *L) +{ + INT32 num = luaL_checkstring(L, 1); + //HUDSAFE + lua_pushstring(L, R_TextureNameForNum(num)); + return 1; +} + // R_DRAW //////////// static int lib_rGetColorByName(lua_State *L) @@ -4174,6 +4190,8 @@ static luaL_Reg lib[] = { // r_data {"R_CheckTextureNumForName",lib_rCheckTextureNumForName}, {"R_TextureNumForName",lib_rTextureNumForName}, + {"R_CheckTextureNameForNum", lib_rCheckTextureNameForNum}, + {"R_TextureNameForNum", lib_rTextureNameForNum}, // r_draw {"R_GetColorByName", lib_rGetColorByName}, diff --git a/src/r_textures.c b/src/r_textures.c index 98c2788a2..2a9fc9953 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1662,6 +1662,26 @@ INT32 R_CheckTextureNumForName(const char *name) return -1; } +// i was fully expecting this to take like an hour to figure out not 2 mintues and 5 lines of c - ashi +const char *R_CheckTextureNameForNum(INT32 num) +{ + if (textures[num] && textures[num]->name) + { + return textures[num]->name; + } + return "-"; +} + +const char *R_TextureNameForNum(INT32 num) +{ + const char *result = R_CheckTextureNameForNum(num); + + if (strcmp(result, "-")) + return "REDWALL"; + + return result; +} + // // R_TextureNumForName // diff --git a/src/r_textures.h b/src/r_textures.h index b9b48da8c..64be59ee3 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -104,6 +104,10 @@ INT32 R_TextureNumForName(const char *name); INT32 R_CheckTextureNumForName(const char *name); lumpnum_t R_GetFlatNumForName(const char *name); +// Returns the texture name for the texture number (in case you ever needed it) +const char *R_TextureNumForName(INT32 num); +const char *R_CheckTextureNumForName(INT32 num); + extern INT32 numtextures; #endif From e48f7d15381753e6ac49ea8c8607cc1a957617f0 Mon Sep 17 00:00:00 2001 From: ashifolfi Date: Sun, 20 Nov 2022 16:06:43 -0500 Subject: [PATCH 054/478] actually use correct names in the header --- src/r_textures.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_textures.h b/src/r_textures.h index 64be59ee3..4fb65f7e5 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -105,8 +105,8 @@ INT32 R_CheckTextureNumForName(const char *name); lumpnum_t R_GetFlatNumForName(const char *name); // Returns the texture name for the texture number (in case you ever needed it) -const char *R_TextureNumForName(INT32 num); -const char *R_CheckTextureNumForName(INT32 num); +const char *R_CheckTextureNameForNum(INT32 num); +const char *R_TextureNameForNum(INT32 num); extern INT32 numtextures; From 1b14dff0e9cb7cea73866a4a6abf51927d507606 Mon Sep 17 00:00:00 2001 From: ashifolfi Date: Sun, 20 Nov 2022 16:06:47 -0500 Subject: [PATCH 055/478] add comments + better checktexturename if statement --- src/r_textures.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/r_textures.c b/src/r_textures.c index 2a9fc9953..34b2f0637 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1662,21 +1662,30 @@ INT32 R_CheckTextureNumForName(const char *name) return -1; } -// i was fully expecting this to take like an hour to figure out not 2 mintues and 5 lines of c - ashi +// +// R_CheckTextureNameForNum +// +// because sidedefs use numbers and sometimes you want names +// returns no texture marker if no texture was found +// const char *R_CheckTextureNameForNum(INT32 num) { - if (textures[num] && textures[num]->name) - { + if (num > 0 && num < numtextures) return textures[num]->name; - } + return "-"; } +// +// R_TextureNameForNum +// +// calls R_CheckTextureNameForNum and returns REDWALL if result is a no texture marker +// const char *R_TextureNameForNum(INT32 num) { const char *result = R_CheckTextureNameForNum(num); - if (strcmp(result, "-")) + if (strcmp(result, "-") == 0) return "REDWALL"; return result; From 47e981d2a876940f581332afd379caca6568f87e Mon Sep 17 00:00:00 2001 From: ashifolfi Date: Sun, 20 Nov 2022 16:07:14 -0500 Subject: [PATCH 056/478] actually check the right type in lua --- src/lua_baselib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9cfde9706..efbc80472 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2834,7 +2834,7 @@ static int lib_rTextureNumForName(lua_State *L) static int lib_rCheckTextureNameForNum(lua_State *L) { - INT32 num = luaL_checkstring(L, 1); + INT32 num = (INT32)luaL_checkinteger(L, 1); //HUDSAFE lua_pushstring(L, R_CheckTextureNameForNum(num)); return 1; @@ -2842,7 +2842,7 @@ static int lib_rCheckTextureNameForNum(lua_State *L) static int lib_rTextureNameForNum(lua_State *L) { - INT32 num = luaL_checkstring(L, 1); + INT32 num = (INT32)luaL_checkinteger(L, 1); //HUDSAFE lua_pushstring(L, R_TextureNameForNum(num)); return 1; From 356bdb25a1b4d36db3fe4c3a385a14f34e5e687a Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 6 Sep 2022 12:36:59 -0700 Subject: [PATCH 057/478] Add a hitbox renderer to Software mode renderhitbox - Tangible - collision activating objects, minus rings - All - every object - Intangible - the opposite of Tangible, also no rings - Rings - rings --- src/Sourcefile | 1 + src/d_netcmd.c | 1 + src/p_mobj.h | 2 +- src/r_bbox.c | 290 +++++++++++++++++++++++++++++++++++++++++++++++++ src/r_things.c | 8 ++ src/r_things.h | 3 + src/screen.h | 2 +- 7 files changed, 305 insertions(+), 2 deletions(-) create mode 100644 src/r_bbox.c diff --git a/src/Sourcefile b/src/Sourcefile index de90bb609..fb08c2171 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -64,6 +64,7 @@ r_skins.c r_sky.c r_splats.c r_things.c +r_bbox.c r_textures.c r_patch.c r_patchrotation.c diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4e90db0dc..ceb94fb1f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -868,6 +868,7 @@ void D_RegisterClientCommands(void) // screen.c CV_RegisterVar(&cv_fullscreen); CV_RegisterVar(&cv_renderview); + CV_RegisterVar(&cv_renderhitbox); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); CV_RegisterVar(&cv_scr_width); diff --git a/src/p_mobj.h b/src/p_mobj.h index 60601692c..a7e25f461 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -122,7 +122,7 @@ typedef enum MF_AMBIENT = 1<<10, // Slide this object when it hits a wall. MF_SLIDEME = 1<<11, - // Player cheat. + // Don't collide with walls or solid objects. Two MF_NOCLIP objects can't touch each other at all! MF_NOCLIP = 1<<12, // Allow moves to any height, no gravity. For active floaters. MF_FLOAT = 1<<13, diff --git a/src/r_bbox.c b/src/r_bbox.c new file mode 100644 index 000000000..e3b5216bf --- /dev/null +++ b/src/r_bbox.c @@ -0,0 +1,290 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2022 by Kart Krew. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_bbox.c +/// \brief Boundary box (cube) renderer + +#include "doomdef.h" +#include "command.h" +#include "r_local.h" +#include "screen.h" // cv_renderhitbox +#include "v_video.h" // V_DrawFill + +enum { + RENDERHITBOX_OFF, + RENDERHITBOX_TANGIBLE, + RENDERHITBOX_ALL, + RENDERHITBOX_INTANGIBLE, + RENDERHITBOX_RINGS, +}; + +static CV_PossibleValue_t renderhitbox_cons_t[] = { + {RENDERHITBOX_OFF, "Off"}, + {RENDERHITBOX_TANGIBLE, "Tangible"}, + {RENDERHITBOX_ALL, "All"}, + {RENDERHITBOX_INTANGIBLE, "Intangible"}, + {RENDERHITBOX_RINGS, "Rings"}, + {0}}; + +consvar_t cv_renderhitbox = CVAR_INIT ("renderhitbox", "Off", 0, renderhitbox_cons_t, NULL); + +struct bbox_col { + INT32 x; + INT32 y; + INT32 h; +}; + +struct bbox_config { + fixed_t height; + fixed_t tz; + struct bbox_col col[4]; + UINT8 color; +}; + +static inline void +raster_bbox_seg +( INT32 x, + fixed_t y, + fixed_t h, + UINT8 pixel) +{ + y /= FRACUNIT; + + if (y < 0) + y = 0; + + h = y + (FixedCeil(abs(h)) / FRACUNIT); + + if (h >= viewheight) + h = viewheight; + + while (y < h) + { + topleft[x + y * vid.width] = pixel; + y++; + } +} + +static void +draw_bbox_col +( struct bbox_config * bb, + int p, + fixed_t tx, + fixed_t ty) +{ + struct bbox_col *col = &bb->col[p]; + + fixed_t xscale = FixedDiv(projection, ty); + fixed_t yscale = FixedDiv(projectiony, ty); + + col->x = (centerxfrac + FixedMul(tx, xscale)) / FRACUNIT; + col->y = (centeryfrac - FixedMul(bb->tz, yscale)); + col->h = FixedMul(bb->height, yscale); + + // Using this function is TOO EASY! + V_DrawFill( + viewwindowx + col->x, + viewwindowy + col->y / FRACUNIT, 1, + col->h / FRACUNIT, V_NOSCALESTART | bb->color); +} + +static void +draw_bbox_row +( struct bbox_config * bb, + int p1, + int p2) +{ + struct bbox_col + *a = &bb->col[p1], + *b = &bb->col[p2]; + + INT32 x1, x2; // left, right + INT32 dx; // width + + fixed_t y1, y2; // top, bottom + fixed_t s1, s2; // top and bottom increment + + if (a->x > b->x) + { + struct bbox_col *c = a; + a = b; + b = c; + } + + x1 = a->x; + x2 = b->x; + + if (x2 >= viewwidth) + x2 = viewwidth - 1; + + if (x1 == x2 || x1 >= viewwidth || x2 < 0) + return; + + dx = x2 - x1; + + y1 = a->y; + y2 = b->y; + s1 = (y2 - y1) / dx; + + y2 = y1 + a->h; + s2 = ((b->y + b->h) - y2) / dx; + + // FixedCeil needs a minimum!!! :D :D + + if (s1 == 0) + s1 = 1; + + if (s2 == 0) + s2 = 1; + + if (x1 < 0) + { + y1 -= x1 * s1; + y2 -= x1 * s2; + x1 = 0; + } + + while (x1 < x2) + { + raster_bbox_seg(x1, y1, s1, bb->color); + raster_bbox_seg(x1, y2, s2, bb->color); + + y1 += s1; + y2 += s2; + + x1++; + } +} + +static UINT8 +get_bbox_color (mobj_t *thing) +{ + UINT32 flags = thing->flags; + + if (thing->player) + return 255; // 0FF + + if (flags & (MF_NOCLIPTHING)) + return 7; // BFBFBF + + if (flags & (MF_BOSS|MF_MISSILE|MF_ENEMY|MF_PAIN)) + return 35; // F00 + + if (flags & (MF_SPECIAL|MF_MONITOR)) + return 73; // FF0 + + if (flags & (MF_NOCLIP)) + return 152; // 00F + + return 0; // FFF +} + +void R_DrawThingBoundingBox(mobj_t *thing) +{ + fixed_t rs, rc; // radius offsets + fixed_t gx, gy; // origin + fixed_t tx, ty; // translated coordinates + + struct bbox_config bb = {0}; + + rs = FixedMul(thing->radius, viewsin); + rc = FixedMul(thing->radius, viewcos); + + gx = thing->x - viewx; + gy = thing->y - viewy; + + tx = FixedMul(gx, viewsin) - FixedMul(gy, viewcos); + ty = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); + + bb.height = thing->height; + bb.tz = (thing->z + bb.height) - viewz; + bb.color = get_bbox_color(thing); + + // 1--3 + // | | + // 0--2 + + // left + + tx -= rs; + ty -= rc; + + draw_bbox_col(&bb, 0, tx + rc, ty - rs); // bottom + draw_bbox_col(&bb, 1, tx - rc, ty + rs); // top + + // right + + tx += rs + rs; + ty += rc + rc; + + draw_bbox_col(&bb, 2, tx + rc, ty - rs); // bottom + draw_bbox_col(&bb, 3, tx - rc, ty + rs); // top + + // connect all four columns + + draw_bbox_row(&bb, 0, 1); + draw_bbox_row(&bb, 1, 3); + draw_bbox_row(&bb, 3, 2); + draw_bbox_row(&bb, 2, 0); +} + +static boolean is_tangible (mobj_t *thing) +{ + // These objects can never touch another + if (thing->flags & (MF_NOCLIPTHING)) + { + return false; + } + + // These objects probably do nothing! :D + if ((thing->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE + |MF_PUSHABLE|MF_BOSS|MF_MISSILE|MF_SPRING + |MF_BOUNCE|MF_MONITOR|MF_FIRE|MF_ENEMY + |MF_PAIN|MF_STICKY + |MF_GRENADEBOUNCE)) == 0U) + { + return false; + } + + return true; +} + +boolean R_ThingBoundingBoxVisible(mobj_t *thing) +{ + INT32 cvmode = cv_renderhitbox.value; + + switch (cvmode) + { + case RENDERHITBOX_OFF: + return false; + + case RENDERHITBOX_ALL: + return true; + + case RENDERHITBOX_INTANGIBLE: + return !is_tangible(thing); + + case RENDERHITBOX_TANGIBLE: + // Exclude rings from here, lots of them! + if (thing->type == MT_RING) + { + return false; + } + + return is_tangible(thing); + + case RENDERHITBOX_RINGS: + return (thing->type == MT_RING); + + default: + return false; + } +} diff --git a/src/r_things.c b/src/r_things.c index fed873fd6..65047176d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2939,6 +2939,14 @@ static void R_DrawSprite(vissprite_t *spr) R_DrawFloorSplat(spr); else R_DrawVisSprite(spr); + + if (R_ThingBoundingBoxVisible(spr->mobj)) + { + // fuck you fuck you fuck you FUCK YOU + // (shadows are linked to their mobj) + if (!(spr->cut & SC_SHADOW)) + R_DrawThingBoundingBox(spr->mobj); + } } // Special drawer for precipitation sprites Tails 08-18-2002 diff --git a/src/r_things.h b/src/r_things.h index 35eeb9ce1..4ba649c30 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -66,6 +66,9 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_InitSprites(void); void R_ClearSprites(void); +boolean R_ThingBoundingBoxVisible(mobj_t *thing); +void R_DrawThingBoundingBox(mobj_t *thing); + boolean R_ThingVisible (mobj_t *thing); boolean R_ThingVisibleWithinDist (mobj_t *thing, diff --git a/src/screen.h b/src/screen.h index add048b25..5a69be659 100644 --- a/src/screen.h +++ b/src/screen.h @@ -199,7 +199,7 @@ extern CV_PossibleValue_t cv_renderer_t[]; extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders -extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen; +extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_renderhitbox, cv_fullscreen; // wait for page flipping to end or not extern consvar_t cv_vidwait; extern consvar_t cv_timescale; From 694804cd96cafb1bfb146406f775e2bd23b1fb7a Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 10 Sep 2022 21:27:37 -0700 Subject: [PATCH 058/478] Refactor hitbox renderer to project vissprites Properly accounts for portals (skyboxes). --- src/r_bbox.c | 46 ++++++--------- src/r_things.c | 155 ++++++++++++++++++++++++++++++++++++++++++------- src/r_things.h | 9 ++- 3 files changed, 161 insertions(+), 49 deletions(-) diff --git a/src/r_bbox.c b/src/r_bbox.c index e3b5216bf..bbac0f56b 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -165,11 +165,11 @@ draw_bbox_row } static UINT8 -get_bbox_color (mobj_t *thing) +get_bbox_color (vissprite_t *vis) { - UINT32 flags = thing->flags; + UINT32 flags = vis->mobjflags; - if (thing->player) + if (vis->mobj->player) return 255; // 0FF if (flags & (MF_NOCLIPTHING)) @@ -187,26 +187,21 @@ get_bbox_color (mobj_t *thing) return 0; // FFF } -void R_DrawThingBoundingBox(mobj_t *thing) +void R_DrawThingBoundingBox(vissprite_t *vis) { - fixed_t rs, rc; // radius offsets - fixed_t gx, gy; // origin - fixed_t tx, ty; // translated coordinates + // radius offsets + fixed_t rs = vis->scale; + fixed_t rc = vis->xscale; - struct bbox_config bb = {0}; + // translated coordinates + fixed_t tx = vis->gx; + fixed_t ty = vis->gy; - rs = FixedMul(thing->radius, viewsin); - rc = FixedMul(thing->radius, viewcos); - - gx = thing->x - viewx; - gy = thing->y - viewy; - - tx = FixedMul(gx, viewsin) - FixedMul(gy, viewcos); - ty = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); - - bb.height = thing->height; - bb.tz = (thing->z + bb.height) - viewz; - bb.color = get_bbox_color(thing); + struct bbox_config bb = { + .height = vis->thingheight, + .tz = vis->texturemid, + .color = get_bbox_color(vis), + }; // 1--3 // | | @@ -214,18 +209,15 @@ void R_DrawThingBoundingBox(mobj_t *thing) // left - tx -= rs; - ty -= rc; - - draw_bbox_col(&bb, 0, tx + rc, ty - rs); // bottom + draw_bbox_col(&bb, 0, tx, ty); // bottom draw_bbox_col(&bb, 1, tx - rc, ty + rs); // top // right - tx += rs + rs; - ty += rc + rc; + tx += rs; + ty += rc; - draw_bbox_col(&bb, 2, tx + rc, ty - rs); // bottom + draw_bbox_col(&bb, 2, tx, ty); // bottom draw_bbox_col(&bb, 3, tx - rc, ty + rs); // top // connect all four columns diff --git a/src/r_things.c b/src/r_things.c index 65047176d..6e4062219 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1424,6 +1424,91 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, objectsdrawn++; } +static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) +{ + fixed_t gx, gy; + fixed_t tx, tz; + + vissprite_t *box; + + if (!R_ThingBoundingBoxVisible(thing)) + { + return; + } + + // 1--3 + // | | + // 0--2 + + // start in the (0) corner + gx = thing->x - thing->radius - viewx; + gy = thing->y - thing->radius - viewy; + + tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); + + // thing is behind view plane? + // if parent vis is visible, ignore this + if (!vis && (tz < FixedMul(MINZ, thing->scale))) + { + return; + } + + tx = FixedMul(gx, viewsin) - FixedMul(gy, viewcos); + + // too far off the side? + if (!vis && abs(tx) > FixedMul(tz, fovtan)<<2) + { + return; + } + + box = R_NewVisSprite(); + box->mobj = thing; + box->mobjflags = thing->flags; + box->thingheight = thing->height; + box->cut = SC_BBOX; + + box->gx = tx; + box->gy = tz; + + box->scale = 2 * FixedMul(thing->radius, viewsin); + box->xscale = 2 * FixedMul(thing->radius, viewcos); + + box->pz = thing->z; + box->pzt = box->pz + box->thingheight; + + box->gzt = box->pzt; + box->gz = box->pz; + box->texturemid = box->gzt - viewz; + + if (vis) + { + box->x1 = vis->x1; + box->x2 = vis->x2; + box->szt = vis->szt; + box->sz = vis->sz; + + box->sortscale = vis->sortscale; // link sorting to sprite + box->dispoffset = vis->dispoffset + 5; + + box->cut |= SC_LINKDRAW; + } + else + { + fixed_t xscale = FixedDiv(projection, tz); + fixed_t yscale = FixedDiv(projectiony, tz); + fixed_t top = (centeryfrac - FixedMul(box->texturemid, yscale)); + + box->x1 = (centerxfrac + FixedMul(box->gx, xscale)) / FRACUNIT; + box->x2 = box->x1; + + box->szt = top / FRACUNIT; + box->sz = (top + FixedMul(box->thingheight, yscale)) / FRACUNIT; + + box->sortscale = yscale; + box->dispoffset = 0; + } +} + // // R_ProjectSprite // Generates a vissprite for a thing @@ -2181,6 +2266,8 @@ static void R_ProjectSprite(mobj_t *thing) if (oldthing->shadowscale && cv_shadow.value) R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz); + R_ProjectBoundingBox(oldthing, vis); + // Debug ++objectsdrawn; } @@ -2406,8 +2493,26 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS; for (thing = sec->thinglist; thing; thing = thing->snext) { - if (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist)) - R_ProjectSprite(thing); + if (R_ThingWithinDist(thing, limit_dist, hoop_limit_dist)) + { + const INT32 oldobjectsdrawn = objectsdrawn; + + if (R_ThingVisible(thing)) + { + R_ProjectSprite(thing); + } + + // I'm so smart :^) + if (objectsdrawn == oldobjectsdrawn) + { + /* + Object is invisible OR is off screen but + render its bbox even if the latter because + radius could be bigger than sprite. + */ + R_ProjectBoundingBox(thing, NULL); + } + } } // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off @@ -2495,6 +2600,10 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e if (dsfirst->cut & SC_SHADOW) continue; + // don't connect to your bounding box! + if (dsfirst->cut & SC_BBOX) + continue; + // don't connect if it's not the tracer if (dsfirst->mobj != ds->mobj) continue; @@ -2935,18 +3044,12 @@ static void R_DrawSprite(vissprite_t *spr) mfloorclip = spr->clipbot; mceilingclip = spr->cliptop; - if (spr->cut & SC_SPLAT) + if (spr->cut & SC_BBOX) + R_DrawThingBoundingBox(spr); + else if (spr->cut & SC_SPLAT) R_DrawFloorSplat(spr); else R_DrawVisSprite(spr); - - if (R_ThingBoundingBoxVisible(spr->mobj)) - { - // fuck you fuck you fuck you FUCK YOU - // (shadows are linked to their mobj) - if (!(spr->cut & SC_SHADOW)) - R_DrawThingBoundingBox(spr->mobj); - } } // Special drawer for precipitation sprites Tails 08-18-2002 @@ -3182,9 +3285,13 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) for (; clippedvissprites < visspritecount; clippedvissprites++) { vissprite_t *spr = R_GetVisSprite(clippedvissprites); - INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; - INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2; - R_ClipVisSprite(spr, x1, x2, dsstart, portal); + + if (!(spr->cut & SC_BBOX)) // Do not clip bounding boxes + { + INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; + INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2; + R_ClipVisSprite(spr, x1, x2, dsstart, portal); + } } } @@ -3198,16 +3305,11 @@ boolean R_ThingVisible (mobj_t *thing) )); } -boolean R_ThingVisibleWithinDist (mobj_t *thing, +boolean R_ThingWithinDist (mobj_t *thing, fixed_t limit_dist, fixed_t hoop_limit_dist) { - fixed_t approx_dist; - - if (! R_ThingVisible(thing)) - return false; - - approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); + const fixed_t approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); if (thing->sprite == SPR_HOOP) { @@ -3223,6 +3325,17 @@ boolean R_ThingVisibleWithinDist (mobj_t *thing, return true; } +// For OpenGL, TODO: REMOVE!! +boolean R_ThingVisibleWithinDist (mobj_t *thing, + fixed_t limit_dist, + fixed_t hoop_limit_dist) +{ + if (! R_ThingVisible(thing)) + return false; + + return R_ThingWithinDist(thing, limit_dist, hoop_limit_dist); +} + /* Check if precipitation may be drawn from our current view. */ boolean R_PrecipThingVisible (precipmobj_t *precipthing, fixed_t limit_dist) diff --git a/src/r_things.h b/src/r_things.h index 4ba649c30..f1855dfd8 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -67,10 +67,13 @@ void R_InitSprites(void); void R_ClearSprites(void); boolean R_ThingBoundingBoxVisible(mobj_t *thing); -void R_DrawThingBoundingBox(mobj_t *thing); boolean R_ThingVisible (mobj_t *thing); +boolean R_ThingWithinDist (mobj_t *thing, + fixed_t draw_dist, + fixed_t nights_draw_dist); + boolean R_ThingVisibleWithinDist (mobj_t *thing, fixed_t draw_dist, fixed_t nights_draw_dist); @@ -135,6 +138,7 @@ typedef enum SC_SHADOW = 1<<10, SC_SHEAR = 1<<11, SC_SPLAT = 1<<12, + SC_BBOX = 1<<13, // masks SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_FLAGMASK = ~SC_CUTMASK @@ -224,6 +228,9 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal); boolean R_SpriteIsFlashing(vissprite_t *vis); + +void R_DrawThingBoundingBox(vissprite_t *spr); + UINT8 *R_GetSpriteTranslation(vissprite_t *vis); // ---------- From 99653de13431d91ae9259dfd6c002861ea396156 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Sep 2022 06:25:08 -0700 Subject: [PATCH 059/478] Do not render viewmobj or skybox viewpoint hitbox If you are a spectator (or in first person), the hitbox exists right ontop of you and hitboxes don't render correctly if they are too close to the viewpoint. --- src/r_bbox.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/r_bbox.c b/src/r_bbox.c index bbac0f56b..3d46aa566 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -253,6 +253,27 @@ boolean R_ThingBoundingBoxVisible(mobj_t *thing) { INT32 cvmode = cv_renderhitbox.value; + // Do not render bbox for these + switch (thing->type) + { + default: + // First person / awayviewmobj -- rendering + // a bbox too close to the viewpoint causes + // anomalies and these are exactly on the + // viewpoint! + if (thing != r_viewmobj) + { + break; + } + // FALLTHRU + + case MT_SKYBOX: + // Ditto for skybox viewpoint but because they + // are rendered using portals in Software, + // r_viewmobj does not point here. + return false; + } + switch (cvmode) { case RENDERHITBOX_OFF: From 7527fdbb568358bc56755220945255c8adaefeae Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Sep 2022 07:08:10 -0700 Subject: [PATCH 060/478] Remedy some quirky rendering of hitboxes if your viewpoint is too close It's not correct but it's better than before. --- src/r_bbox.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/r_bbox.c b/src/r_bbox.c index 3d46aa566..e1749225c 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -82,8 +82,13 @@ draw_bbox_col { struct bbox_col *col = &bb->col[p]; - fixed_t xscale = FixedDiv(projection, ty); - fixed_t yscale = FixedDiv(projectiony, ty); + fixed_t xscale, yscale; + + if (ty < FRACUNIT) // projection breaks down here + ty = FRACUNIT; + + xscale = FixedDiv(projection, ty); + yscale = FixedDiv(projectiony, ty); col->x = (centerxfrac + FixedMul(tx, xscale)) / FRACUNIT; col->y = (centeryfrac - FixedMul(bb->tz, yscale)); From 5b53017a09eb70c94ffaae259350d765de901988 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Sep 2022 16:54:15 -0700 Subject: [PATCH 061/478] r_opengl: add PF_WireFrame and SHADER_NONE Draw lines instead of tris and disable shader entirely. --- src/hardware/hw_defs.h | 4 +++- src/hardware/r_opengl/r_opengl.c | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index fca9b80a3..bb27c34fa 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -136,6 +136,7 @@ typedef struct // Predefined shader types enum { + SHADER_NONE = -1, SHADER_DEFAULT = 0, SHADER_FLOOR, @@ -237,7 +238,8 @@ enum EPolyFlags PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y PF_ForceWrapX = 0x00020000, // Forces repeat texture on X PF_ForceWrapY = 0x00040000, // Forces repeat texture on Y - PF_Ripple = 0x00100000 // Water ripple effect. The current backend doesn't use it for anything. + PF_Ripple = 0x00100000, // Water ripple effect. The current backend doesn't use it for anything. + PF_WireFrame = 0x00200000, // Draws vertices as lines instead of triangles }; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 9d1630abb..3a97f9315 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1030,6 +1030,12 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole EXPORT void HWRAPI(SetShader) (int type) { #ifdef GL_SHADERS + if (type == SHADER_NONE) + { + HWRAPI(UnSetShader)(); + return; + } + if (gl_allowshaders != HWD_SHADEROPTION_OFF) { gl_shader_t *shader = gl_shaderstate.current; @@ -2290,7 +2296,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUI pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); - pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); + pglDrawArrays(PolyFlags & PF_WireFrame ? GL_LINES : GL_TRIANGLE_FAN, 0, iNumPts); if (PolyFlags & PF_RemoveYWrap) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); From bfaf2bc6f3635f3e95b8bf6172d9a2f6d3e22edf Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Sep 2022 16:57:58 -0700 Subject: [PATCH 062/478] OpenGL hitbox renderer I apologize for that vertex array. --- src/hardware/hw_glob.h | 1 + src/hardware/hw_main.c | 118 +++++++++++++++++++++++++++++++++++++++-- src/r_bbox.c | 9 ++-- src/r_things.h | 1 + 4 files changed, 120 insertions(+), 9 deletions(-) diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 1ec9101c3..504cdf148 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -81,6 +81,7 @@ typedef struct gl_vissprite_s boolean flip, vflip; boolean precip; // Tails 08-25-2002 + boolean bbox; boolean rotated; UINT8 translucency; //alpha level 0-255 diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3cb7275a0..24d5925bd 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -66,6 +66,7 @@ static void HWR_ProjectSprite(mobj_t *thing); #ifdef HWPRECIP static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif +static void HWR_ProjectBoundingBox(mobj_t *thing); void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, @@ -4036,6 +4037,54 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) HWR_LinkDrawHackAdd(wallVerts, spr); } +static void HWR_DrawBoundingBox(gl_vissprite_t *vis) +{ + FOutVector v[24]; + FSurfaceInfo Surf = {0}; + + // + // create a cube (side view) + // + // 5--4 3 + // | + // | + // 0--1 2 + // + // repeat this 4 times (overhead) + // + // + // 17 20 21 11 + // 16 15 14 10 + // 27 22 *--* 07 12 + // | | + // 26 23 *--* 06 13 + // 24 00 01 02 + // 25 05 04 03 + // + + v[000].x = v[005].x = v[015].x = v[016].x = v[017].x = v[020].x = + v[022].x = v[023].x = v[024].x = v[025].x = v[026].x = v[027].x = vis->x1; // west + + v[001].x = v[002].x = v[003].x = v[004].x = v[006].x = v[007].x = + v[010].x = v[011].x = v[012].x = v[013].x = v[014].x = v[021].x = vis->x2; // east + + v[000].z = v[001].z = v[002].z = v[003].z = v[004].z = v[005].z = + v[006].z = v[013].z = v[023].z = v[024].z = v[025].z = v[026].z = vis->z1; // south + + v[007].z = v[010].z = v[011].z = v[012].z = v[014].z = v[015].z = + v[016].z = v[017].z = v[020].z = v[021].z = v[022].z = v[027].z = vis->z2; // north + + v[000].y = v[001].y = v[002].y = v[006].y = v[007].y = v[010].y = + v[014].y = v[015].y = v[016].y = v[022].y = v[023].y = v[024].y = vis->gz; // bottom + + v[003].y = v[004].y = v[005].y = v[011].y = v[012].y = v[013].y = + v[017].y = v[020].y = v[021].y = v[025].y = v[026].y = v[027].y = vis->gzt; // top + + Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj)); + + HWR_ProcessPolygon(&Surf, v, 24, PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false); +} + // -----------------+ // HWR_DrawSprite : Draw flat sprites // : (monsters, bonuses, weapons, lights, ...) @@ -4480,9 +4529,16 @@ static int CompareVisSprites(const void *p1, const void *p2) int transparency1; int transparency2; + int linkdraw1; + int linkdraw2; + + // bbox doesn't need to be sorted + if (spr1->bbox || spr2->bbox) + return 0; + // check for precip first, because then sprX->mobj is actually a precipmobj_t and does not have flags2 or tracer - int linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer; - int linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer; + linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer; + linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer; // ^ is the XOR operation // if comparing a linkdraw and non-linkdraw sprite or 2 linkdraw sprites with different tracers, then use @@ -4852,6 +4908,9 @@ static void HWR_DrawSprites(void) for (i = 0; i < gl_visspritecount; i++) { gl_vissprite_t *spr = gl_vsprorder[i]; + if (spr->bbox) + HWR_DrawBoundingBox(spr); + else #ifdef HWPRECIP if (spr->precip) HWR_DrawPrecipitationSprite(spr); @@ -4951,8 +5010,15 @@ static void HWR_AddSprites(sector_t *sec) hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS; for (thing = sec->thinglist; thing; thing = thing->snext) { - if (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist)) - HWR_ProjectSprite(thing); + if (R_ThingWithinDist(thing, limit_dist, hoop_limit_dist)) + { + if (R_ThingVisible(thing)) + { + HWR_ProjectSprite(thing); + } + + HWR_ProjectBoundingBox(thing); + } } #ifdef HWPRECIP @@ -5462,6 +5528,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->vflip = vflip; vis->precip = false; + vis->bbox = false; vis->angle = interp.angle; } @@ -5584,6 +5651,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height); vis->precip = true; + vis->bbox = false; // okay... this is a hack, but weather isn't networked, so it should be ok if (!(thing->precipflags & PCF_THUNK)) @@ -5597,6 +5665,48 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) } #endif +static void HWR_ProjectBoundingBox(mobj_t *thing) +{ + gl_vissprite_t *vis; + float tr_x, tr_y; + float tz; + float rad; + + if (!thing) + return; + + if (!R_ThingBoundingBoxVisible(thing)) + return; + + // transform the origin point + tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; + tr_y = FIXED_TO_FLOAT(thing->y) - gl_viewy; + + // rotation around vertical axis + tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); + + // thing is behind view plane? + if (tz < ZCLIP_PLANE) + return; + + tr_x += gl_viewx; + tr_y += gl_viewy; + + rad = FIXED_TO_FLOAT(thing->radius); + + vis = HWR_NewVisSprite(); + vis->x1 = tr_x - rad; + vis->x2 = tr_x + rad; + vis->z1 = tr_y - rad; + vis->z2 = tr_y + rad; + vis->gz = FIXED_TO_FLOAT(thing->z); + vis->gzt = vis->gz + FIXED_TO_FLOAT(thing->height); + vis->mobj = thing; + + vis->precip = false; + vis->bbox = true; +} + // ========================================================================== // Sky dome rendering, ported from PrBoom+ // ========================================================================== diff --git a/src/r_bbox.c b/src/r_bbox.c index e1749225c..9108ec0c0 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -169,12 +169,11 @@ draw_bbox_row } } -static UINT8 -get_bbox_color (vissprite_t *vis) +UINT8 R_GetBoundingBoxColor(mobj_t *thing) { - UINT32 flags = vis->mobjflags; + UINT32 flags = thing->flags; - if (vis->mobj->player) + if (thing->player) return 255; // 0FF if (flags & (MF_NOCLIPTHING)) @@ -205,7 +204,7 @@ void R_DrawThingBoundingBox(vissprite_t *vis) struct bbox_config bb = { .height = vis->thingheight, .tz = vis->texturemid, - .color = get_bbox_color(vis), + .color = R_GetBoundingBoxColor(vis->mobj), }; // 1--3 diff --git a/src/r_things.h b/src/r_things.h index f1855dfd8..9aa1003da 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -66,6 +66,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_InitSprites(void); void R_ClearSprites(void); +UINT8 R_GetBoundingBoxColor(mobj_t *thing); boolean R_ThingBoundingBoxVisible(mobj_t *thing); boolean R_ThingVisible (mobj_t *thing); From 7855bae8a13f4787ecc6badb11fbf2c96e582515 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Sep 2022 16:59:25 -0700 Subject: [PATCH 063/478] Remove R_ThingVisibleWithinDist It's no longer used! --- src/r_things.c | 11 ----------- src/r_things.h | 4 ---- 2 files changed, 15 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 6e4062219..953f12ea6 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -3325,17 +3325,6 @@ boolean R_ThingWithinDist (mobj_t *thing, return true; } -// For OpenGL, TODO: REMOVE!! -boolean R_ThingVisibleWithinDist (mobj_t *thing, - fixed_t limit_dist, - fixed_t hoop_limit_dist) -{ - if (! R_ThingVisible(thing)) - return false; - - return R_ThingWithinDist(thing, limit_dist, hoop_limit_dist); -} - /* Check if precipitation may be drawn from our current view. */ boolean R_PrecipThingVisible (precipmobj_t *precipthing, fixed_t limit_dist) diff --git a/src/r_things.h b/src/r_things.h index 9aa1003da..84d5967ab 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -75,10 +75,6 @@ boolean R_ThingWithinDist (mobj_t *thing, fixed_t draw_dist, fixed_t nights_draw_dist); -boolean R_ThingVisibleWithinDist (mobj_t *thing, - fixed_t draw_dist, - fixed_t nights_draw_dist); - boolean R_PrecipThingVisible (precipmobj_t *precipthing, fixed_t precip_draw_dist); From f7fa9fcc190f0ba4fb8ad3ef15465f6c37ea9443 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 12 Sep 2022 12:58:39 +0100 Subject: [PATCH 064/478] Fix compilation issue with nested defines for r_opengl.c UnSetShader --- src/hardware/r_opengl/r_opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 3a97f9315..98929f030 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1032,7 +1032,7 @@ EXPORT void HWRAPI(SetShader) (int type) #ifdef GL_SHADERS if (type == SHADER_NONE) { - HWRAPI(UnSetShader)(); + UnSetShader(); return; } From 8430dfa0639c06b0d48b34a76e1abe14af4885ce Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 25 Oct 2022 12:03:18 -0700 Subject: [PATCH 065/478] Fix copyright year in r_bbox.c --- src/r_bbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_bbox.c b/src/r_bbox.c index 9108ec0c0..cc225eaec 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2021 by Sonic Team Junior. // Copyright (C) 2022 by Kart Krew. +// Copyright (C) 1999-2022 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. From 5411d522e5143caed15d23693bba175f0b1d19f3 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 26 Oct 2022 13:53:35 -0700 Subject: [PATCH 066/478] r_bbox.c: use size_t to access column array --- src/r_bbox.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_bbox.c b/src/r_bbox.c index cc225eaec..b45007bb2 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -76,7 +76,7 @@ raster_bbox_seg static void draw_bbox_col ( struct bbox_config * bb, - int p, + size_t p, fixed_t tx, fixed_t ty) { @@ -104,8 +104,8 @@ draw_bbox_col static void draw_bbox_row ( struct bbox_config * bb, - int p1, - int p2) + size_t p1, + size_t p2) { struct bbox_col *a = &bb->col[p1], From 34cc1d1cc4a8c27c86b71ee7c94d0c1fc177f187 Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Wed, 23 Nov 2022 17:09:54 +0000 Subject: [PATCH 067/478] Exposed floor/ceiling pic x/y offsets to Lua. --- src/lua_maplib.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index b4565121d..4b90bc013 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -33,7 +33,13 @@ enum sector_e { sector_floorheight, sector_ceilingheight, sector_floorpic, + sector_floorxoffs, + sector_flooryoffs, + sector_floorpicangle, sector_ceilingpic, + sector_ceilingxoffs, + sector_ceilingyoffs, + sector_ceilingpicangle, sector_lightlevel, sector_floorlightlevel, sector_floorlightabsolute, @@ -63,7 +69,13 @@ static const char *const sector_opt[] = { "floorheight", "ceilingheight", "floorpic", + "floorxoffs", + "flooryoffs", + "floorpicangle", "ceilingpic", + "ceilingxoffs", + "ceilingyoffs", + "ceilingpicangle", "lightlevel", "floorlightlevel", "floorlightabsolute", @@ -607,6 +619,21 @@ static int sector_get(lua_State *L) lua_pushlstring(L, levelflat->name, i); return 1; } + case sector_floorxoffs: + { + lua_pushfixed(L, sector->floor_xoffs); + return 1; + } + case sector_flooryoffs: + { + lua_pushfixed(L, sector->floor_yoffs); + return 1; + } + case sector_floorpicangle: + { + lua_pushangle(L, sector->floorpic_angle); + return 1; + } case sector_ceilingpic: // ceilingpic { levelflat_t *levelflat = &levelflats[sector->ceilingpic]; @@ -616,6 +643,21 @@ static int sector_get(lua_State *L) lua_pushlstring(L, levelflat->name, i); return 1; } + case sector_ceilingxoffs: + { + lua_pushfixed(L, sector->ceiling_xoffs); + return 1; + } + case sector_ceilingyoffs: + { + lua_pushfixed(L, sector->ceiling_yoffs); + return 1; + } + case sector_ceilingpicangle: + { + lua_pushangle(L, sector->ceilingpic_angle); + return 1; + } case sector_lightlevel: lua_pushinteger(L, sector->lightlevel); return 1; @@ -751,9 +793,27 @@ static int sector_set(lua_State *L) case sector_floorpic: sector->floorpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; + case sector_floorxoffs: + sector->floor_xoffs = luaL_checkfixed(L, 3); + break; + case sector_flooryoffs: + sector->floor_yoffs = luaL_checkfixed(L, 3); + break; + case sector_floorpicangle: + sector->floorpic_angle = luaL_checkangle(L, 3); + break; case sector_ceilingpic: sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; + case sector_ceilingxoffs: + sector->ceiling_xoffs = luaL_checkfixed(L, 3); + break; + case sector_ceilingyoffs: + sector->ceiling_yoffs = luaL_checkfixed(L, 3); + break; + case sector_ceilingpicangle: + sector->ceilingpic_angle = luaL_checkangle(L, 3); + break; case sector_lightlevel: sector->lightlevel = (INT16)luaL_checkinteger(L, 3); break; From e789bf1fb241148d6dbd54c2e0efc7059b032b44 Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Wed, 23 Nov 2022 17:29:44 +0000 Subject: [PATCH 068/478] Fix for consistency just *angle for *_angle --- src/lua_maplib.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 4b90bc013..ff732af29 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -35,11 +35,11 @@ enum sector_e { sector_floorpic, sector_floorxoffs, sector_flooryoffs, - sector_floorpicangle, + sector_floorpic_angle, sector_ceilingpic, sector_ceilingxoffs, sector_ceilingyoffs, - sector_ceilingpicangle, + sector_ceilingpic_angle, sector_lightlevel, sector_floorlightlevel, sector_floorlightabsolute, @@ -71,11 +71,11 @@ static const char *const sector_opt[] = { "floorpic", "floorxoffs", "flooryoffs", - "floorpicangle", + "floorpic_angle", "ceilingpic", "ceilingxoffs", "ceilingyoffs", - "ceilingpicangle", + "ceilingpic_angle", "lightlevel", "floorlightlevel", "floorlightabsolute", @@ -629,7 +629,7 @@ static int sector_get(lua_State *L) lua_pushfixed(L, sector->floor_yoffs); return 1; } - case sector_floorpicangle: + case sector_floorpic_angle: { lua_pushangle(L, sector->floorpic_angle); return 1; @@ -653,7 +653,7 @@ static int sector_get(lua_State *L) lua_pushfixed(L, sector->ceiling_yoffs); return 1; } - case sector_ceilingpicangle: + case sector_ceilingpic_angle: { lua_pushangle(L, sector->ceilingpic_angle); return 1; @@ -799,7 +799,7 @@ static int sector_set(lua_State *L) case sector_flooryoffs: sector->floor_yoffs = luaL_checkfixed(L, 3); break; - case sector_floorpicangle: + case sector_floorpic_angle: sector->floorpic_angle = luaL_checkangle(L, 3); break; case sector_ceilingpic: @@ -811,7 +811,7 @@ static int sector_set(lua_State *L) case sector_ceilingyoffs: sector->ceiling_yoffs = luaL_checkfixed(L, 3); break; - case sector_ceilingpicangle: + case sector_ceilingpic_angle: sector->ceilingpic_angle = luaL_checkangle(L, 3); break; case sector_lightlevel: From 27c6afb80b2a67ec1197dca5d9a96e9fec6de512 Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Thu, 24 Nov 2022 18:51:53 +0000 Subject: [PATCH 069/478] Yikes. how did I miss "_" on every single variable --- src/lua_maplib.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index ff732af29..0def825e1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -33,12 +33,12 @@ enum sector_e { sector_floorheight, sector_ceilingheight, sector_floorpic, - sector_floorxoffs, - sector_flooryoffs, + sector_floor_xoffs, + sector_floor_yoffs, sector_floorpic_angle, sector_ceilingpic, - sector_ceilingxoffs, - sector_ceilingyoffs, + sector_ceiling_xoffs, + sector_ceiling_yoffs, sector_ceilingpic_angle, sector_lightlevel, sector_floorlightlevel, @@ -69,12 +69,12 @@ static const char *const sector_opt[] = { "floorheight", "ceilingheight", "floorpic", - "floorxoffs", - "flooryoffs", + "floor_xoffs", + "floor_yoffs", "floorpic_angle", "ceilingpic", - "ceilingxoffs", - "ceilingyoffs", + "ceiling_xoffs", + "ceiling_yoffs", "ceilingpic_angle", "lightlevel", "floorlightlevel", @@ -619,12 +619,12 @@ static int sector_get(lua_State *L) lua_pushlstring(L, levelflat->name, i); return 1; } - case sector_floorxoffs: + case sector_floor_xoffs: { lua_pushfixed(L, sector->floor_xoffs); return 1; } - case sector_flooryoffs: + case sector_floor_yoffs: { lua_pushfixed(L, sector->floor_yoffs); return 1; @@ -643,12 +643,12 @@ static int sector_get(lua_State *L) lua_pushlstring(L, levelflat->name, i); return 1; } - case sector_ceilingxoffs: + case sector_ceiling_xoffs: { lua_pushfixed(L, sector->ceiling_xoffs); return 1; } - case sector_ceilingyoffs: + case sector_ceiling_yoffs: { lua_pushfixed(L, sector->ceiling_yoffs); return 1; @@ -793,10 +793,10 @@ static int sector_set(lua_State *L) case sector_floorpic: sector->floorpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; - case sector_floorxoffs: + case sector_floor_xoffs: sector->floor_xoffs = luaL_checkfixed(L, 3); break; - case sector_flooryoffs: + case sector_floor_yoffs: sector->floor_yoffs = luaL_checkfixed(L, 3); break; case sector_floorpic_angle: @@ -805,10 +805,10 @@ static int sector_set(lua_State *L) case sector_ceilingpic: sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; - case sector_ceilingxoffs: + case sector_ceiling_xoffs: sector->ceiling_xoffs = luaL_checkfixed(L, 3); break; - case sector_ceilingyoffs: + case sector_ceiling_yoffs: sector->ceiling_yoffs = luaL_checkfixed(L, 3); break; case sector_ceilingpic_angle: From 9d4a3b91c3c33d8e8945d90a61584336c41e461f Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Fri, 25 Nov 2022 22:27:41 +0000 Subject: [PATCH 070/478] change names of Lua variables for last time. --- src/lua_maplib.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0def825e1..7908a1d72 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -33,13 +33,13 @@ enum sector_e { sector_floorheight, sector_ceilingheight, sector_floorpic, - sector_floor_xoffs, - sector_floor_yoffs, - sector_floorpic_angle, + sector_floorxoffset, + sector_flooryoffset, + sector_floorangle, sector_ceilingpic, - sector_ceiling_xoffs, - sector_ceiling_yoffs, - sector_ceilingpic_angle, + sector_ceilingxoffset, + sector_ceilingyoffset, + sector_ceilingangle, sector_lightlevel, sector_floorlightlevel, sector_floorlightabsolute, @@ -69,13 +69,13 @@ static const char *const sector_opt[] = { "floorheight", "ceilingheight", "floorpic", - "floor_xoffs", - "floor_yoffs", - "floorpic_angle", + "floorxoffset", + "flooryoffset", + "floorangle", "ceilingpic", - "ceiling_xoffs", - "ceiling_yoffs", - "ceilingpic_angle", + "ceilingxoffset", + "ceilingyoffset", + "ceilingangle", "lightlevel", "floorlightlevel", "floorlightabsolute", @@ -619,17 +619,17 @@ static int sector_get(lua_State *L) lua_pushlstring(L, levelflat->name, i); return 1; } - case sector_floor_xoffs: + case sector_floorxoffset: { lua_pushfixed(L, sector->floor_xoffs); return 1; } - case sector_floor_yoffs: + case sector_flooryoffset: { lua_pushfixed(L, sector->floor_yoffs); return 1; } - case sector_floorpic_angle: + case sector_floorangle: { lua_pushangle(L, sector->floorpic_angle); return 1; @@ -643,17 +643,17 @@ static int sector_get(lua_State *L) lua_pushlstring(L, levelflat->name, i); return 1; } - case sector_ceiling_xoffs: + case sector_ceilingxoffset: { lua_pushfixed(L, sector->ceiling_xoffs); return 1; } - case sector_ceiling_yoffs: + case sector_ceilingyoffset: { lua_pushfixed(L, sector->ceiling_yoffs); return 1; } - case sector_ceilingpic_angle: + case sector_ceilingangle: { lua_pushangle(L, sector->ceilingpic_angle); return 1; @@ -793,25 +793,25 @@ static int sector_set(lua_State *L) case sector_floorpic: sector->floorpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; - case sector_floor_xoffs: + case sector_floorxoffset: sector->floor_xoffs = luaL_checkfixed(L, 3); break; - case sector_floor_yoffs: + case sector_flooryoffset: sector->floor_yoffs = luaL_checkfixed(L, 3); break; - case sector_floorpic_angle: + case sector_floorangle: sector->floorpic_angle = luaL_checkangle(L, 3); break; case sector_ceilingpic: sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; - case sector_ceiling_xoffs: + case sector_ceilingxoffset: sector->ceiling_xoffs = luaL_checkfixed(L, 3); break; - case sector_ceiling_yoffs: + case sector_ceilingyoffset: sector->ceiling_yoffs = luaL_checkfixed(L, 3); break; - case sector_ceilingpic_angle: + case sector_ceilingangle: sector->ceilingpic_angle = luaL_checkangle(L, 3); break; case sector_lightlevel: From 3217984f55720b30a5f43df32cacdb6f89466ccf Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Fri, 25 Nov 2022 23:01:27 +0000 Subject: [PATCH 071/478] c-side offset/angle variable renamed --- src/hardware/hw_main.c | 32 ++++++------- src/lua_maplib.c | 24 +++++----- src/p_saveg.c | 36 +++++++------- src/p_setup.c | 106 ++++++++++++++++++++--------------------- src/p_spec.c | 32 ++++++------- src/r_bsp.c | 58 +++++++++++----------- src/r_defs.h | 8 ++-- src/r_fps.c | 16 +++---- src/r_segs.c | 12 ++--- 9 files changed, 162 insertions(+), 162 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3cb7275a0..2b376544a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -459,30 +459,30 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; - angle = FOFsector->floorpic_angle; + scrollx = FIXED_TO_FLOAT(FOFsector->floorxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->flooryoffset)/fflatheight; + angle = FOFsector->floorangle; } else // it's a ceiling { scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; - angle = FOFsector->ceilingpic_angle; + angle = FOFsector->ceilingangle; } } else if (gl_frontsector) { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight; - angle = gl_frontsector->floorpic_angle; + scrollx = FIXED_TO_FLOAT(gl_frontsector->floorxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->flooryoffset)/fflatheight; + angle = gl_frontsector->floorangle; } else // it's a ceiling { scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth; scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight; - angle = gl_frontsector->ceilingpic_angle; + angle = gl_frontsector->ceilingangle; } } @@ -2719,30 +2719,30 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; - angle = FOFsector->floorpic_angle; + scrollx = FIXED_TO_FLOAT(FOFsector->floorxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->flooryoffset)/fflatheight; + angle = FOFsector->floorangle; } else // it's a ceiling { scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; - angle = FOFsector->ceilingpic_angle; + angle = FOFsector->ceilingangle; } } else if (gl_frontsector) { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight; - angle = gl_frontsector->floorpic_angle; + scrollx = FIXED_TO_FLOAT(gl_frontsector->floorxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->flooryoffset)/fflatheight; + angle = gl_frontsector->floorangle; } else // it's a ceiling { scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth; scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight; - angle = gl_frontsector->ceilingpic_angle; + angle = gl_frontsector->ceilingangle; } } diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 7908a1d72..79909a6be 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -621,17 +621,17 @@ static int sector_get(lua_State *L) } case sector_floorxoffset: { - lua_pushfixed(L, sector->floor_xoffs); + lua_pushfixed(L, sector->floorxoffset); return 1; } case sector_flooryoffset: { - lua_pushfixed(L, sector->floor_yoffs); + lua_pushfixed(L, sector->flooryoffset); return 1; } case sector_floorangle: { - lua_pushangle(L, sector->floorpic_angle); + lua_pushangle(L, sector->floorangle); return 1; } case sector_ceilingpic: // ceilingpic @@ -645,17 +645,17 @@ static int sector_get(lua_State *L) } case sector_ceilingxoffset: { - lua_pushfixed(L, sector->ceiling_xoffs); + lua_pushfixed(L, sector->ceilingxoffset); return 1; } case sector_ceilingyoffset: { - lua_pushfixed(L, sector->ceiling_yoffs); + lua_pushfixed(L, sector->ceilingyoffset); return 1; } case sector_ceilingangle: { - lua_pushangle(L, sector->ceilingpic_angle); + lua_pushangle(L, sector->ceilingangle); return 1; } case sector_lightlevel: @@ -794,25 +794,25 @@ static int sector_set(lua_State *L) sector->floorpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; case sector_floorxoffset: - sector->floor_xoffs = luaL_checkfixed(L, 3); + sector->floorxoffset = luaL_checkfixed(L, 3); break; case sector_flooryoffset: - sector->floor_yoffs = luaL_checkfixed(L, 3); + sector->flooryoffset = luaL_checkfixed(L, 3); break; case sector_floorangle: - sector->floorpic_angle = luaL_checkangle(L, 3); + sector->floorangle = luaL_checkangle(L, 3); break; case sector_ceilingpic: sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; case sector_ceilingxoffset: - sector->ceiling_xoffs = luaL_checkfixed(L, 3); + sector->ceilingxoffset = luaL_checkfixed(L, 3); break; case sector_ceilingyoffset: - sector->ceiling_yoffs = luaL_checkfixed(L, 3); + sector->ceilingyoffset = luaL_checkfixed(L, 3); break; case sector_ceilingangle: - sector->ceilingpic_angle = luaL_checkangle(L, 3); + sector->ceilingangle = luaL_checkangle(L, 3); break; case sector_lightlevel: sector->lightlevel = (INT16)luaL_checkinteger(L, 3); diff --git a/src/p_saveg.c b/src/p_saveg.c index ce7353b95..464372d68 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1022,17 +1022,17 @@ static void ArchiveSectors(void) if (ss->special != spawnss->special) diff |= SD_SPECIAL; - if (ss->floor_xoffs != spawnss->floor_xoffs) + if (ss->floorxoffset != spawnss->floorxoffset) diff2 |= SD_FXOFFS; - if (ss->floor_yoffs != spawnss->floor_yoffs) + if (ss->flooryoffset != spawnss->flooryoffset) diff2 |= SD_FYOFFS; - if (ss->ceiling_xoffs != spawnss->ceiling_xoffs) + if (ss->ceilingxoffset != spawnss->ceilingxoffset) diff2 |= SD_CXOFFS; - if (ss->ceiling_yoffs != spawnss->ceiling_yoffs) + if (ss->ceilingyoffset != spawnss->ceilingyoffset) diff2 |= SD_CYOFFS; - if (ss->floorpic_angle != spawnss->floorpic_angle) + if (ss->floorangle != spawnss->floorangle) diff2 |= SD_FLOORANG; - if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) + if (ss->ceilingangle != spawnss->ceilingangle) diff2 |= SD_CEILANG; if (!Tag_Compare(&ss->tags, &spawnss->tags)) @@ -1095,17 +1095,17 @@ static void ArchiveSectors(void) if (diff & SD_SPECIAL) WRITEINT16(save_p, ss->special); if (diff2 & SD_FXOFFS) - WRITEFIXED(save_p, ss->floor_xoffs); + WRITEFIXED(save_p, ss->floorxoffset); if (diff2 & SD_FYOFFS) - WRITEFIXED(save_p, ss->floor_yoffs); + WRITEFIXED(save_p, ss->flooryoffset); if (diff2 & SD_CXOFFS) - WRITEFIXED(save_p, ss->ceiling_xoffs); + WRITEFIXED(save_p, ss->ceilingxoffset); if (diff2 & SD_CYOFFS) - WRITEFIXED(save_p, ss->ceiling_yoffs); + WRITEFIXED(save_p, ss->ceilingyoffset); if (diff2 & SD_FLOORANG) - WRITEANGLE(save_p, ss->floorpic_angle); + WRITEANGLE(save_p, ss->floorangle); if (diff2 & SD_CEILANG) - WRITEANGLE(save_p, ss->ceilingpic_angle); + WRITEANGLE(save_p, ss->ceilingangle); if (diff2 & SD_TAG) { WRITEUINT32(save_p, ss->tags.count); @@ -1196,17 +1196,17 @@ static void UnArchiveSectors(void) sectors[i].special = READINT16(save_p); if (diff2 & SD_FXOFFS) - sectors[i].floor_xoffs = READFIXED(save_p); + sectors[i].floorxoffset = READFIXED(save_p); if (diff2 & SD_FYOFFS) - sectors[i].floor_yoffs = READFIXED(save_p); + sectors[i].flooryoffset = READFIXED(save_p); if (diff2 & SD_CXOFFS) - sectors[i].ceiling_xoffs = READFIXED(save_p); + sectors[i].ceilingxoffset = READFIXED(save_p); if (diff2 & SD_CYOFFS) - sectors[i].ceiling_yoffs = READFIXED(save_p); + sectors[i].ceilingyoffset = READFIXED(save_p); if (diff2 & SD_FLOORANG) - sectors[i].floorpic_angle = READANGLE(save_p); + sectors[i].floorangle = READANGLE(save_p); if (diff2 & SD_CEILANG) - sectors[i].ceilingpic_angle = READANGLE(save_p); + sectors[i].ceilingangle = READANGLE(save_p); if (diff2 & SD_TAG) { size_t ncount = READUINT32(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index deb308da2..20790a48b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1049,10 +1049,10 @@ static void P_LoadSectors(UINT8 *data) ss->special = SHORT(ms->special); Tag_FSet(&ss->tags, SHORT(ms->tag)); - ss->floor_xoffs = ss->floor_yoffs = 0; - ss->ceiling_xoffs = ss->ceiling_yoffs = 0; + ss->floorxoffset = ss->flooryoffset = 0; + ss->ceilingxoffset = ss->ceilingyoffset = 0; - ss->floorpic_angle = ss->ceilingpic_angle = 0; + ss->floorangle = ss->ceilingangle = 0; ss->floorlightlevel = ss->ceilinglightlevel = 0; ss->floorlightabsolute = ss->ceilinglightabsolute = false; @@ -1578,19 +1578,19 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char if ((id = strchr(id, ' '))) id++; } - } + } else if (fastcmp(param, "xpanningfloor")) - sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val)); + sectors[i].floorxoffset = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "ypanningfloor")) - sectors[i].floor_yoffs = FLOAT_TO_FIXED(atof(val)); + sectors[i].flooryoffset = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "xpanningceiling")) - sectors[i].ceiling_xoffs = FLOAT_TO_FIXED(atof(val)); + sectors[i].ceilingxoffset = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "ypanningceiling")) - sectors[i].ceiling_yoffs = FLOAT_TO_FIXED(atof(val)); + sectors[i].ceilingyoffset = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "rotationfloor")) - sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); + sectors[i].floorangle = FixedAngle(FLOAT_TO_FIXED(atof(val))); else if (fastcmp(param, "rotationceiling")) - sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); + sectors[i].ceilingangle = FixedAngle(FLOAT_TO_FIXED(atof(val))); else if (fastcmp(param, "floorplane_a")) { textmap_planefloor.defined |= PD_A; @@ -1959,47 +1959,47 @@ static void TextmapParse(UINT32 dataPos, size_t num, void (*parser)(UINT32, cons */ static void TextmapFixFlatOffsets(sector_t *sec) { - if (sec->floorpic_angle) + if (sec->floorangle) { - fixed_t pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT); - fixed_t ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT); - fixed_t xoffs = sec->floor_xoffs; - fixed_t yoffs = sec->floor_yoffs; - sec->floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); - sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + fixed_t pc = FINECOSINE(sec->floorangle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->floorangle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->floorxoffset; + fixed_t yoffs = sec->flooryoffset; + sec->floorxoffset = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->flooryoffset = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); } - if (sec->ceilingpic_angle) + if (sec->ceilingangle) { - fixed_t pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT); - fixed_t ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); - fixed_t xoffs = sec->ceiling_xoffs; - fixed_t yoffs = sec->ceiling_yoffs; - sec->ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); - sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + fixed_t pc = FINECOSINE(sec->ceilingangle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->ceilingangle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->ceilingxoffset; + fixed_t yoffs = sec->ceilingyoffset; + sec->ceilingxoffset = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->ceilingyoffset = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); } } static void TextmapUnfixFlatOffsets(sector_t *sec) { - if (sec->floorpic_angle) + if (sec->floorangle) { - fixed_t pc = FINECOSINE(sec->floorpic_angle >> ANGLETOFINESHIFT); - fixed_t ps = FINESINE(sec->floorpic_angle >> ANGLETOFINESHIFT); - fixed_t xoffs = sec->floor_xoffs; - fixed_t yoffs = sec->floor_yoffs; - sec->floor_xoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - sec->floor_yoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + fixed_t pc = FINECOSINE(sec->floorangle >> ANGLETOFINESHIFT); + fixed_t ps = FINESINE(sec->floorangle >> ANGLETOFINESHIFT); + fixed_t xoffs = sec->floorxoffset; + fixed_t yoffs = sec->flooryoffset; + sec->floorxoffset = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + sec->flooryoffset = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); } - if (sec->ceilingpic_angle) + if (sec->ceilingangle) { - fixed_t pc = FINECOSINE(sec->ceilingpic_angle >> ANGLETOFINESHIFT); - fixed_t ps = FINESINE(sec->ceilingpic_angle >> ANGLETOFINESHIFT); - fixed_t xoffs = sec->ceiling_xoffs; - fixed_t yoffs = sec->ceiling_yoffs; - sec->ceiling_xoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); - sec->ceiling_yoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + fixed_t pc = FINECOSINE(sec->ceilingangle >> ANGLETOFINESHIFT); + fixed_t ps = FINESINE(sec->ceilingangle >> ANGLETOFINESHIFT); + fixed_t xoffs = sec->ceilingxoffset; + fixed_t yoffs = sec->ceilingyoffset; + sec->ceilingxoffset = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + sec->ceilingyoffset = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); } } @@ -2492,18 +2492,18 @@ static void P_WriteTextmap(void) } sector_t tempsec = wsectors[i]; TextmapUnfixFlatOffsets(&tempsec); - if (tempsec.floor_xoffs != 0) - fprintf(f, "xpanningfloor = %f;\n", FIXED_TO_FLOAT(tempsec.floor_xoffs)); - if (tempsec.floor_yoffs != 0) - fprintf(f, "ypanningfloor = %f;\n", FIXED_TO_FLOAT(tempsec.floor_yoffs)); - if (tempsec.ceiling_xoffs != 0) - fprintf(f, "xpanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceiling_xoffs)); - if (tempsec.ceiling_yoffs != 0) - fprintf(f, "ypanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceiling_yoffs)); - if (wsectors[i].floorpic_angle != 0) - fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].floorpic_angle))); - if (wsectors[i].ceilingpic_angle != 0) - fprintf(f, "rotationceiling = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].ceilingpic_angle))); + if (tempsec.floorxoffset != 0) + fprintf(f, "xpanningfloor = %f;\n", FIXED_TO_FLOAT(tempsec.floorxoffset)); + if (tempsec.flooryoffset != 0) + fprintf(f, "ypanningfloor = %f;\n", FIXED_TO_FLOAT(tempsec.flooryoffset)); + if (tempsec.ceilingxoffset != 0) + fprintf(f, "xpanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceilingxoffset)); + if (tempsec.ceilingyoffset != 0) + fprintf(f, "ypanningceiling = %f;\n", FIXED_TO_FLOAT(tempsec.ceilingyoffset)); + if (wsectors[i].floorangle != 0) + fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].floorangle))); + if (wsectors[i].ceilingangle != 0) + fprintf(f, "rotationceiling = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].ceilingangle))); if (wsectors[i].extra_colormap) { INT32 lightcolor = P_RGBAToColor(wsectors[i].extra_colormap->rgba); @@ -2708,10 +2708,10 @@ static void P_LoadTextmap(void) sc->special = 0; Tag_FSet(&sc->tags, 0); - sc->floor_xoffs = sc->floor_yoffs = 0; - sc->ceiling_xoffs = sc->ceiling_yoffs = 0; + sc->floorxoffset = sc->flooryoffset = 0; + sc->ceilingxoffset = sc->ceilingyoffset = 0; - sc->floorpic_angle = sc->ceilingpic_angle = 0; + sc->floorangle = sc->ceilingangle = 0; sc->floorlightlevel = sc->ceilinglightlevel = 0; sc->floorlightabsolute = sc->ceilinglightabsolute = false; diff --git a/src/p_spec.c b/src/p_spec.c index 82337d2f6..d781ea7d7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5570,17 +5570,17 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I fflr->target = sec; fflr->bottomheight = &sec2->floorheight; fflr->bottompic = &sec2->floorpic; - fflr->bottomxoffs = &sec2->floor_xoffs; - fflr->bottomyoffs = &sec2->floor_yoffs; - fflr->bottomangle = &sec2->floorpic_angle; + fflr->bottomxoffs = &sec2->floorxoffset; + fflr->bottomyoffs = &sec2->flooryoffset; + fflr->bottomangle = &sec2->floorangle; // Add the ceiling fflr->topheight = &sec2->ceilingheight; fflr->toppic = &sec2->ceilingpic; fflr->toplightlevel = &sec2->lightlevel; - fflr->topxoffs = &sec2->ceiling_xoffs; - fflr->topyoffs = &sec2->ceiling_yoffs; - fflr->topangle = &sec2->ceilingpic_angle; + fflr->topxoffs = &sec2->ceilingxoffset; + fflr->topyoffs = &sec2->ceilingyoffset; + fflr->topangle = &sec2->ceilingangle; // Add slopes fflr->t_slope = &sec2->c_slope; @@ -6098,16 +6098,16 @@ void P_ApplyFlatAlignment(sector_t *sector, angle_t flatangle, fixed_t xoffs, fi { if (floor) { - sector->floorpic_angle = flatangle; - sector->floor_xoffs += xoffs; - sector->floor_yoffs += yoffs; + sector->floorangle = flatangle; + sector->floorxoffset += xoffs; + sector->flooryoffset += yoffs; } if (ceiling) { - sector->ceilingpic_angle = flatangle; - sector->ceiling_xoffs += xoffs; - sector->ceiling_yoffs += yoffs; + sector->ceilingangle = flatangle; + sector->ceilingxoffset += xoffs; + sector->ceilingyoffset += yoffs; } } @@ -7349,14 +7349,14 @@ void T_Scroll(scroll_t *s) case sc_floor: // scroll floor texture sec = sectors + s->affectee; - sec->floor_xoffs += dx; - sec->floor_yoffs += dy; + sec->floorxoffset += dx; + sec->flooryoffset += dy; break; case sc_ceiling: // scroll ceiling texture sec = sectors + s->affectee; - sec->ceiling_xoffs += dx; - sec->ceiling_yoffs += dy; + sec->ceilingxoffset += dx; + sec->ceilingyoffset += dy; break; case sc_carry: diff --git a/src/r_bsp.c b/src/r_bsp.c index bf238a435..129c6ba00 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -275,9 +275,9 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight) { // head-below-floor hack tempsec->floorpic = s->floorpic; - tempsec->floor_xoffs = s->floor_xoffs; - tempsec->floor_yoffs = s->floor_yoffs; - tempsec->floorpic_angle = s->floorpic_angle; + tempsec->floorxoffset = s->floorxoffset; + tempsec->flooryoffset = s->flooryoffset; + tempsec->floorangle = s->floorangle; if (underwater) { @@ -285,16 +285,16 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, { tempsec->floorheight = tempsec->ceilingheight+1; tempsec->ceilingpic = tempsec->floorpic; - tempsec->ceiling_xoffs = tempsec->floor_xoffs; - tempsec->ceiling_yoffs = tempsec->floor_yoffs; - tempsec->ceilingpic_angle = tempsec->floorpic_angle; + tempsec->ceilingxoffset = tempsec->floorxoffset; + tempsec->ceilingyoffset = tempsec->flooryoffset; + tempsec->ceilingangle = tempsec->floorangle; } else { tempsec->ceilingpic = s->ceilingpic; - tempsec->ceiling_xoffs = s->ceiling_xoffs; - tempsec->ceiling_yoffs = s->ceiling_yoffs; - tempsec->ceilingpic_angle = s->ceilingpic_angle; + tempsec->ceilingxoffset = s->ceilingxoffset; + tempsec->ceilingyoffset = s->ceilingyoffset; + tempsec->ceilingangle = s->ceilingangle; } } @@ -315,25 +315,25 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->floorheight = s->ceilingheight + 1; tempsec->floorpic = tempsec->ceilingpic = s->ceilingpic; - tempsec->floor_xoffs = tempsec->ceiling_xoffs = s->ceiling_xoffs; - tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; - tempsec->floorpic_angle = tempsec->ceilingpic_angle = s->ceilingpic_angle; + tempsec->floorxoffset = tempsec->ceilingxoffset = s->ceilingxoffset; + tempsec->flooryoffset = tempsec->ceilingyoffset = s->ceilingyoffset; + tempsec->floorangle = tempsec->ceilingangle = s->ceilingangle; if (s->floorpic == skyflatnum) // SKYFIX? { tempsec->ceilingheight = tempsec->floorheight-1; tempsec->floorpic = tempsec->ceilingpic; - tempsec->floor_xoffs = tempsec->ceiling_xoffs; - tempsec->floor_yoffs = tempsec->ceiling_yoffs; - tempsec->floorpic_angle = tempsec->ceilingpic_angle; + tempsec->floorxoffset = tempsec->ceilingxoffset; + tempsec->flooryoffset = tempsec->ceilingyoffset; + tempsec->floorangle = tempsec->ceilingangle; } else { tempsec->ceilingheight = sec->ceilingheight; tempsec->floorpic = s->floorpic; - tempsec->floor_xoffs = s->floor_xoffs; - tempsec->floor_yoffs = s->floor_yoffs; - tempsec->floorpic_angle = s->floorpic_angle; + tempsec->floorxoffset = s->floorxoffset; + tempsec->flooryoffset = s->flooryoffset; + tempsec->floorangle = s->floorangle; } tempsec->lightlevel = s->lightlevel; @@ -363,12 +363,12 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back) && back->lightlevel == front->lightlevel && !line->sidedef->midtexture // Check offsets too! - && back->floor_xoffs == front->floor_xoffs - && back->floor_yoffs == front->floor_yoffs - && back->floorpic_angle == front->floorpic_angle - && back->ceiling_xoffs == front->ceiling_xoffs - && back->ceiling_yoffs == front->ceiling_yoffs - && back->ceilingpic_angle == front->ceilingpic_angle + && back->floorxoffset == front->floorxoffset + && back->flooryoffset == front->flooryoffset + && back->floorangle == front->floorangle + && back->ceilingxoffset == front->ceilingxoffset + && back->ceilingyoffset == front->ceilingyoffset + && back->ceilingangle == front->ceilingangle // Consider altered lighting. && back->floorlightlevel == front->floorlightlevel && back->floorlightabsolute == front->floorlightabsolute @@ -909,7 +909,7 @@ static void R_Subsector(size_t num) || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum)) { floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel, - frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL, NULL, frontsector->f_slope); + frontsector->floorxoffset, frontsector->flooryoffset, frontsector->floorangle, floorcolormap, NULL, NULL, frontsector->f_slope); } else floorplane = NULL; @@ -919,7 +919,7 @@ static void R_Subsector(size_t num) || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum)) { ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, - ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, + ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingangle, ceilingcolormap, NULL, NULL, frontsector->c_slope); } else @@ -1033,8 +1033,8 @@ static void R_Subsector(size_t num) { light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic, - (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs, - polysec->floorpic_angle-po->angle, + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floorxoffset, polysec->flooryoffset, + polysec->floorangle-po->angle, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, NULL); // will ffloors be slopable eventually? @@ -1057,7 +1057,7 @@ static void R_Subsector(size_t num) { light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, - (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceilingxoffset, polysec->ceilingyoffset, polysec->ceilingangle-po->angle, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, NULL); // will ffloors be slopable eventually? diff --git a/src/r_defs.h b/src/r_defs.h index dbede806e..7da162de7 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -423,12 +423,12 @@ typedef struct sector_s void *fadecolormapdata; // fade colormap thinker // floor and ceiling texture offsets - fixed_t floor_xoffs, floor_yoffs; - fixed_t ceiling_xoffs, ceiling_yoffs; + fixed_t floorxoffset, flooryoffset; + fixed_t ceilingxoffset, ceilingyoffset; // flat angle - angle_t floorpic_angle; - angle_t ceilingpic_angle; + angle_t floorangle; + angle_t ceilingangle; INT32 heightsec; // other sector, or -1 if no other sector INT32 camsec; // used for camera clipping diff --git a/src/r_fps.c b/src/r_fps.c index 2d30c9f01..3d7d3f7ae 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -426,8 +426,8 @@ void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boo } else { - interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->floor_xoffs; - interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->floor_yoffs; + interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->floorxoffset; + interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->flooryoffset; } } @@ -490,9 +490,9 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp) break; case LVLINTERP_SectorScroll: interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs; - interp->sectorscroll.bakxoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_xoffs : interp->sectorscroll.sector->floor_xoffs; + interp->sectorscroll.bakxoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_xoffs : interp->sectorscroll.sector->floorxoffset; interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs; - interp->sectorscroll.bakyoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_yoffs : interp->sectorscroll.sector->floor_yoffs; + interp->sectorscroll.bakyoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_yoffs : interp->sectorscroll.sector->flooryoffset; break; case LVLINTERP_SideScroll: interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset; @@ -583,8 +583,8 @@ void R_ApplyLevelInterpolators(fixed_t frac) } else { - interp->sectorscroll.sector->floor_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac); - interp->sectorscroll.sector->floor_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac); + interp->sectorscroll.sector->floorxoffset = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac); + interp->sectorscroll.sector->flooryoffset = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac); } break; case LVLINTERP_SideScroll: @@ -638,8 +638,8 @@ void R_RestoreLevelInterpolators(void) } else { - interp->sectorscroll.sector->floor_xoffs = interp->sectorscroll.bakxoffs; - interp->sectorscroll.sector->floor_yoffs = interp->sectorscroll.bakyoffs; + interp->sectorscroll.sector->floorxoffset = interp->sectorscroll.bakxoffs; + interp->sectorscroll.sector->flooryoffset = interp->sectorscroll.bakyoffs; } break; case LVLINTERP_SideScroll: diff --git a/src/r_segs.c b/src/r_segs.c index 43a7f945f..681524054 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1906,9 +1906,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) || backsector->floorpic != frontsector->floorpic || backsector->lightlevel != frontsector->lightlevel //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->floor_xoffs != frontsector->floor_xoffs - || backsector->floor_yoffs != frontsector->floor_yoffs - || backsector->floorpic_angle != frontsector->floorpic_angle + || backsector->floorxoffset != frontsector->floorxoffset + || backsector->flooryoffset != frontsector->flooryoffset + || backsector->floorangle != frontsector->floorangle //SoM: 3/22/2000: Prevents bleeding. || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum) || backsector->floorlightlevel != frontsector->floorlightlevel @@ -1939,9 +1939,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) || backsector->ceilingpic != frontsector->ceilingpic || backsector->lightlevel != frontsector->lightlevel //SoM: 3/22/2000: Check floor x and y offsets. - || backsector->ceiling_xoffs != frontsector->ceiling_xoffs - || backsector->ceiling_yoffs != frontsector->ceiling_yoffs - || backsector->ceilingpic_angle != frontsector->ceilingpic_angle + || backsector->ceilingxoffset != frontsector->ceilingxoffset + || backsector->ceilingyoffset != frontsector->ceilingyoffset + || backsector->ceilingangle != frontsector->ceilingangle //SoM: 3/22/2000: Prevents bleeding. || (frontsector->heightsec != -1 && frontsector->ceilingpic != skyflatnum) || backsector->ceilinglightlevel != frontsector->ceilinglightlevel From c5daa248d16f803cf16b0836980cadf973e758e9 Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Fri, 25 Nov 2022 23:06:07 +0000 Subject: [PATCH 072/478] r_fps.c ceiling_y/xoffs renamed --- src/r_fps.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/r_fps.c b/src/r_fps.c index 3d7d3f7ae..661da8ba2 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -421,8 +421,8 @@ void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boo interp->sectorscroll.ceiling = ceiling; if (ceiling) { - interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->ceiling_xoffs; - interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->ceiling_yoffs; + interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs = sector->ceilingxoffset; + interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs = sector->ceilingyoffset; } else { @@ -490,9 +490,9 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp) break; case LVLINTERP_SectorScroll: interp->sectorscroll.oldxoffs = interp->sectorscroll.bakxoffs; - interp->sectorscroll.bakxoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_xoffs : interp->sectorscroll.sector->floorxoffset; + interp->sectorscroll.bakxoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceilingxoffset : interp->sectorscroll.sector->floorxoffset; interp->sectorscroll.oldyoffs = interp->sectorscroll.bakyoffs; - interp->sectorscroll.bakyoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceiling_yoffs : interp->sectorscroll.sector->flooryoffset; + interp->sectorscroll.bakyoffs = interp->sectorscroll.ceiling ? interp->sectorscroll.sector->ceilingyoffset : interp->sectorscroll.sector->flooryoffset; break; case LVLINTERP_SideScroll: interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset; @@ -578,8 +578,8 @@ void R_ApplyLevelInterpolators(fixed_t frac) case LVLINTERP_SectorScroll: if (interp->sectorscroll.ceiling) { - interp->sectorscroll.sector->ceiling_xoffs = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac); - interp->sectorscroll.sector->ceiling_yoffs = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac); + interp->sectorscroll.sector->ceilingxoffset = R_LerpFixed(interp->sectorscroll.oldxoffs, interp->sectorscroll.bakxoffs, frac); + interp->sectorscroll.sector->ceilingyoffset = R_LerpFixed(interp->sectorscroll.oldyoffs, interp->sectorscroll.bakyoffs, frac); } else { @@ -633,8 +633,8 @@ void R_RestoreLevelInterpolators(void) case LVLINTERP_SectorScroll: if (interp->sectorscroll.ceiling) { - interp->sectorscroll.sector->ceiling_xoffs = interp->sectorscroll.bakxoffs; - interp->sectorscroll.sector->ceiling_yoffs = interp->sectorscroll.bakyoffs; + interp->sectorscroll.sector->ceilingxoffset = interp->sectorscroll.bakxoffs; + interp->sectorscroll.sector->ceilingyoffset = interp->sectorscroll.bakyoffs; } else { From 656f7f94acf7390a17aff9b4a4fd92771ea5953b Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Fri, 25 Nov 2022 23:06:22 +0000 Subject: [PATCH 073/478] hw_main.c ceiling_y/xoffs renamed --- src/hardware/hw_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 2b376544a..c1043f8bb 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -465,8 +465,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(FOFsector->ceilingxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceilingyoffset)/fflatheight; angle = FOFsector->ceilingangle; } } @@ -480,8 +480,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(gl_frontsector->ceilingxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->ceilingyoffset)/fflatheight; angle = gl_frontsector->ceilingangle; } } @@ -2725,8 +2725,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(FOFsector->ceilingxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceilingyoffset)/fflatheight; angle = FOFsector->ceilingangle; } } @@ -2740,8 +2740,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth; - scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight; + scrollx = FIXED_TO_FLOAT(gl_frontsector->ceilingxoffset)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->ceilingyoffset)/fflatheight; angle = gl_frontsector->ceilingangle; } } From da9786b593040200fe56f6771e58ed6a16a01ed2 Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Fri, 25 Nov 2022 23:16:11 +0000 Subject: [PATCH 074/478] exposed floorlightsec, ceilinglightsec variables. --- src/lua_maplib.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 79909a6be..d3a00782b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -43,8 +43,10 @@ enum sector_e { sector_lightlevel, sector_floorlightlevel, sector_floorlightabsolute, + sector_floorlightsec, sector_ceilinglightlevel, sector_ceilinglightabsolute, + sector_ceilinglightsec, sector_special, sector_tag, sector_taglist, @@ -79,8 +81,10 @@ static const char *const sector_opt[] = { "lightlevel", "floorlightlevel", "floorlightabsolute", + "floorlightsec", "ceilinglightlevel", "ceilinglightabsolute", + "ceilinglightsec", "special", "tag", "taglist", @@ -667,12 +671,18 @@ static int sector_get(lua_State *L) case sector_floorlightabsolute: lua_pushboolean(L, sector->floorlightabsolute); return 1; + case sector_floorlightsec: + lua_pushinteger(L, sector->floorlightsec); + return 1; case sector_ceilinglightlevel: lua_pushinteger(L, sector->ceilinglightlevel); return 1; case sector_ceilinglightabsolute: lua_pushboolean(L, sector->ceilinglightabsolute); return 1; + case sector_ceilinglightsec: + lua_pushinteger(L, sector->ceilinglightsec); + return 1; case sector_special: lua_pushinteger(L, sector->special); return 1; @@ -801,7 +811,7 @@ static int sector_set(lua_State *L) break; case sector_floorangle: sector->floorangle = luaL_checkangle(L, 3); - break; + break; case sector_ceilingpic: sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; @@ -823,12 +833,18 @@ static int sector_set(lua_State *L) case sector_floorlightabsolute: sector->floorlightabsolute = luaL_checkboolean(L, 3); break; + case sector_floorlightsec: + sector->floorlightsec = (INT32)luaL_checkinteger(L, 3); + break; case sector_ceilinglightlevel: sector->ceilinglightlevel = (INT16)luaL_checkinteger(L, 3); break; case sector_ceilinglightabsolute: sector->ceilinglightabsolute = luaL_checkboolean(L, 3); break; + case sector_ceilinglightsec: + sector->ceilinglightsec = (INT32)luaL_checkinteger(L, 3); + break; case sector_special: sector->special = (INT16)luaL_checkinteger(L, 3); break; From 5cb13f9d1c1a28575cd5fad4160407269e552d8c Mon Sep 17 00:00:00 2001 From: Eidolon Date: Thu, 17 Nov 2022 18:39:39 -0600 Subject: [PATCH 075/478] Bump SRB2VERSION and MODVERSION for 2.2.11 pre1 --- src/version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/version.h b/src/version.h index 7a12fbbbe..5e4c85be4 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define SRB2VERSION "2.2.10"/* this must be the first line, for cmake !! */ +#define SRB2VERSION "2.2.11"/* this must be the first line, for cmake !! */ // The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/members/?key=ms_admin ). // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. @@ -9,7 +9,7 @@ // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1". -#define MODVERSION 51 +#define MODVERSION 52 // Define this as a prerelease version suffix (pre#, RC#) -// #define BETAVERSION "pre1" +#define BETAVERSION "pre1" From df131ef131c5146b8f9a99af182849a2ed19f2e4 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Tue, 6 Dec 2022 18:43:59 -0600 Subject: [PATCH 076/478] Bump SRB2VERSION and MODVERSION for 2.2.11 pre2 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 5e4c85be4..5314314bf 100644 --- a/src/version.h +++ b/src/version.h @@ -12,4 +12,4 @@ #define MODVERSION 52 // Define this as a prerelease version suffix (pre#, RC#) -#define BETAVERSION "pre1" +#define BETAVERSION "pre2" From 9e191d0748df60eb7d11ef7beaaba038e1da6180 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Thu, 8 Dec 2022 21:27:24 -0600 Subject: [PATCH 077/478] Bump SRB2VERSION and MODVERSION for 2.2.11 pre3 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 5314314bf..f8b09ada6 100644 --- a/src/version.h +++ b/src/version.h @@ -12,4 +12,4 @@ #define MODVERSION 52 // Define this as a prerelease version suffix (pre#, RC#) -#define BETAVERSION "pre2" +#define BETAVERSION "pre3" From 30df486dacb53132d0045b0190a22a4468ca14ef Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 10 Dec 2022 15:32:06 -0600 Subject: [PATCH 078/478] Update zones.pk3 hash for pre3 (oops) --- src/config.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.h.in b/src/config.h.in index 928705b30..22cfd6481 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -29,7 +29,7 @@ * Last updated 2022 / 03 / 06 - v2.2.10 - main assets */ #define ASSET_HASH_SRB2_PK3 "ad911f29a28a18968ee5b2d11c2acb39" -#define ASSET_HASH_ZONES_PK3 "86ae55cae4e0a93ceda868635706a093" +#define ASSET_HASH_ZONES_PK3 "188a2bfd552196609323fc91ec1cdb22" #define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c" #ifdef USE_PATCH_DTA #define ASSET_HASH_PATCH_PK3 "7d467a883f7887b3c311798ee2f56b6a" From bc519ad132334b1e764884a468de490c007e4a35 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sat, 31 Dec 2022 22:07:22 -0500 Subject: [PATCH 079/478] Fix for issue #933 - special stage tokens should divert player until after the special stage with a custom exit map --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index b4a127a73..ab399cfa2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4161,7 +4161,7 @@ static void G_DoCompleted(void) { token--; - if (!nextmapoverride) +// if (!nextmapoverride) // Having a token should pull the player into the special stage before going to the overridden map (Issue #933) for (i = 0; i < 7; i++) if (!(emeralds & (1< Date: Sat, 31 Dec 2022 22:46:08 -0500 Subject: [PATCH 080/478] When attaching to a wall to do a climb, the second sidedef wasn't be handled properly. --- src/p_map.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 5c8ccbb19..232bf3a50 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3506,11 +3506,9 @@ static void PTR_GlideClimbTraverse(line_t *li) if (fofline) whichside = 0; - if (!whichside) - { - slidemo->player->lastsidehit = checkline->sidenum[whichside]; - slidemo->player->lastlinehit = (INT16)(checkline - lines); - } + // Even if you attach to the second side of a linedef, we want to know the last hit. + slidemo->player->lastsidehit = checkline->sidenum[whichside]; + slidemo->player->lastlinehit = (INT16)(checkline - lines); P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale)); } From bd89b97e0a770944452da5829c27b78524a58e6b Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 1 Jan 2023 20:59:11 -0500 Subject: [PATCH 081/478] Fixes issue #704 --- src/p_map.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 5c8ccbb19..911d7927c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -418,7 +418,12 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) P_SetPlayerMobjState(object, S_PLAY_ROLL); } else - pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these. + { + pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_THOKKED | PF_BOUNCING); // I still need these. + + if (pflags & PF_SPINNING) // Ensure we're in the rolling state, and not something like spindash. + P_SetPlayerMobjState(object, S_PLAY_ROLL); + } secondjump = object->player->secondjump; washoming = object->player->homing; P_ResetPlayer(object->player); From af146071d87c588e140b3aa52995d1268f0cd928 Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 2 Jan 2023 07:34:33 -0500 Subject: [PATCH 082/478] Check for spindash ability and dashspeed being > 0 before indiscriminately setting roll animation. --- src/p_map.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 911d7927c..cb4309f80 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -419,9 +419,11 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } else { + boolean wasSpindashing = object->player->dashspeed > 0 && (object->player->charability2 == CA2_SPINDASH); + pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_THOKKED | PF_BOUNCING); // I still need these. - if (pflags & PF_SPINNING) // Ensure we're in the rolling state, and not something like spindash. + if (wasSpindashing) // Ensure we're in the rolling state, and not spindash. P_SetPlayerMobjState(object, S_PLAY_ROLL); } secondjump = object->player->secondjump; From 28f97dcd0bd716a3f6773030efbc66640a319d6b Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 2 Jan 2023 08:07:13 -0500 Subject: [PATCH 083/478] Also fix STJr/SRB2#618 since it is highly related. --- src/p_map.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_map.c b/src/p_map.c index cb4309f80..98a5360f6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -425,6 +425,12 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (wasSpindashing) // Ensure we're in the rolling state, and not spindash. P_SetPlayerMobjState(object, S_PLAY_ROLL); + + if (object->player->charability == CA_GLIDEANDCLIMB && object->player->skidtime && (pflags & PF_JUMPED)) + { + object->player->skidtime = 0; // No skidding should be happening, either. + pflags &= ~PF_JUMPED; + } } secondjump = object->player->secondjump; washoming = object->player->homing; From 3a04e1174372fd2b605b99220d127a6cc1291ecc Mon Sep 17 00:00:00 2001 From: katsy Date: Thu, 5 Jan 2023 14:11:54 -0600 Subject: [PATCH 084/478] allow targeting invulnerable bosses --- src/g_game.c | 1 - src/p_user.c | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index b4a127a73..cd29a08f8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1453,7 +1453,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if ( P_MobjWasRemoved(ticcmd_ztargetfocus[forplayer]) || !ticcmd_ztargetfocus[forplayer]->health || - (ticcmd_ztargetfocus[forplayer]->flags2 & MF2_FRET) || (ticcmd_ztargetfocus[forplayer]->type == MT_EGGMOBILE3 && !ticcmd_ztargetfocus[forplayer]->movecount) // Sea Egg is moving around underground and shouldn't be tracked ) P_SetTarget(&ticcmd_ztargetfocus[forplayer], NULL); diff --git a/src/p_user.c b/src/p_user.c index 4ca4e6c8a..0ca49ded0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9059,10 +9059,6 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, switch (mo->type) { - case MT_TNTBARREL: - if (lockonflags & LOCK_INTERESTS) - break; - /*FALLTHRU*/ case MT_PLAYER: // Don't chase other players! case MT_DETON: continue; // Don't be STUPID, Sonic! @@ -9083,17 +9079,13 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, /*FALLTHRU*/ default: - if ((lockonflags & LOCK_BOSS) && ((mo->flags & (MF_BOSS|MF_SHOOTABLE)) == (MF_BOSS|MF_SHOOTABLE))) // allows if it has the flags desired XOR it has the invert aimable flag - { - if (mo->flags2 & MF2_FRET) - continue; + if ((lockonflags & LOCK_BOSS) && (mo->flags & MF_BOSS)) // always allow targeting bosses break; - } if ((lockonflags & LOCK_ENEMY) && (!((mo->flags & (MF_ENEMY|MF_SHOOTABLE)) == (MF_ENEMY|MF_SHOOTABLE)) != !(mo->flags2 & MF2_INVERTAIMABLE))) // allows if it has the flags desired XOR it has the invert aimable flag break; - if ((lockonflags & LOCK_INTERESTS) && (mo->flags & (MF_PUSHABLE|MF_MONITOR))) // allows if it has the flags desired XOR it has the invert aimable flag + if ((lockonflags & LOCK_INTERESTS) && (mo->flags & (MF_PUSHABLE|MF_MONITOR))) // allows if it has the flags desired break; continue; // not a valid object From cc6eac0886317f4dab85743ae20f23c5f03004cc Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sat, 4 Feb 2023 17:34:43 +0100 Subject: [PATCH 085/478] Fix con_hudlines being off by one --- src/console.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/console.c b/src/console.c index 40fb43121..0f3105caa 100644 --- a/src/console.c +++ b/src/console.c @@ -72,8 +72,8 @@ static INT32 con_curlines; // vid lines currently used by console INT32 con_clipviewtop; // (useless) -static INT32 con_hudlines; // number of console heads up message lines -static INT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines +static UINT8 con_hudlines; // number of console heads up message lines +static INT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines INT32 con_clearlines; // top screen lines to refresh when view reduced boolean con_hudupdate; // when messages scroll, we need a backgrnd refresh @@ -128,7 +128,8 @@ static char con_buffer[CON_BUFFERSIZE]; static consvar_t cons_msgtimeout = CVAR_INIT ("con_hudtime", "5", CV_SAVE, CV_Unsigned, NULL); // number of lines displayed on the HUD -static consvar_t cons_hudlines = CVAR_INIT ("con_hudlines", "5", CV_CALL|CV_SAVE, CV_Unsigned, CONS_hudlines_Change); +static CV_PossibleValue_t hudlines_cons_t[] = {{1, "MIN"}, {MAXHUDLINES, "MAX"}, {0, "None"}, {0, NULL}}; +static consvar_t cons_hudlines = CVAR_INIT ("con_hudlines", "5", CV_CALL|CV_SAVE, hudlines_cons_t, CONS_hudlines_Change); // number of lines console move per frame // (con_speed needs a limit, apparently) @@ -168,11 +169,6 @@ static void CONS_hudlines_Change(void) for (i = 0; i < con_hudlines; i++) con_hudtime[i] = 0; - if (cons_hudlines.value < 1) - cons_hudlines.value = 1; - else if (cons_hudlines.value > MAXHUDLINES) - cons_hudlines.value = MAXHUDLINES; - con_hudlines = cons_hudlines.value; Unlock_state(); @@ -1328,7 +1324,8 @@ boolean CON_Responder(event_t *ev) static void CON_Linefeed(void) { // set time for heads up messages - con_hudtime[con_cy%con_hudlines] = cons_msgtimeout.value*TICRATE; + if (con_hudlines) + con_hudtime[con_cy%con_hudlines] = cons_msgtimeout.value*TICRATE; con_cy++; con_cx = 0; @@ -1684,7 +1681,7 @@ static void CON_DrawHudlines(void) INT32 charwidth = 8 * con_scalefactor; INT32 charheight = 8 * con_scalefactor; - if (con_hudlines <= 0) + if (!con_hudlines) return; if (chat_on && OLDCHAT) @@ -1692,7 +1689,7 @@ static void CON_DrawHudlines(void) else y = 0; - for (i = con_cy - con_hudlines+1; i <= con_cy; i++) + for (i = con_cy - con_hudlines; i <= con_cy; i++) { size_t c; INT32 x; From 702b2acfd39d8665ce3290eecb2abd84460198aa Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sat, 4 Feb 2023 17:35:44 +0100 Subject: [PATCH 086/478] Limit con_hudtime to 24 hours Also rename cons_msgtimeout to cons_hudtime for consistency --- src/console.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/console.c b/src/console.c index 0f3105caa..b99b13720 100644 --- a/src/console.c +++ b/src/console.c @@ -72,8 +72,8 @@ static INT32 con_curlines; // vid lines currently used by console INT32 con_clipviewtop; // (useless) -static UINT8 con_hudlines; // number of console heads up message lines -static INT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines +static UINT8 con_hudlines; // number of console heads up message lines +static UINT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines INT32 con_clearlines; // top screen lines to refresh when view reduced boolean con_hudupdate; // when messages scroll, we need a backgrnd refresh @@ -125,7 +125,9 @@ static void CONS_backcolor_Change(void); static char con_buffer[CON_BUFFERSIZE]; // how many seconds the hud messages lasts on the screen -static consvar_t cons_msgtimeout = CVAR_INIT ("con_hudtime", "5", CV_SAVE, CV_Unsigned, NULL); +// CV_Unsigned can overflow when multiplied by TICRATE later, so let's use a 24-hour limit instead +static CV_PossibleValue_t hudtime_cons_t[] = {{0, "MIN"}, {86400, "MAX"}, {0, NULL}}; +static consvar_t cons_hudtime = CVAR_INIT ("con_hudtime", "5", CV_SAVE, hudtime_cons_t, NULL); // number of lines displayed on the HUD static CV_PossibleValue_t hudlines_cons_t[] = {{1, "MIN"}, {MAXHUDLINES, "MAX"}, {0, "None"}, {0, NULL}}; @@ -460,7 +462,7 @@ void CON_Init(void) Unlock_state(); - CV_RegisterVar(&cons_msgtimeout); + CV_RegisterVar(&cons_hudtime); CV_RegisterVar(&cons_hudlines); CV_RegisterVar(&cons_speed); CV_RegisterVar(&cons_height); @@ -773,9 +775,8 @@ void CON_Ticker(void) // make overlay messages disappear after a while for (i = 0; i < con_hudlines; i++) { - con_hudtime[i]--; - if (con_hudtime[i] < 0) - con_hudtime[i] = 0; + if (con_hudtime[i]) + con_hudtime[i]--; } Unlock_state(); @@ -1325,7 +1326,7 @@ static void CON_Linefeed(void) { // set time for heads up messages if (con_hudlines) - con_hudtime[con_cy%con_hudlines] = cons_msgtimeout.value*TICRATE; + con_hudtime[con_cy%con_hudlines] = cons_hudtime.value*TICRATE; con_cy++; con_cx = 0; From b184067048b4c5548d152c2481db9baa0d2866bd Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 14 Mar 2023 14:19:53 +0100 Subject: [PATCH 087/478] Add HUD icons for timed NiGHTS powerups --- src/st_stuff.c | 89 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 3e75750a8..65e4c5e03 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -108,6 +108,9 @@ static patch_t *sneakers; static patch_t *gravboots; static patch_t *nonicon; static patch_t *nonicon2; +static patch_t *nightopianhelper; +static patch_t *linkfreeze; +static patch_t *superparaloop; static patch_t *bluestat; static patch_t *byelstat; static patch_t *orngstat; @@ -313,6 +316,10 @@ void ST_LoadGraphics(void) nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX); // NiGHTS HUD things + nightopianhelper = W_CachePatchName("NHLPICON", PU_HUDGFX); + linkfreeze = W_CachePatchName("NLFZICON", PU_HUDGFX); + superparaloop = W_CachePatchName("NSPRICON", PU_HUDGFX); + bluestat = W_CachePatchName("BLUESTAT", PU_HUDGFX); byelstat = W_CachePatchName("BYELSTAT", PU_HUDGFX); orngstat = W_CachePatchName("ORNGSTAT", PU_HUDGFX); @@ -1448,6 +1455,21 @@ void ST_drawWipeTitleCard(void) } } +#define ICONSEP (16+4) // matches weapon rings HUD + +static INT32 ST_powerupHUDoffset(UINT16 timer) +{ + if (timer > 7) + return ICONSEP; + else + { + UINT8 a = ICONSEP, b = 7-timer; + while (b--) + a = 2*a/3; + return a; + } +} + static void ST_drawPowerupHUD(void) { patch_t *p = NULL; @@ -1455,7 +1477,6 @@ static void ST_drawPowerupHUD(void) INT32 offs = hudinfo[HUD_POWERUPS].x; const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0); static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0}, finishoffs[2] = {0, 0}; -#define ICONSEP (16+4) // matches weapon rings HUD if (F_GetPromptHideHud(hudinfo[HUD_POWERUPS].y)) return; @@ -1567,15 +1588,7 @@ static void ST_drawPowerupHUD(void) DRAWTIMERICON(invincibility, invulntime) } - if (invulntime > 7) - offs -= ICONSEP; - else - { - UINT8 a = ICONSEP, b = 7-invulntime; - while (b--) - a = 2*a/3; - offs -= a; - } + offs -= ST_powerupHUDoffset(invulntime); // Super Sneakers if (stplyr->powers[pw_sneakers] > 3*TICRATE || (stplyr->powers[pw_sneakers] && leveltime & 1)) @@ -1583,15 +1596,7 @@ static void ST_drawPowerupHUD(void) DRAWTIMERICON(sneakers, stplyr->powers[pw_sneakers]) } - if (stplyr->powers[pw_sneakers] > 7) - offs -= ICONSEP; - else - { - UINT8 a = ICONSEP, b = 7-stplyr->powers[pw_sneakers]; - while (b--) - a = 2*a/3; - offs -= a; - } + offs -= ST_powerupHUDoffset(stplyr->powers[pw_sneakers]); // Gravity Boots if (stplyr->powers[pw_gravityboots] > 3*TICRATE || (stplyr->powers[pw_gravityboots] && leveltime & 1)) @@ -1599,6 +1604,36 @@ static void ST_drawPowerupHUD(void) DRAWTIMERICON(gravboots, stplyr->powers[pw_gravityboots]) } + offs -= ST_powerupHUDoffset(stplyr->powers[pw_gravityboots]); + +// -------------------- +// NiGHTS timer-based powerups +// -------------------- + + // Nightopian Helper + if (stplyr->powers[pw_nights_helper] > 3*TICRATE || (stplyr->powers[pw_nights_helper] && leveltime & 1)) + { + DRAWTIMERICON(nightopianhelper, stplyr->powers[pw_nights_helper]) + } + + offs -= ST_powerupHUDoffset(stplyr->powers[pw_nights_helper]); + + // Link Freeze + if (stplyr->powers[pw_nights_linkfreeze] > 3*TICRATE || (stplyr->powers[pw_nights_linkfreeze] && leveltime & 1)) + { + DRAWTIMERICON(linkfreeze, stplyr->powers[pw_nights_linkfreeze]) + } + + offs -= ST_powerupHUDoffset(stplyr->powers[pw_nights_linkfreeze]); + + // Super Paraloop + if (stplyr->powers[pw_nights_superloop] > 3*TICRATE || (stplyr->powers[pw_nights_superloop] && leveltime & 1)) + { + DRAWTIMERICON(superparaloop, stplyr->powers[pw_nights_superloop]) + } + + //offs -= ST_powerupHUDoffset(stplyr->powers[pw_nights_superloop]); + #undef DRAWTIMERICON #undef ICONSEP } @@ -2740,18 +2775,16 @@ static void ST_overlayDrawer(void) } // This is where we draw all the fun cheese if you have the chasecam off! - if (!(maptol & TOL_NIGHTS)) + if ((stplyr == &players[displayplayer] && !camera.chase) + || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) { - if ((stplyr == &players[displayplayer] && !camera.chase) - || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) - { - ST_drawFirstPersonHUD(); - if (cv_powerupdisplay.value) - ST_drawPowerupHUD(); // same as it ever was... - } - else if (cv_powerupdisplay.value == 2) + ST_drawFirstPersonHUD(); + if (cv_powerupdisplay.value) ST_drawPowerupHUD(); // same as it ever was... } + else if (cv_powerupdisplay.value == 2) + ST_drawPowerupHUD(); // same as it ever was... + } else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2) ST_drawPowerupHUD(); // same as it ever was... From 1304874a8f4e92e0507505e7ace02861c5ece0d1 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 16 Mar 2023 19:17:42 +0100 Subject: [PATCH 088/478] Remove incorrect early returns in P_CheckSector --- src/p_map.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 54e2003ba..1cdccbbcc 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4509,7 +4509,6 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) continue; PIT_ChangeSector(mo, true); - return nofit; } } } @@ -4539,10 +4538,7 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) { n->visited = true; if (!(n->m_thing->flags & MF_NOBLOCKMAP)) - { PIT_ChangeSector(n->m_thing, true); - return nofit; - } break; } } while (n); @@ -4562,10 +4558,7 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) { n->visited = true; // mark thing as processed if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these - { PIT_ChangeSector(n->m_thing, true); // process it - return nofit; - } break; // exit and start over } } while (n); // repeat from scratch until all things left are marked valid From 0667bf74feb7f1bf46304d04046608cbae27cba0 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 16 Mar 2023 19:30:21 +0100 Subject: [PATCH 089/478] Remove duplicated code in P_CheckSector --- src/p_map.c | 312 +++++++++++++++++++--------------------------------- 1 file changed, 111 insertions(+), 201 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 1cdccbbcc..d5f6ce1c1 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4340,14 +4340,118 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) return true; } +static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush) +{ + msecnode_t *n; + size_t i; + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->polyobj) + { + polyobj_t *po = sector->lines[i]->polyobj; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + { + INT32 x, y; + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjInsidePolyobj(po, mo)) + continue; + + if (!PIT_ChangeSector(mo, realcrush) && !realcrush) + return false; + } + } + } + } + } + } + + if (sector->numattached) + { + sector_t *sec; + for (i = 0; i < sector->numattached; i++) + { + sec = §ors[sector->attached[i]]; + for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) + n->visited = false; + + sec->moved = true; + + P_RecalcPrecipInSector(sec); + + if (!sector->attachedsolid[i]) + continue; + + do + { + for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) + if (!n->visited) + { + n->visited = true; + if (!(n->m_thing->flags & MF_NOBLOCKMAP)) + { + if (!PIT_ChangeSector(n->m_thing, realcrush) && !realcrush) + return false; + } + break; + } + } while (n); + } + } + + // Mark all things invalid + sector->moved = true; + + for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) + n->visited = false; + + do + { + for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list + if (!n->visited) // unprocessed thing found + { + n->visited = true; // mark thing as processed + if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these + { + if (!PIT_ChangeSector(n->m_thing, realcrush) && !realcrush) // process it + return false; + } + break; // exit and start over + } + } while (n); // repeat from scratch until all things left are marked valid + + return true; +} + // // P_CheckSector // boolean P_CheckSector(sector_t *sector, boolean crunch) { - msecnode_t *n; - size_t i; - nofit = false; crushchange = crunch; @@ -4359,209 +4463,15 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) // // killough 4/7/98: simplified to avoid using complicated counter - // First, let's see if anything will keep it from crushing. - - // Sal: This stupid function chain is required to fix polyobjects not being able to crush. - // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead - validcount++; - - for (i = 0; i < sector->linecount; i++) + if (!P_CheckSectorHelper(sector, false)) { - if (sector->lines[i]->polyobj) - { - polyobj_t *po = sector->lines[i]->polyobj; - if (po->validcount == validcount) - continue; // skip if already checked - if (!(po->flags & POF_SOLID)) - continue; - if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector - { - INT32 x, y; - po->validcount = validcount; - - for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) - { - for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) - { - mobj_t *mo; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - continue; - - mo = blocklinks[y * bmapwidth + x]; - - for (; mo; mo = mo->bnext) - { - // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect - - if (!P_MobjInsidePolyobj(po, mo)) - continue; - - if (!PIT_ChangeSector(mo, false)) - { - nofit = true; - return nofit; - } - } - } - } - } - } + nofit = true; + return nofit; } - if (sector->numattached) - { - sector_t *sec; - for (i = 0; i < sector->numattached; i++) - { - sec = §ors[sector->attached[i]]; - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - sec->moved = true; - - P_RecalcPrecipInSector(sec); - - if (!sector->attachedsolid[i]) - continue; - - do - { - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - if (!n->visited) - { - n->visited = true; - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) - { - if (!PIT_ChangeSector(n->m_thing, false)) - { - nofit = true; - return nofit; - } - } - break; - } - } while (n); - } - } - - // Mark all things invalid - sector->moved = true; - - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - do - { - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list - if (!n->visited) // unprocessed thing found - { - n->visited = true; // mark thing as processed - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these - { - if (!PIT_ChangeSector(n->m_thing, false)) // process it - { - nofit = true; - return nofit; - } - } - break; // exit and start over - } - } while (n); // repeat from scratch until all things left are marked valid - // Nothing blocked us, so lets crush for real! - - // Sal: This stupid function chain is required to fix polyobjects not being able to crush. - // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead - validcount++; - - for (i = 0; i < sector->linecount; i++) - { - if (sector->lines[i]->polyobj) - { - polyobj_t *po = sector->lines[i]->polyobj; - if (po->validcount == validcount) - continue; // skip if already checked - if (!(po->flags & POF_SOLID)) - continue; - if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector - { - INT32 x, y; - po->validcount = validcount; - - for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) - { - for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) - { - mobj_t *mo; - - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - continue; - - mo = blocklinks[y * bmapwidth + x]; - - for (; mo; mo = mo->bnext) - { - // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect - - if (!P_MobjInsidePolyobj(po, mo)) - continue; - - PIT_ChangeSector(mo, true); - } - } - } - } - } - } - if (sector->numattached) - { - sector_t *sec; - for (i = 0; i < sector->numattached; i++) - { - sec = §ors[sector->attached[i]]; - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - sec->moved = true; - - P_RecalcPrecipInSector(sec); - - if (!sector->attachedsolid[i]) - continue; - - do - { - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - if (!n->visited) - { - n->visited = true; - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) - PIT_ChangeSector(n->m_thing, true); - break; - } - } while (n); - } - } - - // Mark all things invalid - sector->moved = true; - - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; - - do - { - for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list - if (!n->visited) // unprocessed thing found - { - n->visited = true; // mark thing as processed - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these - PIT_ChangeSector(n->m_thing, true); // process it - break; // exit and start over - } - } while (n); // repeat from scratch until all things left are marked valid + P_CheckSectorHelper(sector, true); return nofit; } From 411b79e4564a35dc946944c714da98c7a56ba628 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 16 Mar 2023 19:38:30 +0100 Subject: [PATCH 090/478] P_CheckSector: Remove unnecessary static variables --- src/p_map.c | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index d5f6ce1c1..3172f57ed 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4231,13 +4231,11 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama // the way it was and call P_CheckSector (? was P_ChangeSector - Graue) again // to undo the changes. // -static boolean crushchange; -static boolean nofit; // // PIT_ChangeSector // -static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) +static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush, boolean crunch) { mobj_t *killer = NULL; //If a thing is both pushable and vulnerable, it doesn't block the crusher because it gets killed. @@ -4261,11 +4259,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) if (thing->z + thing->height > thing->ceilingz && thing->z <= thing->ceilingz) { if (immunepushable && thing->z + thing->height > thing->subsector->sector->ceilingheight) - { - //Thing is a pushable and blocks the moving ceiling - nofit = true; - return false; - } + return false; //Thing is a pushable and blocks the moving ceiling //Check FOFs in the sector if (thing->subsector->sector->ffloors && (realcrush || immunepushable)) @@ -4291,11 +4285,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2)) { if (immunepushable) - { - //FOF is blocked by pushable - nofit = true; - return false; - } + return false; //FOF is blocked by pushable else { //If the thing was crushed by a crumbling FOF, reward the player who made it crumble! @@ -4333,14 +4323,14 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) } } - if (realcrush && crushchange) + if (realcrush && crunch) P_DamageMobj(thing, NULL, NULL, 1, 0); // keep checking (crush other things) return true; } -static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush) +static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush, boolean crunch) { msecnode_t *n; size_t i; @@ -4381,7 +4371,7 @@ static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush) if (!P_MobjInsidePolyobj(po, mo)) continue; - if (!PIT_ChangeSector(mo, realcrush) && !realcrush) + if (!PIT_ChangeSector(mo, realcrush, crunch) && !realcrush) return false; } } @@ -4414,7 +4404,7 @@ static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush) n->visited = true; if (!(n->m_thing->flags & MF_NOBLOCKMAP)) { - if (!PIT_ChangeSector(n->m_thing, realcrush) && !realcrush) + if (!PIT_ChangeSector(n->m_thing, realcrush, crunch) && !realcrush) return false; } break; @@ -4437,7 +4427,7 @@ static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush) n->visited = true; // mark thing as processed if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these { - if (!PIT_ChangeSector(n->m_thing, realcrush) && !realcrush) // process it + if (!PIT_ChangeSector(n->m_thing, realcrush, crunch) && !realcrush) // process it return false; } break; // exit and start over @@ -4452,9 +4442,6 @@ static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush) // boolean P_CheckSector(sector_t *sector, boolean crunch) { - nofit = false; - crushchange = crunch; - // killough 4/4/98: scan list front-to-back until empty or exhausted, // restarting from beginning after each thing is processed. Avoids // crashes, and is sure to examine all things in the sector, and only @@ -4464,16 +4451,13 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) // killough 4/7/98: simplified to avoid using complicated counter // First, let's see if anything will keep it from crushing. - if (!P_CheckSectorHelper(sector, false)) - { - nofit = true; - return nofit; - } + if (!P_CheckSectorHelper(sector, false, crunch)) + return true; // Nothing blocked us, so lets crush for real! - P_CheckSectorHelper(sector, true); + P_CheckSectorHelper(sector, true, crunch); - return nofit; + return false; } /* From afa1a9ab6a0cf917ed41cf3ba6227a03f90f127a Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 16 Mar 2023 20:03:42 +0100 Subject: [PATCH 091/478] Split P_CheckSector further --- src/p_map.c | 162 ++++++++++++++++++++++++++++------------------------ 1 file changed, 88 insertions(+), 74 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 3172f57ed..e1ebe6ae9 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4330,9 +4330,8 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush, boolean crunch return true; } -static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush, boolean crunch) +static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boolean crunch) { - msecnode_t *n; size_t i; // Sal: This stupid function chain is required to fix polyobjects not being able to crush. @@ -4341,80 +4340,51 @@ static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush, boolean for (i = 0; i < sector->linecount; i++) { - if (sector->lines[i]->polyobj) + INT32 x, y; + polyobj_t *po = sector->lines[i]->polyobj; + + if (!po) + continue; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector != sector) // Make sure you're currently checking the control sector + continue; + + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) { - polyobj_t *po = sector->lines[i]->polyobj; - if (po->validcount == validcount) - continue; // skip if already checked - if (!(po->flags & POF_SOLID)) - continue; - if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) { - INT32 x, y; - po->validcount = validcount; + mobj_t *mo; - for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) { - for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) - { - mobj_t *mo; + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect - if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) - continue; + if (!P_MobjInsidePolyobj(po, mo)) + continue; - mo = blocklinks[y * bmapwidth + x]; - - for (; mo; mo = mo->bnext) - { - // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect - - if (!P_MobjInsidePolyobj(po, mo)) - continue; - - if (!PIT_ChangeSector(mo, realcrush, crunch) && !realcrush) - return false; - } - } + if (!PIT_ChangeSector(mo, realcrush, crunch) && !realcrush) + return false; } } } } - if (sector->numattached) - { - sector_t *sec; - for (i = 0; i < sector->numattached; i++) - { - sec = §ors[sector->attached[i]]; - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - n->visited = false; + return true; +} - sec->moved = true; - - P_RecalcPrecipInSector(sec); - - if (!sector->attachedsolid[i]) - continue; - - do - { - for (n = sec->touching_thinglist; n; n = n->m_thinglist_next) - if (!n->visited) - { - n->visited = true; - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) - { - if (!PIT_ChangeSector(n->m_thing, realcrush, crunch) && !realcrush) - return false; - } - break; - } - } while (n); - } - } - - // Mark all things invalid - sector->moved = true; +static boolean P_CheckTouchingThinglist(sector_t *sector, boolean realcrush, boolean crunch) +{ + msecnode_t *n; for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) n->visited = false; @@ -4422,21 +4392,65 @@ static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush, boolean do { for (n = sector->touching_thinglist; n; n = n->m_thinglist_next) // go through list - if (!n->visited) // unprocessed thing found - { - n->visited = true; // mark thing as processed - if (!(n->m_thing->flags & MF_NOBLOCKMAP)) //jff 4/7/98 don't do these - { - if (!PIT_ChangeSector(n->m_thing, realcrush, crunch) && !realcrush) // process it - return false; - } - break; // exit and start over - } + { + if (n->visited) + continue; + + n->visited = true; // mark thing as processed + + if (n->m_thing->flags & MF_NOBLOCKMAP) //jff 4/7/98 don't do these + continue; + + if (!PIT_ChangeSector(n->m_thing, realcrush, crunch) && !realcrush) // process it + return false; + + break; // exit and start over + } } while (n); // repeat from scratch until all things left are marked valid return true; } +static boolean P_CheckSectorFFloors(sector_t *sector, boolean realcrush, boolean crunch) +{ + sector_t *sec; + size_t i; + + if (!sector->numattached) + return true; + + for (i = 0; i < sector->numattached; i++) + { + sec = §ors[sector->attached[i]]; + + sec->moved = true; + + P_RecalcPrecipInSector(sec); + + if (!sector->attachedsolid[i]) + continue; + + if (!P_CheckTouchingThinglist(sec, realcrush, crunch)) + return false; + } + + return true; +} + +static boolean P_CheckSectorHelper(sector_t *sector, boolean realcrush, boolean crunch) +{ + if (!P_CheckSectorPolyObjects(sector, realcrush, crunch)) + return false; + + if (!P_CheckSectorFFloors(sector, realcrush, crunch)) + return false; + + // Mark all things invalid + sector->moved = true; + + return P_CheckTouchingThinglist(sector, realcrush, crunch); +} + // // P_CheckSector // From fff6683173e0a2ec61a5a2a8ab7e33f85ad714c3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Thu, 16 Mar 2023 20:38:28 +0100 Subject: [PATCH 092/478] Clean up PIT_ChangeSector --- src/p_map.c | 63 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index e1ebe6ae9..8ea1a6392 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4271,43 +4271,54 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush, boolean crunch for (rover = thing->subsector->sector->ffloors; rover; rover = rover->next) { - if (!(((rover->fofflags & FOF_BLOCKPLAYER) && thing->player) - || ((rover->fofflags & FOF_BLOCKOTHERS) && !thing->player)) || !(rover->fofflags & FOF_EXISTS)) + thinker_t *think; + + if (!(rover->fofflags & FOF_EXISTS)) + continue; + if (thing->player && !(rover->fofflags & FOF_BLOCKPLAYER)) + continue; + if (!thing->player && !(rover->fofflags & FOF_BLOCKOTHERS)) continue; topheight = *rover->topheight; bottomheight = *rover->bottomheight; - //topheight = P_GetFFloorTopZAt (rover, thing->x, thing->y); - //bottomheight = P_GetFFloorBottomZAt(rover, thing->x, thing->y); + + if (bottomheight > thing->ceilingz) + continue; delta1 = thing->z - (bottomheight + topheight)/2; delta2 = thingtop - (bottomheight + topheight)/2; - if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2)) + if (abs(delta1) < abs(delta2)) + continue; + + if (immunepushable) + return false; //FOF is blocked by pushable + + if (!realcrush) + continue; + + //If the thing was crushed by a crumbling FOF, reward the player who made it crumble! + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { - if (immunepushable) - return false; //FOF is blocked by pushable - else - { - //If the thing was crushed by a crumbling FOF, reward the player who made it crumble! - thinker_t *think; - crumble_t *crumbler; + crumble_t *crumbler; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) - { - if (think->function.acp1 != (actionf_p1)T_StartCrumble) - continue; + if (think->function.acp1 != (actionf_p1)T_StartCrumble) + continue; - crumbler = (crumble_t *)think; + crumbler = (crumble_t *)think; - if (crumbler->player && crumbler->player->mo - && crumbler->player->mo != thing - && crumbler->actionsector == thing->subsector->sector - && crumbler->sector == rover->master->frontsector) - { - killer = crumbler->player->mo; - } - } - } + if (!crumbler->player) + continue; + if (!crumbler->player->mo) + continue; + if (crumbler->player->mo == thing) + continue; + if (crumbler->actionsector != thing->subsector->sector) + continue; + if (crumbler->sector != rover->master->frontsector) + continue; + + killer = crumbler->player->mo; } } } From 498c9da85943886fda0538e1689fc66dbfebe64d Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 29 Mar 2023 16:41:45 +0200 Subject: [PATCH 093/478] Don't attract bomb spheres with Attraction shield --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 30e0183de..f5a951d65 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9686,7 +9686,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_RingThinker(mobj); if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); - else + else if (mobj->type != MT_BOMBSPHERE) // prevent shields from attracting bomb spheres A_AttractChase(mobj); return false; // Flung items From cb849ca4f03a6d209cdfb972ec88ecbfd941d6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 11 Apr 2023 22:13:29 +0200 Subject: [PATCH 094/478] Fix segfault when first mobj in overlaycap is removed --- src/p_mobj.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index c8adb6f1d..d6352bc2a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6900,6 +6900,13 @@ static void P_AddOverlay(mobj_t *thing) static void P_RemoveOverlay(mobj_t *thing) { mobj_t *mo; + if (overlaycap == thing) + { + P_SetTarget(&overlaycap, thing->hnext); + P_SetTarget(&thing->hnext, NULL); + return; + } + for (mo = overlaycap; mo; mo = mo->hnext) { if (mo->hnext != thing) From 4b6de096e516bf4579d2367639ae71d12ea865d2 Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 12 Apr 2023 00:59:08 +0200 Subject: [PATCH 095/478] Define cv_addons_folder in dedicated --- src/d_netcmd.c | 4 ++-- src/r_main.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 1fbdfdce2..28e7727e1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -794,8 +794,8 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_digitaldeadzone2); // filesrch.c - CV_RegisterVar(&cv_addons_option); - CV_RegisterVar(&cv_addons_folder); + //CV_RegisterVar(&cv_addons_option); // These two are now defined + //CV_RegisterVar(&cv_addons_folder); // in R_RegisterEngineStuff CV_RegisterVar(&cv_addons_md5); CV_RegisterVar(&cv_addons_showall); CV_RegisterVar(&cv_addons_search_type); diff --git a/src/r_main.c b/src/r_main.c index 4d801dc80..53f6ee2f9 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -36,6 +36,7 @@ #include "r_main.h" #include "i_system.h" // I_GetPreciseTime #include "r_fps.h" // Frame interpolation/uncapped +#include "filesrch.c" // cv_addons_folder #ifdef HWRENDER #include "hardware/hw_main.h" @@ -1589,6 +1590,10 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_flipcam); CV_RegisterVar(&cv_flipcam2); + // Other filesrch.c consvars are defined in D_RegisterClientCommands + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); + // Enough for dedicated server if (dedicated) return; From 488f0fdfab57e30478dcb87032ac0368cd064c5c Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 12 Apr 2023 20:06:02 +0200 Subject: [PATCH 096/478] bruh --- src/d_netcmd.c | 6 +++++- src/r_main.c | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 64a61d701..0eedd4542 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -613,6 +613,10 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_allowseenames); + // Other filesrch.c consvars are defined in D_RegisterClientCommands + CV_RegisterVar(&cv_addons_option); + CV_RegisterVar(&cv_addons_folder); + CV_RegisterVar(&cv_dummyconsvar); } @@ -795,7 +799,7 @@ void D_RegisterClientCommands(void) // filesrch.c //CV_RegisterVar(&cv_addons_option); // These two are now defined - //CV_RegisterVar(&cv_addons_folder); // in R_RegisterEngineStuff + //CV_RegisterVar(&cv_addons_folder); // in D_RegisterServerCommands CV_RegisterVar(&cv_addons_md5); CV_RegisterVar(&cv_addons_showall); CV_RegisterVar(&cv_addons_search_type); diff --git a/src/r_main.c b/src/r_main.c index 2a31227d1..ebf7a28bf 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -36,7 +36,6 @@ #include "r_main.h" #include "i_system.h" // I_GetPreciseTime #include "r_fps.h" // Frame interpolation/uncapped -#include "filesrch.c" // cv_addons_folder #ifdef HWRENDER #include "hardware/hw_main.h" @@ -1590,10 +1589,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_flipcam); CV_RegisterVar(&cv_flipcam2); - // Other filesrch.c consvars are defined in D_RegisterClientCommands - CV_RegisterVar(&cv_addons_option); - CV_RegisterVar(&cv_addons_folder); - // Enough for dedicated server if (dedicated) return; From c61594931debe50e520b1737810331c39f7d776c Mon Sep 17 00:00:00 2001 From: spherallic Date: Fri, 14 Apr 2023 00:28:14 +0200 Subject: [PATCH 097/478] Fix titlecard hook being inconsistent on map load --- src/st_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index cce8ea9f2..206c93273 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1412,7 +1412,7 @@ void ST_drawTitleCard(void) lt_lasttic = lt_ticker; luahook: - if (renderisnewtic) + //if (renderisnewtic) { LUA_HUD_ClearDrawList(luahuddrawlist_titlecard); LUA_HUDHOOK(titlecard, luahuddrawlist_titlecard); From 930b1355ed5634110dfa6895b14d0f510c4a70f6 Mon Sep 17 00:00:00 2001 From: spherallic Date: Fri, 14 Apr 2023 12:03:21 +0200 Subject: [PATCH 098/478] Don't call P_ResetCamera when spawning a bot --- src/g_game.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 8c497a72d..a0ea9ae88 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2825,6 +2825,9 @@ void G_MovePlayerToSpawnOrStarpost(INT32 playernum) R_ResetMobjInterpolationState(players[playernum].mo); + if (players[playernum].bot) // don't reset the camera for bots + return; + if (playernum == consoleplayer) P_ResetCamera(&players[playernum], &camera); else if (playernum == secondarydisplayplayer) From e4f92cc6676afe8af23c01b1d1be6cc1dd3f4dc2 Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 18 Apr 2023 02:04:23 +0200 Subject: [PATCH 099/478] Always important --- src/w_wad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/w_wad.c b/src/w_wad.c index 40073fc55..456afef7b 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1035,7 +1035,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup) return W_InitFileError(path, startup); } - important = 0; /// \todo Implement a W_VerifyFolder. + important = 1; /// \todo Implement a W_VerifyFolder. // Remove path delimiters. p = path + (strlen(path) - 1); From 072dd2eda761981df5dbd4165d4ec6638d599cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 18 Apr 2023 20:46:13 +0200 Subject: [PATCH 100/478] Fix segfault when removing source from ShouldDamage --- src/p_inter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 8bc5c95e4..de13202ab 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3546,6 +3546,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da UINT8 shouldForce = LUA_HookShouldDamage(target, inflictor, source, damage, damagetype); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed + if (P_MobjWasRemoved(source)) + source = NULL; if (shouldForce == 1) force = true; else if (shouldForce == 2) From ad412c9700cb19dec4ad795857796f8bb5900ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 18 Apr 2023 22:08:26 +0200 Subject: [PATCH 101/478] Fix segfault when damaging mobj with no painstate --- src/p_inter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 8bc5c95e4..fc193ac94 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3763,6 +3763,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da else P_SetMobjState(target, target->info->painstate); + if (P_MobjWasRemoved(target)) + return false; + if (target->type == MT_HIVEELEMENTAL) target->extravalue1 += 3; From e5a1fee7596a5ed15034f5604693a22c9635d739 Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 19 Apr 2023 00:21:10 +0200 Subject: [PATCH 102/478] Adjust default look/turn axis for new SDL2 version --- src/g_game.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index a0ea9ae88..b7f3eb24a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -411,8 +411,8 @@ consvar_t cv_cam_lockonboss[2] = { consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); @@ -422,8 +422,8 @@ consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "Y-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); -consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL); +consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL); consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL); From 6ff37b47d9b60b8c71768ba3ca2cb9d1d8aae333 Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 19 Apr 2023 12:13:29 +0200 Subject: [PATCH 103/478] Skip emerald bounce logic in Y_Ticker on dedicated --- src/y_inter.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 7b4b6f5cf..cfd1e106e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1133,7 +1133,11 @@ void Y_Ticker(void) } // emerald bounce - if (intertic <= 1) + if (dedicated) + { + // dedicated servers don't need this, especially since it crashes when stagefailed + } + else if (intertic <= 1) { data.spec.emeraldbounces = 0; data.spec.emeraldmomy = 20; From c2c430853ccb47174281908f131f87a0059ac560 Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 19 Apr 2023 20:17:50 +0200 Subject: [PATCH 104/478] If Lua disabled intermission emeralds, skip sounds --- src/y_inter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index cfd1e106e..f0777add7 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1133,9 +1133,10 @@ void Y_Ticker(void) } // emerald bounce - if (dedicated) + if (dedicated || !LUA_HudEnabled(hud_intermissionemeralds)) { // dedicated servers don't need this, especially since it crashes when stagefailed + // also skip this if Lua disabled intermission emeralds, so it doesn't play sounds } else if (intertic <= 1) { From 2d3153079b046ae9c5f585e77d677022aabf957b Mon Sep 17 00:00:00 2001 From: SteelT Date: Fri, 21 Apr 2023 12:57:37 -0400 Subject: [PATCH 105/478] A_PointyThink crash fix (patch from #827) Fixes A_PointyThink crashing in certain scenarios --- src/p_enemy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index 63d430eb6..ca947fc20 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1589,6 +1589,10 @@ void A_PointyThink(mobj_t *actor) if (!actor->tracer) // For some reason we do not have spike balls... return; + // Catch case where actor lastlook is -1 (which segfaults the following blocks) + if (actor->lastlook < 0) + return; + // Position spike balls relative to the value of 'lastlook'. ball = actor->tracer; From 98dcf2d228141015c6fcdc2a054454357037dec6 Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 24 Apr 2023 23:23:47 +0200 Subject: [PATCH 106/478] Tweak yellow/green/blue/red/peridot text colors --- src/console.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/console.c b/src/console.c index 33d59046e..5ada6dd94 100644 --- a/src/console.c +++ b/src/console.c @@ -382,16 +382,16 @@ static void CON_SetupColormaps(void) // 0x1 0x3 0x9 0xF colset(magentamap, 177, 177, 178, 178, 178, 180, 180, 180, 182, 182, 182, 182, 184, 184, 184, 185); - colset(yellowmap, 82, 82, 73, 73, 73, 64, 64, 64, 66, 66, 66, 66, 67, 67, 67, 68); - colset(lgreenmap, 96, 96, 98, 98, 98, 101, 101, 101, 104, 104, 104, 104, 106, 106, 106, 107); - colset(bluemap, 146, 146, 147, 147, 147, 149, 149, 149, 152, 152, 152, 152, 155, 155, 155, 157); - colset(redmap, 32, 32, 33, 33, 33, 35, 35, 35, 39, 39, 39, 39, 42, 42, 42, 44); + colset(yellowmap, 82, 82, 73, 73, 73, 74, 74, 74, 66, 66, 66, 66, 67, 67, 67, 68); + colset(lgreenmap, 96, 96, 98, 98, 98, 100, 100, 100, 103, 103, 103, 103, 105, 105, 105, 107); + colset(bluemap, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149, 149, 149, 150, 150, 150, 151); + colset(redmap, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 37, 37, 37, 39); colset(graymap, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23); colset(orangemap, 50, 50, 52, 52, 52, 54, 54, 54, 56, 56, 56, 56, 59, 59, 59, 60); colset(skymap, 129, 129, 130, 130, 130, 131, 131, 131, 133, 133, 133, 133, 135, 135, 135, 136); colset(purplemap, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165); colset(aquamap, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 125); - colset(peridotmap, 72, 72, 188, 188, 189, 189, 189, 189, 190, 190, 190, 190, 191, 191, 191, 94); + colset(peridotmap, 73, 73, 188, 188, 188, 189, 189, 189, 190, 190, 190, 190, 191, 191, 191, 94); colset(azuremap, 144, 144, 145, 145, 145, 146, 146, 146, 170, 170, 170, 170, 171, 171, 171, 172); colset(brownmap, 219, 219, 221, 221, 221, 222, 222, 222, 224, 224, 224, 224, 227, 227, 227, 229); colset(rosymap, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 203, 204, 204, 204, 205); From d6cafea571cab556c89ff31343af0242a797378b Mon Sep 17 00:00:00 2001 From: spherallic Date: Fri, 28 Apr 2023 15:30:02 +0200 Subject: [PATCH 107/478] Don't force FLS to false after a pre-map cutscene --- src/f_finale.c | 13 +++++++------ src/f_finale.h | 2 +- src/g_game.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index fe94b924c..6560c24f1 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -337,7 +337,7 @@ static tic_t introscenetime[NUMINTROSCENES] = }; // custom intros -void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer); +void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS); void F_StartIntro(void) { @@ -349,7 +349,7 @@ void F_StartIntro(void) if (!cutscenes[introtoplay - 1]) D_StartTitle(); else - F_StartCustomCutscene(introtoplay - 1, false, false); + F_StartCustomCutscene(introtoplay - 1, false, false, false); return; } @@ -1257,7 +1257,7 @@ void F_StartCredits(void) if (creditscutscene) { - F_StartCustomCutscene(creditscutscene - 1, false, false); + F_StartCustomCutscene(creditscutscene - 1, false, false, false); return; } @@ -3859,7 +3859,7 @@ static INT32 scenenum, cutnum; static INT32 picxpos, picypos, picnum, pictime, picmode, numpics, pictoloop; static INT32 textxpos, textypos; static boolean cutsceneover = false; -static boolean runningprecutscene = false, precutresetplayer = false; +static boolean runningprecutscene = false, precutresetplayer = false, precutFLS = false; static void F_AdvanceToNextScene(void) { @@ -3928,7 +3928,7 @@ void F_EndCutScene(void) if (runningprecutscene) { if (server) - D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, false); + D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, precutFLS); } else { @@ -3943,7 +3943,7 @@ void F_EndCutScene(void) } } -void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer) +void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS) { if (!cutscenes[cutscenenum]) return; @@ -3962,6 +3962,7 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset cutsceneover = false; runningprecutscene = precutscene; precutresetplayer = resetplayer; + precutFLS = FLS; scenenum = picnum = 0; cutnum = cutscenenum; diff --git a/src/f_finale.h b/src/f_finale.h index e37b45253..6ea1b5537 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -52,7 +52,7 @@ void F_EndingDrawer(void); void F_CreditTicker(void); void F_CreditDrawer(void); -void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer); +void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS); void F_CutsceneDrawer(void); void F_EndCutScene(void); diff --git a/src/g_game.c b/src/g_game.c index b7f3eb24a..0d5181b07 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4108,7 +4108,7 @@ void G_AfterIntermission(void) && stagefailed == false) { // Start a custom cutscene. - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); + F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false, false); } else { @@ -4958,7 +4958,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean imcontinuing = false; if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene. - F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); + F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer, FLS); else G_DoLoadLevel(resetplayer); From 901c7362ed65434ad83c623506d8a00fc4b9099d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 30 Apr 2023 14:05:10 +0200 Subject: [PATCH 108/478] Fix segfault when P_RemoveMobj is called within A_FaceTarget action --- src/p_enemy.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index 63d430eb6..af629a299 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1571,6 +1571,8 @@ void A_PointyThink(mobj_t *actor) // Okay, we found the closest player. Let's move based on his movement. P_SetTarget(&actor->target, player->mo); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y) < P_AproxDistance(player->mo->x + player->mo->momx - actor->x, player->mo->y + player->mo->momy - actor->y)) sign = -1; // Player is moving away @@ -1686,6 +1688,8 @@ void A_HoodFire(mobj_t *actor) } A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (!(arrow = P_SpawnMissile(actor, actor->target, (mobjtype_t)locvar1))) return; @@ -2266,6 +2270,8 @@ void A_VultureVtol(mobj_t *actor) actor->flags |= MF_FLOAT; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; S_StopSound(actor); @@ -2364,6 +2370,9 @@ void A_VultureHover(mobj_t *actor) P_VultureHoverParticle(actor); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + targetz = actor->target->z + actor->target->height / 2; for (i = -1; i <= 1; i++) { @@ -2680,6 +2689,8 @@ void A_LobShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->eflags & MFE_VERTICALFLIP) { @@ -2775,6 +2786,8 @@ void A_FireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); @@ -2813,6 +2826,8 @@ void A_SuperFireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(48*FRACUNIT + locvar2*FRACUNIT, actor->scale); @@ -2860,6 +2875,8 @@ void A_BossFireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; switch (locvar2) { @@ -2947,6 +2964,8 @@ void A_Boss7FireMissiles(mobj_t *actor) } A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; S_StartSound(NULL, locvar2); @@ -3331,6 +3350,8 @@ void A_SkullAttack(mobj_t *actor) if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); @@ -3442,6 +3463,9 @@ void A_BossZoom(mobj_t *actor) if (actor->info->attacksound) S_StartAttackSound(actor, actor->info->attacksound); A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + an = actor->angle >> ANGLETOFINESHIFT; actor->momx = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINECOSINE(an)); actor->momy = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINESINE(an)); @@ -5539,6 +5563,9 @@ void A_JetgShoot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); if (ultimatemode) @@ -5573,6 +5600,9 @@ void A_ShootBullet(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); if (actor->info->attacksound) @@ -7431,6 +7461,8 @@ void A_Boss7Chase(mobj_t *actor) && (actor->target->player->powers[pw_carry] == CR_GENERIC)) { A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, S_BLACKEGG_SHOOT1); actor->movecount = TICRATE + P_RandomByte()/2; return; @@ -7448,6 +7480,8 @@ void A_Boss7Chase(mobj_t *actor) if (actor->z < 1056*FRACUNIT) { A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, actor->info->xdeathstate); actor->movecount = 7*TICRATE + P_RandomByte(); break; @@ -7456,6 +7490,8 @@ void A_Boss7Chase(mobj_t *actor) /* FALLTHRU */ case 1: // Chaingun Goop A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, S_BLACKEGG_SHOOT1); if (actor->health > actor->info->damage) @@ -7465,6 +7501,8 @@ void A_Boss7Chase(mobj_t *actor) break; case 2: // Homing Missile A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; P_SetMobjState(actor, actor->info->missilestate); S_StartSound(0, sfx_beflap); break; @@ -8182,6 +8220,9 @@ void A_Boss3Path(mobj_t *actor) P_SetTarget(&actor->target, actor->tracer->target); var1 = 0, var2 = 0; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + if (actor->tracer->state == &states[actor->tracer->info->missilestate]) P_SetMobjState(actor, actor->info->missilestate); return; @@ -9856,6 +9897,8 @@ void A_SplitShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; { const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT; const fixed_t fasin = FINESINE(an); @@ -9920,6 +9963,9 @@ void A_MultiShot(mobj_t *actor) if (actor->target) A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + if(loc1lw > 90) ad = FixedMul(90*FRACUNIT, actor->scale); else @@ -11064,6 +11110,8 @@ void A_VileTarget(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; // Determine object to spawn if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) @@ -11151,6 +11199,8 @@ void A_VileAttack(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (locvar1 <= 0 || locvar1 >= NUMSFX) soundtoplay = sfx_brakrx; @@ -11469,6 +11519,8 @@ void A_BrakFireShot(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(64*FRACUNIT, actor->scale)) @@ -11586,6 +11638,9 @@ void A_BrakLobShot(mobj_t *actor) // Okay, complicated math done. Let's fire our object already, sheesh. A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; + if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) typeOfShot = MT_CANNONBALL; else typeOfShot = (mobjtype_t)locvar1; @@ -12670,6 +12725,8 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor) return; A_FaceTarget(actor); + if (P_MobjWasRemoved(actor)) + return; if (actor->extravalue1) actor->extravalue1--; From 03971f58a924e41c0f794a9dcbe459052835a381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Thu, 4 May 2023 22:42:51 +0200 Subject: [PATCH 109/478] Fix segfault when shields are removed after thinking --- src/p_mobj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ee4440b73..0704c15a7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6765,7 +6765,8 @@ void P_RunShields(void) // run shields for (i = 0; i < numshields; i++) { - P_ShieldLook(shields[i], shields[i]->threshold); + if (!P_MobjWasRemoved(shields[i])) + P_ShieldLook(shields[i], shields[i]->threshold); P_SetTarget(&shields[i], NULL); } numshields = 0; From ed46dd08a6a2ae85f7eebc9d15cb5c2c024e0e96 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 7 May 2023 17:33:12 +0200 Subject: [PATCH 110/478] Prevent tmthing crash with P_SpawnParaloop in Lua --- src/lua_baselib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6e258c82a..db06d53dd 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -874,6 +874,7 @@ static int lib_pGetClosestAxis(lua_State *L) static int lib_pSpawnParaloop(lua_State *L) { + mobj_t *ptmthing = tmthing; fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); fixed_t z = luaL_checkfixed(L, 3); @@ -890,6 +891,7 @@ static int lib_pSpawnParaloop(lua_State *L) if (nstate >= NUMSTATES) return luaL_error(L, "state %d out of range (0 - %d)", nstate, NUMSTATES-1); P_SpawnParaloop(x, y, z, radius, number, type, nstate, rotangle, spawncenter); + P_SetTarget(&tmthing, ptmthing); return 0; } From b99ecde7b85ae78482762f0e73162b817e7edcfd Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 7 May 2023 17:42:39 +0200 Subject: [PATCH 111/478] Fix [BOT] indicator color not being cleared --- src/lua_baselib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index db06d53dd..6f5b46e30 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3589,14 +3589,14 @@ static int lib_gAddPlayer(lua_State *L) char joinmsg[256]; // Truncate bot name - player_names[newplayernum][sizeof(*player_names) - 7] = '\0'; // The length of colored [BOT] + 1 + player_names[newplayernum][sizeof(*player_names) - 8] = '\0'; // The length of colored [BOT] + 1 strcpy(joinmsg, M_GetText("\x82*Bot %s has joined the game (player %d)")); strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum)); HU_AddChatText(joinmsg, false); // Append blue [BOT] tag at the end - strlcat(player_names[newplayernum], "\x84[BOT]", sizeof(*player_names)); + strlcat(player_names[newplayernum], "\x84[BOT]\x80", sizeof(*player_names)); } LUA_PushUserdata(L, newplayer, META_PLAYER); From b487a71533e4d3058b703362b6a828d51069c6cc Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 14 May 2023 16:26:34 +0200 Subject: [PATCH 112/478] Fix light fades being unable to lower light levels --- src/p_lights.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_lights.c b/src/p_lights.c index 75455da73..4b6a3673b 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -353,8 +353,8 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean else { // Speed means increment per tic (literally speed). - ll->timer = FixedDiv((destvalue<fixedcurlevel, speed<>FRACBITS; - ll->fixedpertic = speed<timer = abs(FixedDiv((destvalue<fixedcurlevel, speed<>FRACBITS); + ll->fixedpertic = ll->destlevel < ll->sourcelevel ? -speed< Date: Thu, 4 May 2023 16:17:10 +0200 Subject: [PATCH 113/478] 2.2.11 --- appveyor.yml | 2 +- assets/CMakeLists.txt | 1 + src/config.h.in | 5 +++-- src/doomdef.h | 2 +- src/version.h | 2 +- src/win32/Srb2win.rc | 4 ++-- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 348b727b1..e3348d35c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.2.10.{branch}-{build} +version: 2.2.11.{branch}-{build} os: MinGW environment: diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index de164b23f..dfb2f4180 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -29,6 +29,7 @@ set(SRB2_ASSETS_GAME "srb2.pk3" "player.dta" "zones.pk3" + "patch.pk3" "music.dta" "models.dat" ) diff --git a/src/config.h.in b/src/config.h.in index 22cfd6481..3d6d98375 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -27,12 +27,13 @@ * Last updated 2020 / 10 / 02 - v2.2.8 - patch.pk3 * Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3 * Last updated 2022 / 03 / 06 - v2.2.10 - main assets + * Last updated 2023 / 05 / 02 - v2.2.11 - patch.pk3 & zones.pk3 */ #define ASSET_HASH_SRB2_PK3 "ad911f29a28a18968ee5b2d11c2acb39" -#define ASSET_HASH_ZONES_PK3 "188a2bfd552196609323fc91ec1cdb22" +#define ASSET_HASH_ZONES_PK3 "1c8adf8d079ecb87d00081f158acf3c7" #define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c" #ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_PK3 "7d467a883f7887b3c311798ee2f56b6a" +#define ASSET_HASH_PATCH_PK3 "2e69558bce3b9610624549a75e29e19b" #endif #endif diff --git a/src/doomdef.h b/src/doomdef.h index 3abe27112..d521d4fbb 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -152,7 +152,7 @@ extern char logfilename[1024]; // Does this version require an added patch file? // Comment or uncomment this as necessary. -// #define USE_PATCH_DTA +#define USE_PATCH_DTA // Enforce a limit of loaded WAD files. //#define ENFORCE_WAD_LIMIT diff --git a/src/version.h b/src/version.h index f8b09ada6..083c53134 100644 --- a/src/version.h +++ b/src/version.h @@ -12,4 +12,4 @@ #define MODVERSION 52 // Define this as a prerelease version suffix (pre#, RC#) -#define BETAVERSION "pre3" +//#define BETAVERSION "pre1" diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index 07898dbc1..869c0e7d3 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -77,8 +77,8 @@ END #include "../doomdef.h" // Needed for version string VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,2,10,0 - PRODUCTVERSION 2,2,10,0 + FILEVERSION 2,2,11,0 + PRODUCTVERSION 2,2,11,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From 6bb3ee226f825a013bd17b200d4d491e3170d780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 16 May 2023 19:16:14 +0200 Subject: [PATCH 114/478] Fix segfault when going up steep slopes in rare cases --- src/p_slopes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index cf7807d4e..48a13a07d 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -869,7 +869,7 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) vector3_t slopemom, axis; angle_t ang; - if (mo->standingslope->flags & SL_NOPHYSICS) + if (slope->flags & SL_NOPHYSICS) return 0; // If there's physics, time for launching. From d4951f7cdd804a237ded2ed66711d69901673636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 16 May 2023 22:18:11 +0200 Subject: [PATCH 115/478] Fix segfault when Crushstaceans hit a player with Armageddon shield --- src/p_enemy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index ca947fc20..618665c97 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2231,7 +2231,7 @@ void A_CrushclawLaunch(mobj_t *actor) } } - if (!actor->target) + if (P_MobjWasRemoved(actor->target)) return; { From 2f98cd3b972b35427ef42978af46bade61874f5e Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Fri, 19 May 2023 14:26:30 -0300 Subject: [PATCH 116/478] Fix I_GetFreeMem --- src/android/i_system.c | 2 +- src/dummy/i_system.c | 2 +- src/i_system.h | 2 +- src/sdl/i_system.c | 13 ++++++------- src/z_zone.c | 10 +++++----- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/android/i_system.c b/src/android/i_system.c index f0edcc17e..ff8b88de5 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -24,7 +24,7 @@ static INT64 start_time; // as microseconds since the epoch // I should probably return how much memory is remaining // for this process, considering Android's process memory limit. -UINT32 I_GetFreeMem(UINT32 *total) +size_t I_GetFreeMem(size_t *total) { // what the heck? sysinfo() is partially missing in bionic? /* struct sysinfo si; */ diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index 997115ad0..00550c410 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -8,7 +8,7 @@ UINT8 graphics_started = 0; UINT8 keyboard_started = 0; -UINT32 I_GetFreeMem(UINT32 *total) +size_t I_GetFreeMem(UINT32 *total) { *total = 0; return 0; diff --git a/src/i_system.h b/src/i_system.h index 957150fe6..deea9f8a8 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -40,7 +40,7 @@ extern UINT8 keyboard_started; \return free memory in the system */ -UINT32 I_GetFreeMem(UINT32 *total); +size_t I_GetFreeMem(size_t *total); /** \brief Returns precise time value for performance measurement. The precise time should be a monotonically increasing counter, and will wrap. diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index e328bedc2..67ee8d668 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2962,8 +2962,7 @@ static long get_entry(const char* name, const char* buf) } #endif -// quick fix for compil -UINT32 I_GetFreeMem(UINT32 *total) +size_t I_GetFreeMem(size_t *total) { #ifdef FREEBSD struct vmmeter sum; @@ -3011,14 +3010,14 @@ UINT32 I_GetFreeMem(UINT32 *total) info.dwLength = sizeof (MEMORYSTATUS); GlobalMemoryStatus( &info ); if (total) - *total = (UINT32)info.dwTotalPhys; - return (UINT32)info.dwAvailPhys; + *total = (size_t)info.dwTotalPhys; + return (size_t)info.dwAvailPhys; #elif defined (__linux__) /* Linux */ char buf[1024]; char *memTag; - UINT32 freeKBytes; - UINT32 totalKBytes; + size_t freeKBytes; + size_t totalKBytes; INT32 n; INT32 meminfo_fd = -1; long Cached; @@ -3049,7 +3048,7 @@ UINT32 I_GetFreeMem(UINT32 *total) } memTag += sizeof (MEMTOTAL); - totalKBytes = atoi(memTag); + totalKBytes = (size_t)atoi(memTag); if ((memTag = strstr(buf, MEMAVAILABLE)) == NULL) { diff --git a/src/z_zone.c b/src/z_zone.c index c012816ff..11c4bcb2c 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -106,14 +106,14 @@ static void Command_Memdump_f(void); */ void Z_Init(void) { - UINT32 total, memfree; + size_t total, memfree; memset(&head, 0x00, sizeof(head)); head.next = head.prev = &head; memfree = I_GetFreeMem(&total)>>20; - CONS_Printf("System memory: %uMB - Free: %uMB\n", total>>20, memfree); + CONS_Printf("System memory: %sMB - Free: %sMB\n", sizeu1(total>>20), sizeu2(memfree)); // Note: This allocates memory. Watch out. COM_AddCommand("memfree", Command_Memfree_f, COM_LUA); @@ -791,7 +791,7 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag) */ static void Command_Memfree_f(void) { - UINT32 freebytes, totalbytes; + size_t freebytes, totalbytes; Z_CheckHeap(-1); CONS_Printf("\x82%s", M_GetText("Memory Info\n")); @@ -824,8 +824,8 @@ static void Command_Memfree_f(void) CONS_Printf("\x82%s", M_GetText("System Memory Info\n")); freebytes = I_GetFreeMem(&totalbytes); - CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10); - CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10); + CONS_Printf(M_GetText(" Total physical memory: %s KB\n"), sizeu1(totalbytes>>10)); + CONS_Printf(M_GetText("Available physical memory: %s KB\n"), sizeu1(freebytes>>10)); } #ifdef ZDEBUG From 7dc74fc364b688a44279a7d29322798fb838fd99 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Fri, 19 May 2023 15:12:20 -0300 Subject: [PATCH 117/478] Fix declaration of I_GetFreeMem in src/dummy/i_system.c --- src/dummy/i_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index 00550c410..8556c0248 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -8,7 +8,7 @@ UINT8 graphics_started = 0; UINT8 keyboard_started = 0; -size_t I_GetFreeMem(UINT32 *total) +size_t I_GetFreeMem(size_t *total) { *total = 0; return 0; From eb1492fe6e501001a2271fa133bd76c0b0612715 Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 23 May 2023 17:51:56 +0200 Subject: [PATCH 118/478] Zone Builder config updates --- extras/conf/SRB2-22.cfg | 299 ++++++++++++++++++++++------------------ 1 file changed, 163 insertions(+), 136 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index ae905b637..b5078cd0c 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -41,6 +41,9 @@ linetagindicatesectors = true; // The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder formatinterface = "SRB2MapSetIO"; + +//Maximum safe map size check (0 means skip check) +safeboundary = 0; //Sky textures for vanilla maps defaultskytextures @@ -77,7 +80,7 @@ defaultskytextures defaultlumpname = "MAP01"; // Default testing parameters -testparameters = "-file \"%AP\" \"%F\" -warp %L"; +testparameters = "-folder \"%AF\" -file \"%AA\" \"%F\" -warp %L"; testshortpaths = true; // Default nodebuilder configurations @@ -437,6 +440,8 @@ sectortypes 144 = "Egg Capsule"; 160 = "Special Stage Time/Spheres Parameters "; 176 = "Custom Global Gravity "; + 512 = "Wind/Current "; + 1024 = "Conveyor Belt "; 1280 = "Speed Pad"; 1536 = "Flip Gravity on Jump"; 4096 = "Star Post Activator"; @@ -496,6 +501,8 @@ gen_sectortypes third { 0 = "Normal"; + 512 = "Wind/Current "; + 1024 = "Conveyor Belt "; 1280 = "Speed Pad"; 1536 = "Flip Gravity on Jump"; } @@ -578,7 +585,7 @@ linedeftypes title = "Per-Sector Gravity"; prefix = "(1)"; flags64text = "[6] Flip in reverse gravity"; - flags8192text = "[13] Reverse while inside"; + flags8192text = "[13] Cancel MF2_OBJECTFLIP"; } 5 @@ -641,35 +648,35 @@ linedeftypes 96 { - title = "Apply Tag to Tagged Sectors"; + title = "Add Front Sector Tag to Tagged Sectors"; prefix = "(96)"; flags1024text = "[10] Offsets are target tags"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 97 { - title = "Apply Tag to Front Sector"; + title = "Add Tag to Front Sector"; prefix = "(97)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 98 { - title = "Apply Tag to Back Sector"; + title = "Add Tag to Back Sector"; prefix = "(98)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 99 { - title = "Apply Tag to Front and Back Sectors"; + title = "Add Tag to Front and Back Sectors"; prefix = "(99)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 540 @@ -990,6 +997,7 @@ linedeftypes flags128text = "[7] Only block non-players"; 3dfloor = true; 3dfloorflags = "47"; + invisiblefof = true; } 140 @@ -1227,6 +1235,7 @@ linedeftypes prefix = "(223)"; 3dfloor = true; 3dfloorflags = "41"; + invisiblefof = true; } } @@ -1524,6 +1533,7 @@ linedeftypes prefix = "(200)"; 3dfloor = true; 3dfloorflags = "20201"; + invisiblefof = true; } 201 @@ -1532,6 +1542,7 @@ linedeftypes prefix = "(201)"; 3dfloor = true; 3dfloorflags = "201"; + invisiblefof = true; } 202 @@ -1539,7 +1550,8 @@ linedeftypes title = "Fog Block"; prefix = "(202)"; 3dfloor = true; - 3dfloorflags = "3EF19"; + 3dfloorflags = "3EF01"; + invisiblefof = true; } 250 @@ -3624,7 +3636,7 @@ thingtypes 3328 = "3D Mode Start"; } - + starts { color = 1; // Blue @@ -3814,7 +3826,7 @@ thingtypes enemies { - color = 9; // Light_Blue + color = 9; // Light Blue arrow = 1; title = "Enemies"; @@ -4124,7 +4136,7 @@ thingtypes bosses { - color = 8; // Dark_Gray + color = 4; // Dark Red arrow = 1; title = "Bosses"; @@ -4223,6 +4235,7 @@ thingtypes sprite = "internal:capsule"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 292 { @@ -4310,13 +4323,13 @@ thingtypes 308 { title = "CTF Team Ring (Red)"; - sprite = "internal:TRNGA0r"; + sprite = "internal:TRNGA0R"; width = 16; } 309 { title = "CTF Team Ring (Blue)"; - sprite = "internal:TRNGA0b"; + sprite = "internal:TRNGA0B"; width = 16; } 330 @@ -4353,7 +4366,7 @@ thingtypes collectibles { - color = 10; // Light_Green + color = 10; // Light Green title = "Other Collectibles"; width = 16; height = 32; @@ -4457,6 +4470,7 @@ thingtypes flags8text = "[8] Random (Weak)"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; 400 { @@ -4589,6 +4603,7 @@ thingtypes flags1text = "[1] Run linedef executor on pop"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; 431 { @@ -4659,7 +4674,7 @@ thingtypes generic { - color = 11; // Light_Cyan + color = 11; // Light Cyan title = "Generic Items & Hazards"; 500 @@ -4765,7 +4780,7 @@ thingtypes springs { - color = 12; // Light_Red + color = 12; // Light Red title = "Springs and Fans"; width = 20; height = 16; @@ -4927,13 +4942,13 @@ thingtypes { arrow = 0; title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalyellow"; } 601 { arrow = 0; title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalred"; height = 1024; } 602 @@ -4951,7 +4966,7 @@ thingtypes 604 { title = "Circle of Rings"; - sprite = "RINGA0"; + sprite = "internal:circlering"; width = 96; height = 192; unflippable = true; @@ -4960,7 +4975,7 @@ thingtypes 605 { title = "Circle of Rings (Big)"; - sprite = "RINGA0"; + sprite = "internal:circlebigring"; width = 192; unflippable = true; centerHitbox = true; @@ -4968,7 +4983,7 @@ thingtypes 606 { title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circlesphere"; width = 96; height = 192; unflippable = true; @@ -4977,7 +4992,7 @@ thingtypes 607 { title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigsphere"; width = 192; unflippable = true; centerHitbox = true; @@ -4985,7 +5000,7 @@ thingtypes 608 { title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circleringsphere"; width = 96; height = 192; unflippable = true; @@ -4994,13 +5009,77 @@ thingtypes 609 { title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigringsphere"; width = 192; unflippable = true; centerHitbox = true; } } + ambience + { + color = 8; // Dark Gray + title = "Ambience"; + width = 8; + height = 16; + sprite = "internal:ambiance"; + + 700 + { + title = "Water Ambience A (Large)"; + } + + 701 + { + title = "Water Ambience B (Large)"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + } + + 704 + { + title = "Water Ambience E (Small)"; + } + + 705 + { + title = "Water Ambience F (Small)"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + } + + 708 + { + title = "Disco Ambience"; + } + + 709 + { + title = "Volcano Ambience"; + } + + 710 + { + title = "Machine Ambience"; + } + } + invisible { color = 15; // White @@ -5009,72 +5088,6 @@ thingtypes height = 16; sprite = "UNKNA0"; - 700 - { - title = "Water Ambience A (Large)"; - sprite = "internal:ambiance"; - } - - 701 - { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; - } - - 702 - { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; - } - - 703 - { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; - } - - 704 - { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; - } - - 705 - { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; - } - - 706 - { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; - } - - 707 - { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; - } - - 708 - { - title = "Disco Ambience"; - sprite = "internal:ambiance"; - } - - 709 - { - title = "Volcano Ambience"; - sprite = "internal:ambiance"; - } - - 710 - { - title = "Machine Ambience"; - sprite = "internal:ambiance"; - } - 750 { title = "Slope Vertex"; @@ -5083,6 +5096,7 @@ thingtypes fixedrotation = 1; parametertext = "Absolute?"; flagsvaluetext = "Absolute Z"; + tagthing = true; } 751 @@ -5128,20 +5142,22 @@ thingtypes 756 { title = "Blast Linedef Executor"; - sprite = "TOADA0"; + sprite = "internal:blastexec"; width = 32; height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 757 { title = "Fan Particle Generator"; - sprite = "PRTLA0"; + sprite = "internal:fanparticles"; width = 8; height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 758 { @@ -5154,6 +5170,8 @@ thingtypes sprite = "internal:polyanchor"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 761 @@ -5162,6 +5180,8 @@ thingtypes sprite = "internal:polycenter"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 762 @@ -5170,6 +5190,8 @@ thingtypes sprite = "internal:polycentercrush"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 780 { @@ -5183,7 +5205,7 @@ thingtypes greenflower { - color = 10; // Green + color = 2; // Green title = "Greenflower"; 800 @@ -5288,7 +5310,7 @@ thingtypes technohill { - color = 10; // Green + color = 2; // Green title = "Techno Hill"; 900 @@ -5332,7 +5354,7 @@ thingtypes deepsea { - color = 10; // Green + color = 2; // Green title = "Deep Sea"; 1000 @@ -5467,7 +5489,7 @@ thingtypes castleeggman { - color = 10; // Green + color = 2; // Green title = "Castle Eggman"; 1100 @@ -5516,6 +5538,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1105 { @@ -5528,6 +5551,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1106 { @@ -5540,23 +5564,25 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1107 { title = "Chain Spawnpoint"; - sprite = "BMCHA0"; + sprite = "BMCHB0"; width = 17; height = 34; flags8text = "[8] Double size"; angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1108 { arrow = 1; title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; + sprite = "SMCHA0"; width = 17; height = 34; flags8text = "[8] Double size"; @@ -5572,6 +5598,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1110 { @@ -5583,6 +5610,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1111 { @@ -5736,7 +5764,7 @@ thingtypes aridcanyon { - color = 10; // Green + color = 2; // Green title = "Arid Canyon"; 1200 @@ -5764,6 +5792,7 @@ thingtypes height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 1203 { @@ -5955,7 +5984,7 @@ thingtypes redvolcano { - color = 10; // Green + color = 2; // Green title = "Red Volcano"; 1300 @@ -6055,7 +6084,7 @@ thingtypes botanicserenity { - color = 10; // Green + color = 2; // Green title = "Botanic Serenity"; width = 16; height = 32; @@ -6298,7 +6327,7 @@ thingtypes azuretemple { - color = 10; // Green + color = 2; // Green title = "Azure Temple"; 1500 @@ -6374,7 +6403,7 @@ thingtypes dreamhill { - color = 10; // Green + color = 2; // Green title = "Dream Hill"; 1600 @@ -6402,8 +6431,8 @@ thingtypes nightstrk { - color = 13; // Pink - title = "NiGHTS Track"; + color = 16; // Light Pink + title = "NiGHTS Track & Basics"; width = 8; height = 4096; sprite = "UNKNA0"; @@ -6438,6 +6467,19 @@ thingtypes flagsvaluetext = "Order"; parametertext = "Mare"; } + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags1text = "[1] Align player to middle"; + flags4text = "[4] Align player to top"; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + fixedrotation = 1; + parametertext = "Height"; + } 1710 { title = "Ideya Capture"; @@ -6455,20 +6497,6 @@ thingtypes title = "NiGHTS Items"; width = 16; height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - flags1text = "[1] Align player to middle"; - flags4text = "[4] Align player to top"; - flags8text = "[8] Die upon time up"; - angletext = "Time limit"; - fixedrotation = 1; - parametertext = "Height"; - } 1704 { arrow = 1; @@ -6479,13 +6507,12 @@ thingtypes unflippable = true; flagsvaluetext = "Pitch"; angletext = "Yaw"; - fixedrotation = 1; } 1705 { arrow = 1; title = "Hoop (Generic)"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; unflippable = true; @@ -6502,7 +6529,6 @@ thingtypes height = 24; flags8height = 24; flags8text = "[8] Float"; - unflippable = true; } 1707 { @@ -6547,7 +6573,7 @@ thingtypes flags2text = "[2] Radius +32"; flags4text = "[4] Radius +64"; flags8text = "[8] Radius +128"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; unflippable = true; @@ -6657,7 +6683,7 @@ thingtypes christmasdisco { - color = 10; // Green + color = 2; // Green title = "Christmas & Disco"; 1850 @@ -6760,7 +6786,7 @@ thingtypes stalagmites { - color = 10; // Green + color = 2; // Green title = "Stalagmites"; width = 16; height = 40; @@ -6839,7 +6865,7 @@ thingtypes hauntedheights { - color = 10; // Green + color = 2; // Green title = "Haunted Heights"; 2000 @@ -6928,7 +6954,7 @@ thingtypes frozenhillside { - color = 10; // Green + color = 2; // Green title = "Frozen Hillside"; 2100 @@ -6979,7 +7005,7 @@ thingtypes tutorial { - color = 10; // Green + color = 2; // Green title = "Tutorial"; 799 @@ -6990,10 +7016,11 @@ thingtypes height = 144; parametertext = "Start frame"; } + } flickies { - color = 10; // Green + color = 3; // Teal title = "Flickies"; width = 8; height = 20; From b9c86a0f7f579253f622fc00ca8e5ac9b513f89d Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 23 May 2023 17:51:56 +0200 Subject: [PATCH 119/478] Zone Builder config updates --- extras/conf/SRB2-22.cfg | 299 ++++++++++++++++++++++------------------ 1 file changed, 163 insertions(+), 136 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index ae905b637..b5078cd0c 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -41,6 +41,9 @@ linetagindicatesectors = true; // The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder formatinterface = "SRB2MapSetIO"; + +//Maximum safe map size check (0 means skip check) +safeboundary = 0; //Sky textures for vanilla maps defaultskytextures @@ -77,7 +80,7 @@ defaultskytextures defaultlumpname = "MAP01"; // Default testing parameters -testparameters = "-file \"%AP\" \"%F\" -warp %L"; +testparameters = "-folder \"%AF\" -file \"%AA\" \"%F\" -warp %L"; testshortpaths = true; // Default nodebuilder configurations @@ -437,6 +440,8 @@ sectortypes 144 = "Egg Capsule"; 160 = "Special Stage Time/Spheres Parameters "; 176 = "Custom Global Gravity "; + 512 = "Wind/Current "; + 1024 = "Conveyor Belt "; 1280 = "Speed Pad"; 1536 = "Flip Gravity on Jump"; 4096 = "Star Post Activator"; @@ -496,6 +501,8 @@ gen_sectortypes third { 0 = "Normal"; + 512 = "Wind/Current "; + 1024 = "Conveyor Belt "; 1280 = "Speed Pad"; 1536 = "Flip Gravity on Jump"; } @@ -578,7 +585,7 @@ linedeftypes title = "Per-Sector Gravity"; prefix = "(1)"; flags64text = "[6] Flip in reverse gravity"; - flags8192text = "[13] Reverse while inside"; + flags8192text = "[13] Cancel MF2_OBJECTFLIP"; } 5 @@ -641,35 +648,35 @@ linedeftypes 96 { - title = "Apply Tag to Tagged Sectors"; + title = "Add Front Sector Tag to Tagged Sectors"; prefix = "(96)"; flags1024text = "[10] Offsets are target tags"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 97 { - title = "Apply Tag to Front Sector"; + title = "Add Tag to Front Sector"; prefix = "(97)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 98 { - title = "Apply Tag to Back Sector"; + title = "Add Tag to Back Sector"; prefix = "(98)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 99 { - title = "Apply Tag to Front and Back Sectors"; + title = "Add Tag to Front and Back Sectors"; prefix = "(99)"; - flags8192text = "[13] Use front side offsets"; - flags32768text = "[15] Use back side offsets"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; } 540 @@ -990,6 +997,7 @@ linedeftypes flags128text = "[7] Only block non-players"; 3dfloor = true; 3dfloorflags = "47"; + invisiblefof = true; } 140 @@ -1227,6 +1235,7 @@ linedeftypes prefix = "(223)"; 3dfloor = true; 3dfloorflags = "41"; + invisiblefof = true; } } @@ -1524,6 +1533,7 @@ linedeftypes prefix = "(200)"; 3dfloor = true; 3dfloorflags = "20201"; + invisiblefof = true; } 201 @@ -1532,6 +1542,7 @@ linedeftypes prefix = "(201)"; 3dfloor = true; 3dfloorflags = "201"; + invisiblefof = true; } 202 @@ -1539,7 +1550,8 @@ linedeftypes title = "Fog Block"; prefix = "(202)"; 3dfloor = true; - 3dfloorflags = "3EF19"; + 3dfloorflags = "3EF01"; + invisiblefof = true; } 250 @@ -3624,7 +3636,7 @@ thingtypes 3328 = "3D Mode Start"; } - + starts { color = 1; // Blue @@ -3814,7 +3826,7 @@ thingtypes enemies { - color = 9; // Light_Blue + color = 9; // Light Blue arrow = 1; title = "Enemies"; @@ -4124,7 +4136,7 @@ thingtypes bosses { - color = 8; // Dark_Gray + color = 4; // Dark Red arrow = 1; title = "Bosses"; @@ -4223,6 +4235,7 @@ thingtypes sprite = "internal:capsule"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 292 { @@ -4310,13 +4323,13 @@ thingtypes 308 { title = "CTF Team Ring (Red)"; - sprite = "internal:TRNGA0r"; + sprite = "internal:TRNGA0R"; width = 16; } 309 { title = "CTF Team Ring (Blue)"; - sprite = "internal:TRNGA0b"; + sprite = "internal:TRNGA0B"; width = 16; } 330 @@ -4353,7 +4366,7 @@ thingtypes collectibles { - color = 10; // Light_Green + color = 10; // Light Green title = "Other Collectibles"; width = 16; height = 32; @@ -4457,6 +4470,7 @@ thingtypes flags8text = "[8] Random (Weak)"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; 400 { @@ -4589,6 +4603,7 @@ thingtypes flags1text = "[1] Run linedef executor on pop"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; 431 { @@ -4659,7 +4674,7 @@ thingtypes generic { - color = 11; // Light_Cyan + color = 11; // Light Cyan title = "Generic Items & Hazards"; 500 @@ -4765,7 +4780,7 @@ thingtypes springs { - color = 12; // Light_Red + color = 12; // Light Red title = "Springs and Fans"; width = 20; height = 16; @@ -4927,13 +4942,13 @@ thingtypes { arrow = 0; title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalyellow"; } 601 { arrow = 0; title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalred"; height = 1024; } 602 @@ -4951,7 +4966,7 @@ thingtypes 604 { title = "Circle of Rings"; - sprite = "RINGA0"; + sprite = "internal:circlering"; width = 96; height = 192; unflippable = true; @@ -4960,7 +4975,7 @@ thingtypes 605 { title = "Circle of Rings (Big)"; - sprite = "RINGA0"; + sprite = "internal:circlebigring"; width = 192; unflippable = true; centerHitbox = true; @@ -4968,7 +4983,7 @@ thingtypes 606 { title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circlesphere"; width = 96; height = 192; unflippable = true; @@ -4977,7 +4992,7 @@ thingtypes 607 { title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigsphere"; width = 192; unflippable = true; centerHitbox = true; @@ -4985,7 +5000,7 @@ thingtypes 608 { title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circleringsphere"; width = 96; height = 192; unflippable = true; @@ -4994,13 +5009,77 @@ thingtypes 609 { title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigringsphere"; width = 192; unflippable = true; centerHitbox = true; } } + ambience + { + color = 8; // Dark Gray + title = "Ambience"; + width = 8; + height = 16; + sprite = "internal:ambiance"; + + 700 + { + title = "Water Ambience A (Large)"; + } + + 701 + { + title = "Water Ambience B (Large)"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + } + + 704 + { + title = "Water Ambience E (Small)"; + } + + 705 + { + title = "Water Ambience F (Small)"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + } + + 708 + { + title = "Disco Ambience"; + } + + 709 + { + title = "Volcano Ambience"; + } + + 710 + { + title = "Machine Ambience"; + } + } + invisible { color = 15; // White @@ -5009,72 +5088,6 @@ thingtypes height = 16; sprite = "UNKNA0"; - 700 - { - title = "Water Ambience A (Large)"; - sprite = "internal:ambiance"; - } - - 701 - { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; - } - - 702 - { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; - } - - 703 - { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; - } - - 704 - { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; - } - - 705 - { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; - } - - 706 - { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; - } - - 707 - { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; - } - - 708 - { - title = "Disco Ambience"; - sprite = "internal:ambiance"; - } - - 709 - { - title = "Volcano Ambience"; - sprite = "internal:ambiance"; - } - - 710 - { - title = "Machine Ambience"; - sprite = "internal:ambiance"; - } - 750 { title = "Slope Vertex"; @@ -5083,6 +5096,7 @@ thingtypes fixedrotation = 1; parametertext = "Absolute?"; flagsvaluetext = "Absolute Z"; + tagthing = true; } 751 @@ -5128,20 +5142,22 @@ thingtypes 756 { title = "Blast Linedef Executor"; - sprite = "TOADA0"; + sprite = "internal:blastexec"; width = 32; height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 757 { title = "Fan Particle Generator"; - sprite = "PRTLA0"; + sprite = "internal:fanparticles"; width = 8; height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 758 { @@ -5154,6 +5170,8 @@ thingtypes sprite = "internal:polyanchor"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 761 @@ -5162,6 +5180,8 @@ thingtypes sprite = "internal:polycenter"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 762 @@ -5170,6 +5190,8 @@ thingtypes sprite = "internal:polycentercrush"; angletext = "Tag"; fixedrotation = 1; + tagthing = true; + unflippable = true; } 780 { @@ -5183,7 +5205,7 @@ thingtypes greenflower { - color = 10; // Green + color = 2; // Green title = "Greenflower"; 800 @@ -5288,7 +5310,7 @@ thingtypes technohill { - color = 10; // Green + color = 2; // Green title = "Techno Hill"; 900 @@ -5332,7 +5354,7 @@ thingtypes deepsea { - color = 10; // Green + color = 2; // Green title = "Deep Sea"; 1000 @@ -5467,7 +5489,7 @@ thingtypes castleeggman { - color = 10; // Green + color = 2; // Green title = "Castle Eggman"; 1100 @@ -5516,6 +5538,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1105 { @@ -5528,6 +5551,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1106 { @@ -5540,23 +5564,25 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1107 { title = "Chain Spawnpoint"; - sprite = "BMCHA0"; + sprite = "BMCHB0"; width = 17; height = 34; flags8text = "[8] Double size"; angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1108 { arrow = 1; title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; + sprite = "SMCHA0"; width = 17; height = 34; flags8text = "[8] Double size"; @@ -5572,6 +5598,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1110 { @@ -5583,6 +5610,7 @@ thingtypes angletext = "Tag"; parametertext = "Spokes"; fixedrotation = 1; + tagthing = true; } 1111 { @@ -5736,7 +5764,7 @@ thingtypes aridcanyon { - color = 10; // Green + color = 2; // Green title = "Arid Canyon"; 1200 @@ -5764,6 +5792,7 @@ thingtypes height = 16; angletext = "Tag"; fixedrotation = 1; + tagthing = true; } 1203 { @@ -5955,7 +5984,7 @@ thingtypes redvolcano { - color = 10; // Green + color = 2; // Green title = "Red Volcano"; 1300 @@ -6055,7 +6084,7 @@ thingtypes botanicserenity { - color = 10; // Green + color = 2; // Green title = "Botanic Serenity"; width = 16; height = 32; @@ -6298,7 +6327,7 @@ thingtypes azuretemple { - color = 10; // Green + color = 2; // Green title = "Azure Temple"; 1500 @@ -6374,7 +6403,7 @@ thingtypes dreamhill { - color = 10; // Green + color = 2; // Green title = "Dream Hill"; 1600 @@ -6402,8 +6431,8 @@ thingtypes nightstrk { - color = 13; // Pink - title = "NiGHTS Track"; + color = 16; // Light Pink + title = "NiGHTS Track & Basics"; width = 8; height = 4096; sprite = "UNKNA0"; @@ -6438,6 +6467,19 @@ thingtypes flagsvaluetext = "Order"; parametertext = "Mare"; } + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags1text = "[1] Align player to middle"; + flags4text = "[4] Align player to top"; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + fixedrotation = 1; + parametertext = "Height"; + } 1710 { title = "Ideya Capture"; @@ -6455,20 +6497,6 @@ thingtypes title = "NiGHTS Items"; width = 16; height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - flags1text = "[1] Align player to middle"; - flags4text = "[4] Align player to top"; - flags8text = "[8] Die upon time up"; - angletext = "Time limit"; - fixedrotation = 1; - parametertext = "Height"; - } 1704 { arrow = 1; @@ -6479,13 +6507,12 @@ thingtypes unflippable = true; flagsvaluetext = "Pitch"; angletext = "Yaw"; - fixedrotation = 1; } 1705 { arrow = 1; title = "Hoop (Generic)"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; unflippable = true; @@ -6502,7 +6529,6 @@ thingtypes height = 24; flags8height = 24; flags8text = "[8] Float"; - unflippable = true; } 1707 { @@ -6547,7 +6573,7 @@ thingtypes flags2text = "[2] Radius +32"; flags4text = "[4] Radius +64"; flags8text = "[8] Radius +128"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; unflippable = true; @@ -6657,7 +6683,7 @@ thingtypes christmasdisco { - color = 10; // Green + color = 2; // Green title = "Christmas & Disco"; 1850 @@ -6760,7 +6786,7 @@ thingtypes stalagmites { - color = 10; // Green + color = 2; // Green title = "Stalagmites"; width = 16; height = 40; @@ -6839,7 +6865,7 @@ thingtypes hauntedheights { - color = 10; // Green + color = 2; // Green title = "Haunted Heights"; 2000 @@ -6928,7 +6954,7 @@ thingtypes frozenhillside { - color = 10; // Green + color = 2; // Green title = "Frozen Hillside"; 2100 @@ -6979,7 +7005,7 @@ thingtypes tutorial { - color = 10; // Green + color = 2; // Green title = "Tutorial"; 799 @@ -6990,10 +7016,11 @@ thingtypes height = 144; parametertext = "Start frame"; } + } flickies { - color = 10; // Green + color = 3; // Teal title = "Flickies"; width = 8; height = 20; From b2313aa4bda91da0bf4575c67bb5eeac4647f0c7 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Mon, 22 May 2023 17:55:04 +0200 Subject: [PATCH 120/478] Rewrite F_SkyScroll to fix overflows --- src/d_clisrv.c | 2 +- src/f_finale.c | 73 +++++++++++++++++++++----------------------------- src/f_finale.h | 4 +-- src/g_game.c | 6 +++-- src/m_menu.c | 6 ++--- 5 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 94384e46a..839f70f7e 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2486,7 +2486,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic { if (!snake) { - F_MenuPresTicker(true); // title sky + F_MenuPresTicker(); // title sky F_TitleScreenTicker(true); F_TitleScreenDrawer(); } diff --git a/src/f_finale.c b/src/f_finale.c index 6560c24f1..47d4627ec 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -63,7 +63,6 @@ static tic_t stoptimer; static boolean keypressed = false; // (no longer) De-Demo'd Title Screen -static INT32 menuanimtimer; // Title screen: background animation timing mobj_t *titlemapcameraref = NULL; // menu presentation state @@ -75,6 +74,8 @@ INT32 curbgyspeed; boolean curbghide; boolean hidetitlemap; // WARNING: set to false by M_SetupNextMenu and M_ClearMenus +static fixed_t curbgx = 0; +static fixed_t curbgy = 0; static UINT8 curDemo = 0; static UINT32 demoDelayLeft; static UINT32 demoIdleLeft; @@ -2258,7 +2259,8 @@ void F_GameEndTicker(void) void F_InitMenuPresValues(void) { - menuanimtimer = 0; + curbgx = 0; + curbgy = 0; prevMenuId = 0; activeMenuId = MainDef.menuid; @@ -2291,17 +2293,11 @@ void F_InitMenuPresValues(void) // // F_SkyScroll // -void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname) +void F_SkyScroll(const char *patchname) { - INT32 xscrolled, x, xneg = (scrollxspeed > 0) - (scrollxspeed < 0), tilex; - INT32 yscrolled, y, yneg = (scrollyspeed > 0) - (scrollyspeed < 0), tiley; - boolean xispos = (scrollxspeed >= 0), yispos = (scrollyspeed >= 0); + INT32 x, basey = 0; INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - INT16 patwidth, patheight; - INT32 pw, ph; // scaled by dupz patch_t *pat; - INT32 i, j; - fixed_t fracmenuanimtimer, xscrolltimer, yscrolltimer; if (rendermode == render_none) return; @@ -2312,43 +2308,34 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname) return; } - if (!scrollxspeed && !scrollyspeed) + pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY); + + if (!curbgxspeed && !curbgyspeed) { - V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY)); + V_DrawPatchFill(pat); + W_UnlockCachedPatch(pat); return; } - pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY); + // Modulo the background scrolling to prevent jumps from integer overflows + // We already load the background patch here, so we can modulo it here + // to avoid also having to load the patch in F_MenuPresTicker + curbgx %= pat->width * 16; + curbgy %= pat->height * 16; - patwidth = pat->width; - patheight = pat->height; - pw = patwidth * dupz; - ph = patheight * dupz; + // Ooh, fancy frame interpolation + x = ((curbgx*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*dupz)) / 16; + basey = ((curbgy*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*dupz)) / 16; - tilex = max(FixedCeil(FixedDiv(vid.width, pw)) >> FRACBITS, 1)+2; // one tile on both sides of center - tiley = max(FixedCeil(FixedDiv(vid.height, ph)) >> FRACBITS, 1)+2; + if (x > 0) // Make sure that we don't leave the left or top sides empty + x -= pat->width * dupz; + if (basey > 0) + basey -= pat->height * dupz; - fracmenuanimtimer = (menuanimtimer * FRACUNIT) - (FRACUNIT - rendertimefrac); - xscrolltimer = ((fracmenuanimtimer*scrollxspeed)/16 + patwidth*xneg*FRACUNIT) % (patwidth * FRACUNIT); - yscrolltimer = ((fracmenuanimtimer*scrollyspeed)/16 + patheight*yneg*FRACUNIT) % (patheight * FRACUNIT); - - // coordinate offsets - xscrolled = FixedInt(xscrolltimer * dupz); - yscrolled = FixedInt(yscrolltimer * dupz); - - for (x = (xispos) ? -pw*(tilex-1)+pw : 0, i = 0; - i < tilex; - x += pw, i++) + for (; x < vid.width; x += pat->width * dupz) { - for (y = (yispos) ? -ph*(tiley-1)+ph : 0, j = 0; - j < tiley; - y += ph, j++) - { - V_DrawScaledPatch( - (xispos) ? xscrolled - x : x + xscrolled, - (yispos) ? yscrolled - y : y + yscrolled, - V_NOSCALESTART, pat); - } + for (INT32 y = basey; y < vid.height; y += pat->height * dupz) + V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); } W_UnlockCachedPatch(pat); @@ -2671,7 +2658,7 @@ void F_TitleScreenDrawer(void) if (curbgcolor >= 0) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS) - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); // Don't draw outside of the title screen, or if the patch isn't there. if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS) @@ -3426,10 +3413,10 @@ luahook: // separate animation timer for backgrounds, since we also count // during GS_TIMEATTACK -void F_MenuPresTicker(boolean run) +void F_MenuPresTicker(void) { - if (run) - menuanimtimer++; + curbgx += curbgxspeed; + curbgy += curbgyspeed; } // (no longer) De-Demo'd Title Screen diff --git a/src/f_finale.h b/src/f_finale.h index 6ea1b5537..7f53bfbad 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -40,7 +40,7 @@ void F_TextPromptTicker(void); void F_GameEndDrawer(void); void F_IntroDrawer(void); void F_TitleScreenDrawer(void); -void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname); +void F_SkyScroll(const char *patchname); void F_GameEvaluationDrawer(void); void F_StartGameEvaluation(void); @@ -131,7 +131,7 @@ extern UINT16 curtttics; #define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0]) void F_InitMenuPresValues(void); -void F_MenuPresTicker(boolean run); +void F_MenuPresTicker(void); // // WIPE diff --git a/src/g_game.c b/src/g_game.c index 0d5181b07..2935daa55 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2390,7 +2390,8 @@ void G_Ticker(boolean run) break; case GS_TIMEATTACK: - F_MenuPresTicker(run); + if (run) + F_MenuPresTicker(); break; case GS_INTRO: @@ -2438,7 +2439,8 @@ void G_Ticker(boolean run) // then intentionally fall through /* FALLTHRU */ case GS_WAITINGPLAYERS: - F_MenuPresTicker(run); + if (run) + F_MenuPresTicker(); F_TitleScreenTicker(run); break; diff --git a/src/m_menu.c b/src/m_menu.c index e879e9c14..7efe81f43 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5964,7 +5964,7 @@ static void M_DrawLevelPlatterMenu(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) { - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); // Draw and animate foreground if (!strncmp("RECATKBG", curbgname, 8)) M_DrawRecordAttackForeground(); @@ -6226,7 +6226,7 @@ static void M_DrawMessageMenu(void) } else { - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); if (!strncmp("RECATKBG", curbgname, 8)) M_DrawRecordAttackForeground(); } @@ -9873,7 +9873,7 @@ void M_DrawTimeAttackMenu(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); else if (!curbghide || !titlemapinaction) { - F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + F_SkyScroll(curbgname); // Draw and animate foreground if (!strncmp("RECATKBG", curbgname, 8)) M_DrawRecordAttackForeground(); From 3f5e7ff0d06b2a0aa7fdb1c42e9ebdc34b13129c Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Mon, 22 May 2023 20:53:17 +0200 Subject: [PATCH 121/478] Interpolate shadows when scaling mobjs --- src/hardware/hw_main.c | 2 ++ src/r_things.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 343fa43bf..6e7214571 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3606,6 +3606,8 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) scalemul = FixedMul(FRACUNIT - floordiff/640, scale); scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height); + if ((thing->scale != thing->old_scale) && (thing->scale >= FRACUNIT/1024)) // Interpolate shadows when scaling mobjs + scalemul = FixedMul(scalemul, FixedDiv(interp.scale, thing->scale)); fscale = FIXED_TO_FLOAT(scalemul); fx = FIXED_TO_FLOAT(interp.x); diff --git a/src/r_things.c b/src/r_things.c index 2916482fb..62d97ff33 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1324,6 +1324,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, if (trans >= 9) return; scalemul = FixedMul(FRACUNIT - floordiff/640, scale); + if ((thing->scale != thing->old_scale) && (thing->scale >= FRACUNIT/1024)) // Interpolate shadows when scaling mobjs + scalemul = FixedMul(scalemul, FixedDiv(interp.scale, thing->scale)); patch = W_CachePatchName("DSHADOW", PU_SPRITE); xscale = FixedDiv(projection, tz); From 05f1a9a2c8a0da9ed4ab00a0abac3d439b3ec08c Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Mon, 29 May 2023 14:38:22 +0200 Subject: [PATCH 122/478] Suppress libdivide warnings in GCC/Clang --- src/libdivide.h | 9 +++++++++ src/r_draw8_npo2.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/libdivide.h b/src/libdivide.h index 1a589c7e5..71a5ae6be 100644 --- a/src/libdivide.h +++ b/src/libdivide.h @@ -581,6 +581,11 @@ static inline void libdivide_u128_shift(uint64_t *u1, uint64_t *u0, int32_t sign ////////// UINT32 +#if defined(__GNUC__) || defined(__clang__) // Suppress intentional compiler warnings + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Waggregate-return" +#endif + static inline struct libdivide_u32_t libdivide_internal_u32_gen(uint32_t d, int branchfree) { struct libdivide_u32_t result; uint32_t floor_log_2_d; @@ -647,6 +652,10 @@ struct libdivide_u32_t libdivide_u32_gen(uint32_t d) { return ret; }*/ +#if defined(__GNUC__) || defined(__clang__) // Stop suppressing intentional compiler warnings + #pragma GCC diagnostic pop +#endif + uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom) { uint8_t more = denom->more; if (!denom->magic) { diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index faf1cdba8..91f3b06c4 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -18,6 +18,11 @@ #define SPANSIZE 16 #define INVSPAN 0.0625f +#if defined(__GNUC__) || defined(__clang__) // Suppress intentional libdivide compiler warnings - Also added to libdivide.h + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Waggregate-return" +#endif + /** \brief The R_DrawSpan_NPO2_8 function Draws the actual span. */ @@ -1572,3 +1577,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void) } #endif } + +#if defined(__GNUC__) || defined(__clang__) // Stop suppressing intentional libdivide compiler warnings + #pragma GCC diagnostic pop +#endif From 58b3b8e0750effcc1da5149305c8781003289366 Mon Sep 17 00:00:00 2001 From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com> Date: Wed, 31 May 2023 22:33:16 -0500 Subject: [PATCH 123/478] Fix Flung Spheres not using the Blue Sphere collection effect --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 873448dcd..86fc2a6ae 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -563,7 +563,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->momx = special->momy = special->momz = 0; P_GivePlayerSpheres(player, 1); - if (special->type == MT_BLUESPHERE) + if (special->type == MT_BLUESPHERE || special->type == MT_FLINGBLUESPHERE) { special->destscale = ((player->powers[pw_carry] == CR_NIGHTSMODE) ? 4 : 2)*special->scale; if (states[special->info->deathstate].tics > 0) From 49fa46d80efd95047f05834bde41dbbd7311d418 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 27 Feb 2022 16:52:05 -0500 Subject: [PATCH 124/478] Online emblems Currently, emblems share with everyone. Will add an option to toggle this. --- src/d_clisrv.c | 3 + src/d_main.c | 9 +- src/d_netcmd.c | 14 +-- src/deh_soc.c | 2 +- src/dehacked.c | 2 +- src/doomstat.h | 54 ---------- src/f_finale.c | 43 ++++---- src/g_game.c | 251 ++++++++++++++++++++++----------------------- src/g_game.h | 25 ++--- src/hu_stuff.c | 2 +- src/m_cheat.c | 4 +- src/m_cond.c | 248 +++++++++++++++++++++++++++++--------------- src/m_cond.h | 123 ++++++++++++++++++---- src/m_menu.c | 155 +++++++++++++++------------- src/m_random.c | 5 +- src/p_inter.c | 18 +++- src/p_mobj.c | 19 ++-- src/p_saveg.c | 225 ++++++++++++++++++++++++++++++++++++++++ src/p_setup.c | 11 +- src/p_spec.c | 7 +- src/p_tick.c | 5 +- src/r_skins.c | 13 +-- src/s_sound.c | 5 +- src/sdl/i_system.c | 6 +- src/st_stuff.c | 9 +- src/y_inter.c | 16 +-- 26 files changed, 824 insertions(+), 450 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 64e5aff6b..18f0179f8 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3645,6 +3645,9 @@ void SV_ResetServer(void) CV_RevertNetVars(); + // Ensure synched when creating a new server + M_CopyGameData(serverGamedata, clientGamedata); + DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } diff --git a/src/d_main.c b/src/d_main.c index 6506c9d4e..5861f9886 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1350,6 +1350,9 @@ void D_SRB2Main(void) CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n"); Z_Init(); + clientGamedata = M_NewGameDataStruct(); + serverGamedata = M_NewGameDataStruct(); + // Do this up here so that WADs loaded through the command line can use ExecCfg COM_Init(); @@ -1479,7 +1482,9 @@ void D_SRB2Main(void) // confusion issues when loading mods. strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename); } - G_LoadGameData(); + + G_LoadGameData(clientGamedata); + M_CopyGameData(serverGamedata, clientGamedata); #if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen @@ -1710,7 +1715,7 @@ void D_SRB2Main(void) // ... unless you're in a dedicated server. Yes, technically this means you can view any level by // running a dedicated server and joining it yourself, but that's better than making dedicated server's // lives hell. - else if (!dedicated && M_MapLocked(pstartmap)) + else if (!dedicated && M_MapLocked(pstartmap, serverGamedata)) I_Error("You need to unlock this level before you can warp to it!\n"); else { diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 80a084e16..af44e53d6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2036,7 +2036,7 @@ static void Command_Map_f(void) // ... unless you're in a dedicated server. Yes, technically this means you can view any level by // running a dedicated server and joining it yourself, but that's better than making dedicated server's // lives hell. - if (!dedicated && M_MapLocked(newmapnum)) + if (!dedicated && M_MapLocked(newmapnum, serverGamedata)) { CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n")); Z_Free(realmapname); @@ -3945,18 +3945,12 @@ void ItemFinder_OnChange(void) if (!cv_itemfinder.value) return; // it's fine. - if (!M_SecretUnlocked(SECRET_ITEMFINDER)) + if (!M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_itemfinder, 0); return; } - else if (netgame || multiplayer) - { - CONS_Printf(M_GetText("This only works in single player.\n")); - CV_StealthSetValue(&cv_itemfinder, 0); - return; - } } /** Deals with a pointlimit change by printing the change to the console. @@ -4305,7 +4299,7 @@ void D_GameTypeChanged(INT32 lastgametype) static void Ringslinger_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && cv_ringslinger.value && !cv_debug) + if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && cv_ringslinger.value && !cv_debug) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); CV_StealthSetValue(&cv_ringslinger, 0); @@ -4318,7 +4312,7 @@ static void Ringslinger_OnChange(void) static void Gravity_OnChange(void) { - if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && !cv_debug + if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && !cv_debug && strcmp(cv_gravity.string, cv_gravity.defaultvalue)) { CONS_Printf(M_GetText("You haven't earned this yet.\n")); diff --git a/src/deh_soc.c b/src/deh_soc.c index 3a3942c14..81adbc9d2 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3849,7 +3849,7 @@ void readmaincfg(MYFILE *f) if (!GoodDataFileName(word2)) I_Error("Maincfg: bad data file name '%s'\n", word2); - G_SaveGameData(); + G_SaveGameData(clientGamedata); strlcpy(gamedatafilename, word2, sizeof (gamedatafilename)); strlwr(gamedatafilename); savemoddata = true; diff --git a/src/dehacked.c b/src/dehacked.c index 17768eb7f..fd2a70171 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -575,7 +575,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) } // end while if (gamedataadded) - G_LoadGameData(); + G_LoadGameData(clientGamedata); if (gamestate == GS_TITLESCREEN) { diff --git a/src/doomstat.h b/src/doomstat.h index 847c10b8c..5875bd01f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -132,8 +132,6 @@ extern INT32 postimgparam2; extern INT32 viewwindowx, viewwindowy; extern INT32 viewwidth, scaledviewwidth; -extern boolean gamedataloaded; - // Player taking events, and displaying. extern INT32 consoleplayer; extern INT32 displayplayer; @@ -495,8 +493,6 @@ typedef struct extern tolinfo_t TYPEOFLEVEL[NUMTOLNAMES]; extern UINT32 lastcustomtol; -extern tic_t totalplaytime; - extern boolean stagefailed; // Emeralds stored as bits to throw savegame hackers off. @@ -515,52 +511,6 @@ extern INT32 luabanks[NUM_LUABANKS]; extern INT32 nummaprings; //keep track of spawned rings/coins -/** Time attack information, currently a very small structure. - */ -typedef struct -{ - tic_t time; ///< Time in which the level was finished. - UINT32 score; ///< Score when the level was finished. - UINT16 rings; ///< Rings when the level was finished. -} recorddata_t; - -/** Setup for one NiGHTS map. - * These are dynamically allocated because I am insane - */ -#define GRADE_F 0 -#define GRADE_E 1 -#define GRADE_D 2 -#define GRADE_C 3 -#define GRADE_B 4 -#define GRADE_A 5 -#define GRADE_S 6 - -typedef struct -{ - // 8 mares, 1 overall (0) - UINT8 nummares; - UINT32 score[9]; - UINT8 grade[9]; - tic_t time[9]; -} nightsdata_t; - -extern nightsdata_t *nightsrecords[NUMMAPS]; -extern recorddata_t *mainrecords[NUMMAPS]; - -// mapvisited is now a set of flags that says what we've done in the map. -#define MV_VISITED 1 -#define MV_BEATEN 2 -#define MV_ALLEMERALDS 4 -#define MV_ULTIMATE 8 -#define MV_PERFECT 16 -#define MV_PERFECTRA 32 -#define MV_MAX 63 // used in gamedata check, update whenever MV's are added -#define MV_MP 128 -extern UINT8 mapvisited[NUMMAPS]; - -// Temporary holding place for nights data for the current map -extern nightsdata_t ntemprecords; - extern UINT32 token; ///< Number of tokens collected in a level extern UINT32 tokenlist; ///< List of tokens collected extern boolean gottoken; ///< Did you get a token? Used for end of act @@ -616,10 +566,6 @@ extern INT32 cheats; extern tic_t hidetime; -extern UINT32 timesBeaten; // # of times the game has been beaten. -extern UINT32 timesBeatenWithEmeralds; -extern UINT32 timesBeatenUltimate; - // =========================== // Internal parameters, fixed. // =========================== diff --git a/src/f_finale.c b/src/f_finale.c index 68b2641a1..4bb640d50 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1411,7 +1411,7 @@ boolean F_CreditResponder(event_t *event) break; } - if (!(timesBeaten) && !(netgame || multiplayer) && !cv_debug) + if (!(serverGamedata->timesBeaten) && !(netgame || multiplayer) && !cv_debug) return false; if (event->type != ev_keydown) @@ -1573,23 +1573,17 @@ void F_GameEvaluationDrawer(void) #if 0 // the following looks like hot garbage the more unlockables we add, and we now have a lot of unlockables if (finalecount >= 5*TICRATE) { + INT32 startcoord = 32; V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); - if (netgame) - V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!"); - else + for (i = 0; i < MAXUNLOCKABLES; i++) { - INT32 startcoord = 32; - - for (i = 0; i < MAXUNLOCKABLES; i++) + if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS + && unlockables[i].type && !unlockables[i].nocecho) { - if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS - && unlockables[i].type && !unlockables[i].nocecho) - { - if (unlockables[i].unlocked) - V_DrawString(8, startcoord, 0, unlockables[i].name); - startcoord += 8; - } + if (clientGamedata->unlocked[i]) + V_DrawString(8, startcoord, 0, unlockables[i].name); + startcoord += 8; } } } @@ -1657,18 +1651,27 @@ void F_GameEvaluationTicker(void) } else { - ++timesBeaten; + serverGamedata->timesBeaten++; + clientGamedata->timesBeaten++; if (ALL7EMERALDS(emeralds)) - ++timesBeatenWithEmeralds; + { + serverGamedata->timesBeatenWithEmeralds++; + clientGamedata->timesBeatenWithEmeralds++; + } if (ultimatemode) - ++timesBeatenUltimate; + { + serverGamedata->timesBeatenUltimate++; + clientGamedata->timesBeatenUltimate++; + } - if (M_UpdateUnlockablesAndExtraEmblems()) + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); + G_SaveGameData(clientGamedata); } } } @@ -2183,7 +2186,7 @@ void F_EndingDrawer(void) //colset(linkmap, 164, 165, 169); -- the ideal purple colour to represent a clicked in-game link, but not worth it just for a soundtest-controlled secret V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<'|(trans<= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); + V_DrawString(40, ((finalecount == STOPPINGPOINT-(20+TICRATE)) ? 1 : 0)+BASEVIDHEIGHT-16, ((serverGamedata->timesBeaten || finalecount >= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); } if (finalecount > STOPPINGPOINT-(20+(2*TICRATE))) diff --git a/src/g_game.c b/src/g_game.c index 7386b2a84..854bf9bbb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -185,18 +185,6 @@ INT32 tokenbits; // Used for setting token bits // Old Special Stage INT32 sstimer; // Time allotted in the special stage -tic_t totalplaytime; -boolean gamedataloaded = false; - -// Time attack data for levels -// These are dynamically allocated for space reasons now -recorddata_t *mainrecords[NUMMAPS] = {NULL}; -nightsdata_t *nightsrecords[NUMMAPS] = {NULL}; -UINT8 mapvisited[NUMMAPS]; - -// Temporary holding place for nights data for the current map -nightsdata_t ntemprecords; - UINT32 bluescore, redscore; // CTF and Team Match team scores // ring count... for PERFECT! @@ -252,11 +240,6 @@ INT32 cheats; //for multiplayer cheat commands tic_t hidetime; -// Grading -UINT32 timesBeaten; -UINT32 timesBeatenWithEmeralds; -UINT32 timesBeatenUltimate; - typedef struct joystickvector2_s { INT32 xaxis; @@ -452,86 +435,86 @@ INT16 rw_maximums[NUM_WEAPONS] = }; // Allocation for time and nights data -void G_AllocMainRecordData(INT16 i) +void G_AllocMainRecordData(INT16 i, gamedata_t *data) { - if (!mainrecords[i]) - mainrecords[i] = Z_Malloc(sizeof(recorddata_t), PU_STATIC, NULL); - memset(mainrecords[i], 0, sizeof(recorddata_t)); + if (!data->mainrecords[i]) + data->mainrecords[i] = Z_Malloc(sizeof(recorddata_t), PU_STATIC, NULL); + memset(data->mainrecords[i], 0, sizeof(recorddata_t)); } -void G_AllocNightsRecordData(INT16 i) +void G_AllocNightsRecordData(INT16 i, gamedata_t *data) { - if (!nightsrecords[i]) - nightsrecords[i] = Z_Malloc(sizeof(nightsdata_t), PU_STATIC, NULL); - memset(nightsrecords[i], 0, sizeof(nightsdata_t)); + if (!data->nightsrecords[i]) + data->nightsrecords[i] = Z_Malloc(sizeof(nightsdata_t), PU_STATIC, NULL); + memset(data->nightsrecords[i], 0, sizeof(nightsdata_t)); } // MAKE SURE YOU SAVE DATA BEFORE CALLING THIS -void G_ClearRecords(void) +void G_ClearRecords(gamedata_t *data) { INT16 i; for (i = 0; i < NUMMAPS; ++i) { - if (mainrecords[i]) + if (data->mainrecords[i]) { - Z_Free(mainrecords[i]); - mainrecords[i] = NULL; + Z_Free(data->mainrecords[i]); + data->mainrecords[i] = NULL; } - if (nightsrecords[i]) + if (data->nightsrecords[i]) { - Z_Free(nightsrecords[i]); - nightsrecords[i] = NULL; + Z_Free(data->nightsrecords[i]); + data->nightsrecords[i] = NULL; } } } // For easy retrieval of records -UINT32 G_GetBestScore(INT16 map) +UINT32 G_GetBestScore(INT16 map, gamedata_t *data) { - if (!mainrecords[map-1]) + if (!data->mainrecords[map-1]) return 0; - return mainrecords[map-1]->score; + return data->mainrecords[map-1]->score; } -tic_t G_GetBestTime(INT16 map) +tic_t G_GetBestTime(INT16 map, gamedata_t *data) { - if (!mainrecords[map-1] || mainrecords[map-1]->time <= 0) + if (!data->mainrecords[map-1] || data->mainrecords[map-1]->time <= 0) return (tic_t)UINT32_MAX; - return mainrecords[map-1]->time; + return data->mainrecords[map-1]->time; } -UINT16 G_GetBestRings(INT16 map) +UINT16 G_GetBestRings(INT16 map, gamedata_t *data) { - if (!mainrecords[map-1]) + if (!data->mainrecords[map-1]) return 0; - return mainrecords[map-1]->rings; + return data->mainrecords[map-1]->rings; } -UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare) +UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare, gamedata_t *data) { - if (!nightsrecords[map-1]) + if (!data->nightsrecords[map-1]) return 0; - return nightsrecords[map-1]->score[mare]; + return data->nightsrecords[map-1]->score[mare]; } -tic_t G_GetBestNightsTime(INT16 map, UINT8 mare) +tic_t G_GetBestNightsTime(INT16 map, UINT8 mare, gamedata_t *data) { - if (!nightsrecords[map-1] || nightsrecords[map-1]->time[mare] <= 0) + if (!data->nightsrecords[map-1] || data->nightsrecords[map-1]->time[mare] <= 0) return (tic_t)UINT32_MAX; - return nightsrecords[map-1]->time[mare]; + return data->nightsrecords[map-1]->time[mare]; } -UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare) +UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data) { - if (!nightsrecords[map-1]) + if (!data->nightsrecords[map-1]) return 0; - return nightsrecords[map-1]->grade[mare]; + return data->nightsrecords[map-1]->grade[mare]; } // For easy adding of NiGHTS records @@ -553,7 +536,7 @@ void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare) // Update replay files/data, etc. for Record Attack // See G_SetNightsRecords for NiGHTS Attack. // -static void G_UpdateRecordReplays(void) +static void G_UpdateRecordReplays(gamedata_t *data) { const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; char *gpath; @@ -561,17 +544,17 @@ static void G_UpdateRecordReplays(void) UINT8 earnedEmblems; // Record new best time - if (!mainrecords[gamemap-1]) - G_AllocMainRecordData(gamemap-1); + if (!data->mainrecords[gamemap-1]) + G_AllocMainRecordData(gamemap-1, data); - if (players[consoleplayer].score > mainrecords[gamemap-1]->score) - mainrecords[gamemap-1]->score = players[consoleplayer].score; + if (players[consoleplayer].score > data->mainrecords[gamemap-1]->score) + data->mainrecords[gamemap-1]->score = players[consoleplayer].score; - if ((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) - mainrecords[gamemap-1]->time = players[consoleplayer].realtime; + if ((data->mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < data->mainrecords[gamemap-1]->time)) + data->mainrecords[gamemap-1]->time = players[consoleplayer].realtime; - if ((UINT16)(players[consoleplayer].rings) > mainrecords[gamemap-1]->rings) - mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); + if ((UINT16)(players[consoleplayer].rings) > data->mainrecords[gamemap-1]->rings) + data->mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); // Save demo! bestdemo[255] = '\0'; @@ -627,14 +610,14 @@ static void G_UpdateRecordReplays(void) free(gpath); // Check emblems when level data is updated - if ((earnedEmblems = M_CheckLevelEmblems())) + if ((earnedEmblems = M_CheckLevelEmblems(data))) CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); // Update timeattack menu's replay availability. Nextmap_OnChange(); } -void G_SetNightsRecords(void) +void G_SetNightsRecords(gamedata_t *data) { INT32 i; UINT32 totalscore = 0; @@ -675,9 +658,9 @@ void G_SetNightsRecords(void) { nightsdata_t *maprecords; - if (!nightsrecords[gamemap-1]) - G_AllocNightsRecordData(gamemap-1); - maprecords = nightsrecords[gamemap-1]; + if (!data->nightsrecords[gamemap-1]) + G_AllocNightsRecordData(gamemap-1, data); + maprecords = data->nightsrecords[gamemap-1]; if (maprecords->nummares != ntemprecords.nummares) maprecords->nummares = ntemprecords.nummares; @@ -739,7 +722,7 @@ void G_SetNightsRecords(void) } free(gpath); - if ((earnedEmblems = M_CheckLevelEmblems())) + if ((earnedEmblems = M_CheckLevelEmblems(data))) CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for NiGHTS records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); // If the mare count changed, this will update the score display @@ -3838,7 +3821,7 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) for (ix = 0; ix < NUMMAPS; ix++) if (mapheaderinfo[ix] && (mapheaderinfo[ix]->typeoflevel & tolflags) == tolflags && ix != pprevmap // Don't pick the same map. - && (dedicated || !M_MapLocked(ix+1)) // Don't pick locked maps. + && (dedicated || !M_MapLocked(ix+1, serverGamedata)) // Don't pick locked maps. ) okmaps[numokmaps++] = ix; @@ -3855,7 +3838,7 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) // // G_UpdateVisited // -static void G_UpdateVisited(void) +static void G_UpdateVisited(gamedata_t *data, boolean silent) { boolean spec = G_IsSpecialStage(gamemap); // Update visitation flags? @@ -3865,30 +3848,37 @@ static void G_UpdateVisited(void) UINT8 earnedEmblems; // Update visitation flags - mapvisited[gamemap-1] |= MV_BEATEN; + data->mapvisited[gamemap-1] |= MV_BEATEN; // eh, what the hell if (ultimatemode) - mapvisited[gamemap-1] |= MV_ULTIMATE; + data->mapvisited[gamemap-1] |= MV_ULTIMATE; // may seem incorrect but IS possible in what the main game uses as mp special stages, and nummaprings will be -1 in NiGHTS if (nummaprings > 0 && players[consoleplayer].rings >= nummaprings) { - mapvisited[gamemap-1] |= MV_PERFECT; + data->mapvisited[gamemap-1] |= MV_PERFECT; if (modeattacking) - mapvisited[gamemap-1] |= MV_PERFECTRA; + data->mapvisited[gamemap-1] |= MV_PERFECTRA; } if (!spec) { // not available to special stages because they can only really be done in one order in an unmodified game, so impossible for first six and trivial for seventh if (ALL7EMERALDS(emeralds)) - mapvisited[gamemap-1] |= MV_ALLEMERALDS; + data->mapvisited[gamemap-1] |= MV_ALLEMERALDS; } - if (modeattacking == ATTACKING_RECORD) - G_UpdateRecordReplays(); - else if (modeattacking == ATTACKING_NIGHTS) - G_SetNightsRecords(); + if (silent) + { + M_CheckLevelEmblems(data); + } + else + { + if (modeattacking == ATTACKING_RECORD) + G_UpdateRecordReplays(data); + else if (modeattacking == ATTACKING_NIGHTS) + G_SetNightsRecords(data); + } - if ((earnedEmblems = M_CompletionEmblems())) + if ((earnedEmblems = M_CompletionEmblems(data)) && !silent) CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); } } @@ -4091,7 +4081,8 @@ static void G_DoCompleted(void) if ((skipstats && !modeattacking) || (modeattacking && stagefailed) || (intertype == int_none)) { - G_UpdateVisited(); + G_UpdateVisited(serverGamedata, true); + G_UpdateVisited(clientGamedata, false); G_HandleSaveLevel(); G_AfterIntermission(); } @@ -4100,7 +4091,8 @@ static void G_DoCompleted(void) G_SetGamestate(GS_INTERMISSION); Y_StartIntermission(); Y_LoadIntermissionData(); - G_UpdateVisited(); + G_UpdateVisited(serverGamedata, true); + G_UpdateVisited(clientGamedata, false); G_HandleSaveLevel(); } } @@ -4287,7 +4279,7 @@ void G_LoadGameSettings(void) // G_LoadGameData // Loads the main data file, which stores information such as emblems found, etc. -void G_LoadGameData(void) +void G_LoadGameData(gamedata_t *data) { size_t length; INT32 i, j; @@ -4304,13 +4296,13 @@ void G_LoadGameData(void) INT32 curmare; // Stop saving, until we successfully load it again. - gamedataloaded = false; + data->loaded = false; // Clear things so previously read gamedata doesn't transfer // to new gamedata - G_ClearRecords(); // main and nights records - M_ClearSecrets(); // emblems, unlocks, maps visited, etc - totalplaytime = 0; // total play time (separate from all) + G_ClearRecords(data); // main and nights records + M_ClearSecrets(data); // emblems, unlocks, maps visited, etc + data->totalplaytime = 0; // total play time (separate from all) if (M_CheckParm("-nodata")) { @@ -4321,7 +4313,7 @@ void G_LoadGameData(void) if (M_CheckParm("-resetdata")) { // Don't load, but do save. (essentially, reset) - gamedataloaded = true; + data->loaded = true; return; } @@ -4329,7 +4321,7 @@ void G_LoadGameData(void) if (!length) { // No gamedata. We can save a new one. - gamedataloaded = true; + data->loaded = true; return; } @@ -4352,7 +4344,7 @@ void G_LoadGameData(void) I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } - totalplaytime = READUINT32(save_p); + data->totalplaytime = READUINT32(save_p); #ifdef COMPAT_GAMEDATA_ID if (versionID == COMPAT_GAMEDATA_ID) @@ -4386,7 +4378,7 @@ void G_LoadGameData(void) // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - if ((mapvisited[i] = READUINT8(save_p)) > MV_MAX) + if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) goto datacorrupt; // To save space, use one bit per collected/achieved/unlocked flag @@ -4394,34 +4386,34 @@ void G_LoadGameData(void) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) - emblemlocations[j+i].collected = ((rtemp >> j) & 1); + data->collected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) - extraemblems[j+i].collected = ((rtemp >> j) & 1); + data->extraCollected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXUNLOCKABLES;) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) - unlockables[j+i].unlocked = ((rtemp >> j) & 1); + data->unlocked[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXCONDITIONSETS;) { rtemp = READUINT8(save_p); for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) - conditionSets[j+i].achieved = ((rtemp >> j) & 1); + data->achieved[j+i] = ((rtemp >> j) & 1); i += j; } - timesBeaten = READUINT32(save_p); - timesBeatenWithEmeralds = READUINT32(save_p); - timesBeatenUltimate = READUINT32(save_p); + data->timesBeaten = READUINT32(save_p); + data->timesBeatenWithEmeralds = READUINT32(save_p); + data->timesBeatenUltimate = READUINT32(save_p); // Main records for (i = 0; i < NUMMAPS; ++i) @@ -4436,10 +4428,10 @@ void G_LoadGameData(void) if (recscore || rectime || recrings) { - G_AllocMainRecordData((INT16)i); - mainrecords[i]->score = recscore; - mainrecords[i]->time = rectime; - mainrecords[i]->rings = recrings; + G_AllocMainRecordData((INT16)i, data); + data->mainrecords[i]->score = recscore; + data->mainrecords[i]->time = rectime; + data->mainrecords[i]->rings = recrings; } } @@ -4449,19 +4441,21 @@ void G_LoadGameData(void) if ((recmares = READUINT8(save_p)) == 0) continue; - G_AllocNightsRecordData((INT16)i); + G_AllocNightsRecordData((INT16)i, data); for (curmare = 0; curmare < (recmares+1); ++curmare) { - nightsrecords[i]->score[curmare] = READUINT32(save_p); - nightsrecords[i]->grade[curmare] = READUINT8(save_p); - nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + data->nightsrecords[i]->score[curmare] = READUINT32(save_p); + data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); + data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); - if (nightsrecords[i]->grade[curmare] > GRADE_S) + if (data->nightsrecords[i]->grade[curmare] > GRADE_S) + { goto datacorrupt; + } } - nightsrecords[i]->nummares = recmares; + data->nightsrecords[i]->nummares = recmares; } // done @@ -4472,10 +4466,11 @@ void G_LoadGameData(void) // It used to do this much earlier, but this would cause the gamedata to // save over itself when it I_Errors from the corruption landing point below, // which can accidentally delete players' legitimate data if the code ever has any tiny mistakes! - gamedataloaded = true; + data->loaded = true; // Silent update unlockables in case they're out of sync with conditions - M_SilentUpdateUnlockablesAndEmblems(); + M_SilentUpdateUnlockablesAndEmblems(data); + M_SilentUpdateSkinAvailabilites(); return; @@ -4495,7 +4490,7 @@ void G_LoadGameData(void) // G_SaveGameData // Saves the main data file, which stores information such as emblems found, etc. -void G_SaveGameData(void) +void G_SaveGameData(gamedata_t *data) { size_t length; INT32 i, j; @@ -4503,7 +4498,7 @@ void G_SaveGameData(void) INT32 curmare; - if (!gamedataloaded) + if (!data->loaded) return; // If never loaded (-nodata), don't save save_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE); @@ -4523,20 +4518,20 @@ void G_SaveGameData(void) // Version test WRITEUINT32(save_p, GAMEDATA_ID); - WRITEUINT32(save_p, totalplaytime); + WRITEUINT32(save_p, data->totalplaytime); WRITEUINT32(save_p, quickncasehash(timeattackfolder, sizeof timeattackfolder)); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - WRITEUINT8(save_p, (mapvisited[i] & MV_MAX)); + WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX)); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) { btemp = 0; for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) - btemp |= (emblemlocations[j+i].collected << j); + btemp |= (data->collected[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } @@ -4544,7 +4539,7 @@ void G_SaveGameData(void) { btemp = 0; for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) - btemp |= (extraemblems[j+i].collected << j); + btemp |= (data->extraCollected[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } @@ -4552,7 +4547,7 @@ void G_SaveGameData(void) { btemp = 0; for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) - btemp |= (unlockables[j+i].unlocked << j); + btemp |= (data->unlocked[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } @@ -4560,23 +4555,23 @@ void G_SaveGameData(void) { btemp = 0; for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) - btemp |= (conditionSets[j+i].achieved << j); + btemp |= (data->achieved[j+i] << j); WRITEUINT8(save_p, btemp); i += j; } - WRITEUINT32(save_p, timesBeaten); - WRITEUINT32(save_p, timesBeatenWithEmeralds); - WRITEUINT32(save_p, timesBeatenUltimate); + WRITEUINT32(save_p, data->timesBeaten); + WRITEUINT32(save_p, data->timesBeatenWithEmeralds); + WRITEUINT32(save_p, data->timesBeatenUltimate); // Main records for (i = 0; i < NUMMAPS; i++) { - if (mainrecords[i]) + if (data->mainrecords[i]) { - WRITEUINT32(save_p, mainrecords[i]->score); - WRITEUINT32(save_p, mainrecords[i]->time); - WRITEUINT16(save_p, mainrecords[i]->rings); + WRITEUINT32(save_p, data->mainrecords[i]->score); + WRITEUINT32(save_p, data->mainrecords[i]->time); + WRITEUINT16(save_p, data->mainrecords[i]->rings); } else { @@ -4590,19 +4585,19 @@ void G_SaveGameData(void) // NiGHTS records for (i = 0; i < NUMMAPS; i++) { - if (!nightsrecords[i] || !nightsrecords[i]->nummares) + if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) { WRITEUINT8(save_p, 0); continue; } - WRITEUINT8(save_p, nightsrecords[i]->nummares); + WRITEUINT8(save_p, data->nightsrecords[i]->nummares); - for (curmare = 0; curmare < (nightsrecords[i]->nummares + 1); ++curmare) + for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) { - WRITEUINT32(save_p, nightsrecords[i]->score[curmare]); - WRITEUINT8(save_p, nightsrecords[i]->grade[curmare]); - WRITEUINT32(save_p, nightsrecords[i]->time[curmare]); + WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]); + WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]); + WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); } } diff --git a/src/g_game.h b/src/g_game.h index 144360db4..6cda7ca9c 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -19,6 +19,7 @@ #include "d_event.h" #include "g_demo.h" #include "m_cheat.h" // objectplacing +#include "m_cond.h" extern char gamedatafilename[64]; extern char timeattackfolder[64]; @@ -183,7 +184,7 @@ boolean G_IsTitleCardAvailable(void); // Can be called by the startup code or M_Responder, calls P_SetupLevel. void G_LoadGame(UINT32 slot, INT16 mapoverride); -void G_SaveGameData(void); +void G_SaveGameData(gamedata_t *data); void G_SaveGame(UINT32 slot, INT16 mapnum); @@ -239,7 +240,7 @@ void G_SetModeAttackRetryFlag(void); void G_ClearModeAttackRetryFlag(void); boolean G_GetModeAttackRetryFlag(void); -void G_LoadGameData(void); +void G_LoadGameData(gamedata_t *data); void G_LoadGameSettings(void); void G_SetGameModified(boolean silent); @@ -248,19 +249,19 @@ void G_SetUsedCheats(boolean silent); void G_SetGamestate(gamestate_t newstate); // Gamedata record shit -void G_AllocMainRecordData(INT16 i); -void G_AllocNightsRecordData(INT16 i); -void G_ClearRecords(void); +void G_AllocMainRecordData(INT16 i, gamedata_t *data); +void G_AllocNightsRecordData(INT16 i, gamedata_t *data); +void G_ClearRecords(gamedata_t *data); -UINT32 G_GetBestScore(INT16 map); -tic_t G_GetBestTime(INT16 map); -UINT16 G_GetBestRings(INT16 map); -UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare); -tic_t G_GetBestNightsTime(INT16 map, UINT8 mare); -UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare); +UINT32 G_GetBestScore(INT16 map, gamedata_t *data); +tic_t G_GetBestTime(INT16 map, gamedata_t *data); +UINT16 G_GetBestRings(INT16 map, gamedata_t *data); +UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare, gamedata_t *data); +tic_t G_GetBestNightsTime(INT16 map, UINT8 mare, gamedata_t *data); +UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data); void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare); -void G_SetNightsRecords(void); +void G_SetNightsRecords(gamedata_t *data); FUNCMATH INT32 G_TicsToHours(tic_t tics); FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 55ebe0d4d..eceb6bbaf 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2996,7 +2996,7 @@ static void HU_DrawCoopOverlay(void) if (LUA_HudEnabled(hud_tabemblems)) { - V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems)); + V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(clientGamedata), numemblems+numextraemblems)); V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon); } diff --git a/src/m_cheat.c b/src/m_cheat.c index 9d257b48b..934779982 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -102,7 +102,7 @@ static UINT8 cheatf_devmode(void) // Just unlock all the things and turn on -debug and console devmode. G_SetUsedCheats(false); for (i = 0; i < MAXUNLOCKABLES; i++) - unlockables[i].unlocked = true; + clientGamedata->unlocked[i] = true; devparm = true; cv_debug |= 0x8000; @@ -238,7 +238,7 @@ boolean cht_Responder(event_t *ev) } // Console cheat commands rely on these a lot... -#define REQUIRE_PANDORA if (!M_SecretUnlocked(SECRET_PANDORA) && !cv_debug)\ +#define REQUIRE_PANDORA if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !cv_debug)\ { CONS_Printf(M_GetText("You haven't earned this yet.\n")); return; } #define REQUIRE_DEVMODE if (!cv_debug)\ diff --git a/src/m_cond.c b/src/m_cond.c index bd6faadfd..55f35830a 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -21,6 +21,9 @@ #include "r_skins.h" // numskins #include "r_draw.h" // R_GetColorByName +gamedata_t *clientGamedata; // Our gamedata +gamedata_t *serverGamedata; // Server's gamedata + // Map triggers for linedef executors // 32 triggers, one bit each UINT32 unlocktriggers; @@ -41,6 +44,70 @@ unlockable_t unlockables[MAXUNLOCKABLES]; INT32 numemblems = 0; INT32 numextraemblems = 0; +// Temporary holding place for nights data for the current map +nightsdata_t ntemprecords; + +// Create a new gamedata_t, for start-up +gamedata_t *M_NewGameDataStruct(void) +{ + gamedata_t *data = Z_Calloc(sizeof (*data), PU_STATIC, NULL); + M_ClearSecrets(data); + G_ClearRecords(data); + return data; +} + +void M_CopyGameData(gamedata_t *dest, gamedata_t *src) +{ + INT32 i, j; + + M_ClearSecrets(dest); + G_ClearRecords(dest); + + dest->loaded = src->loaded; + dest->totalplaytime = src->totalplaytime; + + dest->timesBeaten = src->timesBeaten; + dest->timesBeatenWithEmeralds = src->timesBeatenWithEmeralds; + dest->timesBeatenUltimate = src->timesBeatenUltimate; + + memcpy(dest->achieved, src->achieved, sizeof(dest->achieved)); + memcpy(dest->collected, src->collected, sizeof(dest->collected)); + memcpy(dest->extraCollected, src->extraCollected, sizeof(dest->extraCollected)); + memcpy(dest->unlocked, src->unlocked, sizeof(dest->unlocked)); + + memcpy(dest->mapvisited, src->mapvisited, sizeof(dest->mapvisited)); + + // Main records + for (i = 0; i < NUMMAPS; ++i) + { + if (!src->mainrecords[i]) + continue; + + G_AllocMainRecordData((INT16)i, dest); + dest->mainrecords[i]->score = src->mainrecords[i]->score; + dest->mainrecords[i]->time = src->mainrecords[i]->time; + dest->mainrecords[i]->rings = src->mainrecords[i]->rings; + } + + // Nights records + for (i = 0; i < NUMMAPS; ++i) + { + if (!src->nightsrecords[i] || !src->nightsrecords[i]->nummares) + continue; + + G_AllocNightsRecordData((INT16)i, dest); + + for (j = 0; j < (src->nightsrecords[i]->nummares + 1); j++) + { + dest->nightsrecords[i]->score[j] = src->nightsrecords[i]->score[j]; + dest->nightsrecords[i]->grade[j] = src->nightsrecords[i]->grade[j]; + dest->nightsrecords[i]->time[j] = src->nightsrecords[i]->time[j]; + } + + dest->nightsrecords[i]->nummares = src->nightsrecords[i]->nummares; + } +} + void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2) { condition_t *cond; @@ -70,89 +137,90 @@ void M_ClearConditionSet(UINT8 set) conditionSets[set - 1].condition = NULL; conditionSets[set - 1].numconditions = 0; } - conditionSets[set - 1].achieved = false; + clientGamedata->achieved[set - 1] = serverGamedata->achieved[set - 1] = false; } // Clear ALL secrets. -void M_ClearSecrets(void) +void M_ClearSecrets(gamedata_t *data) { INT32 i; - memset(mapvisited, 0, sizeof(mapvisited)); + memset(data->mapvisited, 0, sizeof(data->mapvisited)); for (i = 0; i < MAXEMBLEMS; ++i) - emblemlocations[i].collected = false; + data->collected[i] = false; for (i = 0; i < MAXEXTRAEMBLEMS; ++i) - extraemblems[i].collected = false; + data->extraCollected[i] = false; for (i = 0; i < MAXUNLOCKABLES; ++i) - unlockables[i].unlocked = false; + data->unlocked[i] = false; for (i = 0; i < MAXCONDITIONSETS; ++i) - conditionSets[i].achieved = false; + data->achieved[i] = false; - timesBeaten = timesBeatenWithEmeralds = timesBeatenUltimate = 0; + data->timesBeaten = data->timesBeatenWithEmeralds = data->timesBeatenUltimate = 0; // Re-unlock any always unlocked things - M_SilentUpdateUnlockablesAndEmblems(); + M_SilentUpdateUnlockablesAndEmblems(data); + M_SilentUpdateSkinAvailabilites(); } // ---------------------- // Condition set checking // ---------------------- -static UINT8 M_CheckCondition(condition_t *cn) +static UINT8 M_CheckCondition(condition_t *cn, gamedata_t *data) { switch (cn->type) { case UC_PLAYTIME: // Requires total playing time >= x - return (totalplaytime >= (unsigned)cn->requirement); + return (data->totalplaytime >= (unsigned)cn->requirement); case UC_GAMECLEAR: // Requires game beaten >= x times - return (timesBeaten >= (unsigned)cn->requirement); + return (data->timesBeaten >= (unsigned)cn->requirement); case UC_ALLEMERALDS: // Requires game beaten with all 7 emeralds >= x times - return (timesBeatenWithEmeralds >= (unsigned)cn->requirement); + return (data->timesBeatenWithEmeralds >= (unsigned)cn->requirement); case UC_ULTIMATECLEAR: // Requires game beaten on ultimate >= x times (in other words, never) - return (timesBeatenUltimate >= (unsigned)cn->requirement); + return (data->timesBeatenUltimate >= (unsigned)cn->requirement); case UC_OVERALLSCORE: // Requires overall score >= x - return (M_GotHighEnoughScore(cn->requirement)); + return (M_GotHighEnoughScore(cn->requirement, data)); case UC_OVERALLTIME: // Requires overall time <= x - return (M_GotLowEnoughTime(cn->requirement)); + return (M_GotLowEnoughTime(cn->requirement, data)); case UC_OVERALLRINGS: // Requires overall rings >= x - return (M_GotHighEnoughRings(cn->requirement)); + return (M_GotHighEnoughRings(cn->requirement, data)); case UC_MAPVISITED: // Requires map x to be visited - return ((mapvisited[cn->requirement - 1] & MV_VISITED) == MV_VISITED); + return ((data->mapvisited[cn->requirement - 1] & MV_VISITED) == MV_VISITED); case UC_MAPBEATEN: // Requires map x to be beaten - return ((mapvisited[cn->requirement - 1] & MV_BEATEN) == MV_BEATEN); + return ((data->mapvisited[cn->requirement - 1] & MV_BEATEN) == MV_BEATEN); case UC_MAPALLEMERALDS: // Requires map x to be beaten with all emeralds in possession - return ((mapvisited[cn->requirement - 1] & MV_ALLEMERALDS) == MV_ALLEMERALDS); + return ((data->mapvisited[cn->requirement - 1] & MV_ALLEMERALDS) == MV_ALLEMERALDS); case UC_MAPULTIMATE: // Requires map x to be beaten on ultimate - return ((mapvisited[cn->requirement - 1] & MV_ULTIMATE) == MV_ULTIMATE); + return ((data->mapvisited[cn->requirement - 1] & MV_ULTIMATE) == MV_ULTIMATE); case UC_MAPPERFECT: // Requires map x to be beaten with a perfect bonus - return ((mapvisited[cn->requirement - 1] & MV_PERFECT) == MV_PERFECT); + return ((data->mapvisited[cn->requirement - 1] & MV_PERFECT) == MV_PERFECT); case UC_MAPSCORE: // Requires score on map >= x - return (G_GetBestScore(cn->extrainfo1) >= (unsigned)cn->requirement); + return (G_GetBestScore(cn->extrainfo1, data) >= (unsigned)cn->requirement); case UC_MAPTIME: // Requires time on map <= x - return (G_GetBestTime(cn->extrainfo1) <= (unsigned)cn->requirement); + return (G_GetBestTime(cn->extrainfo1, data) <= (unsigned)cn->requirement); case UC_MAPRINGS: // Requires rings on map >= x - return (G_GetBestRings(cn->extrainfo1) >= cn->requirement); + return (G_GetBestRings(cn->extrainfo1, data) >= cn->requirement); case UC_NIGHTSSCORE: - return (G_GetBestNightsScore(cn->extrainfo1, (UINT8)cn->extrainfo2) >= (unsigned)cn->requirement); + return (G_GetBestNightsScore(cn->extrainfo1, (UINT8)cn->extrainfo2, data) >= (unsigned)cn->requirement); case UC_NIGHTSTIME: - return (G_GetBestNightsTime(cn->extrainfo1, (UINT8)cn->extrainfo2) <= (unsigned)cn->requirement); + return (G_GetBestNightsTime(cn->extrainfo1, (UINT8)cn->extrainfo2, data) <= (unsigned)cn->requirement); case UC_NIGHTSGRADE: - return (G_GetBestNightsGrade(cn->extrainfo1, (UINT8)cn->extrainfo2) >= cn->requirement); + return (G_GetBestNightsGrade(cn->extrainfo1, (UINT8)cn->extrainfo2, data) >= cn->requirement); case UC_TRIGGER: // requires map trigger set return !!(unlocktriggers & (1 << cn->requirement)); case UC_TOTALEMBLEMS: // Requires number of emblems >= x - return (M_GotEnoughEmblems(cn->requirement)); + return (M_GotEnoughEmblems(cn->requirement, data)); case UC_EMBLEM: // Requires emblem x to be obtained - return emblemlocations[cn->requirement-1].collected; + return data->collected[cn->requirement-1]; case UC_EXTRAEMBLEM: // Requires extra emblem x to be obtained - return extraemblems[cn->requirement-1].collected; + return data->extraCollected[cn->requirement-1]; case UC_CONDITIONSET: // requires condition set x to already be achieved - return M_Achieved(cn->requirement-1); + return M_Achieved(cn->requirement-1, data); } return false; } -static UINT8 M_CheckConditionSet(conditionset_t *c) +static UINT8 M_CheckConditionSet(conditionset_t *c, gamedata_t *data) { UINT32 i; UINT32 lastID = 0; @@ -173,13 +241,13 @@ static UINT8 M_CheckConditionSet(conditionset_t *c) continue; lastID = cn->id; - achievedSoFar = M_CheckCondition(cn); + achievedSoFar = M_CheckCondition(cn, data); } return achievedSoFar; } -void M_CheckUnlockConditions(void) +void M_CheckUnlockConditions(gamedata_t *data) { INT32 i; conditionset_t *c; @@ -187,27 +255,27 @@ void M_CheckUnlockConditions(void) for (i = 0; i < MAXCONDITIONSETS; ++i) { c = &conditionSets[i]; - if (!c->numconditions || c->achieved) + if (!c->numconditions || data->achieved[i]) continue; - c->achieved = (M_CheckConditionSet(c)); + data->achieved[i] = (M_CheckConditionSet(c, data)); } } -UINT8 M_UpdateUnlockablesAndExtraEmblems(void) +UINT8 M_UpdateUnlockablesAndExtraEmblems(gamedata_t *data) { INT32 i; char cechoText[992] = ""; UINT8 cechoLines = 0; - M_CheckUnlockConditions(); + M_CheckUnlockConditions(data); // Go through extra emblems for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected || !extraemblems[i].conditionset) + if (data->extraCollected[i] || !extraemblems[i].conditionset) continue; - if ((extraemblems[i].collected = M_Achieved(extraemblems[i].conditionset - 1)) != false) + if ((data->extraCollected[i] = M_Achieved(extraemblems[i].conditionset - 1, data)) != false) { strcat(cechoText, va(M_GetText("Got \"%s\" emblem!\\"), extraemblems[i].name)); ++cechoLines; @@ -217,14 +285,14 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void) // Fun part: if any of those unlocked we need to go through the // unlock conditions AGAIN just in case an emblem reward was reached if (cechoLines) - M_CheckUnlockConditions(); + M_CheckUnlockConditions(data); // Go through unlockables for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (unlockables[i].unlocked || !unlockables[i].conditionset) + if (data->unlocked[i] || !unlockables[i].conditionset) continue; - if ((unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1)) != false) + if ((data->unlocked[i] = M_Achieved(unlockables[i].conditionset - 1, data)) != false) { if (unlockables[i].nocecho) continue; @@ -248,45 +316,49 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void) HU_DoCEcho(slashed); return true; } + return false; } // Used when loading gamedata to make sure all unlocks are synched with conditions -void M_SilentUpdateUnlockablesAndEmblems(void) +void M_SilentUpdateUnlockablesAndEmblems(gamedata_t *data) { INT32 i; boolean checkAgain = false; // Just in case they aren't to sync - M_CheckUnlockConditions(); - M_CheckLevelEmblems(); + M_CheckUnlockConditions(data); + M_CheckLevelEmblems(data); // Go through extra emblems for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected || !extraemblems[i].conditionset) + if (data->extraCollected[i] || !extraemblems[i].conditionset) continue; - if ((extraemblems[i].collected = M_Achieved(extraemblems[i].conditionset - 1)) != false) + if ((data->extraCollected[i] = M_Achieved(extraemblems[i].conditionset - 1, data)) != false) checkAgain = true; } // check again if extra emblems unlocked, blah blah, etc if (checkAgain) - M_CheckUnlockConditions(); + M_CheckUnlockConditions(data); // Go through unlockables for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (unlockables[i].unlocked || !unlockables[i].conditionset) + if (data->unlocked[i] || !unlockables[i].conditionset) continue; - unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1); + data->unlocked[i] = M_Achieved(unlockables[i].conditionset - 1, data); } +} +void M_SilentUpdateSkinAvailabilites(void) +{ players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p } // Emblem unlocking shit -UINT8 M_CheckLevelEmblems(void) +UINT8 M_CheckLevelEmblems(gamedata_t *data) { INT32 i; INT32 valToReach; @@ -297,7 +369,7 @@ UINT8 M_CheckLevelEmblems(void) // Update Score, Time, Rings emblems for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].type <= ET_SKIN || emblemlocations[i].type == ET_MAP || emblemlocations[i].collected) + if (emblemlocations[i].type <= ET_SKIN || emblemlocations[i].type == ET_MAP || data->collected[i]) continue; levelnum = emblemlocations[i].level; @@ -306,32 +378,32 @@ UINT8 M_CheckLevelEmblems(void) switch (emblemlocations[i].type) { case ET_SCORE: // Requires score on map >= x - res = (G_GetBestScore(levelnum) >= (unsigned)valToReach); + res = (G_GetBestScore(levelnum, data) >= (unsigned)valToReach); break; case ET_TIME: // Requires time on map <= x - res = (G_GetBestTime(levelnum) <= (unsigned)valToReach); + res = (G_GetBestTime(levelnum, data) <= (unsigned)valToReach); break; case ET_RINGS: // Requires rings on map >= x - res = (G_GetBestRings(levelnum) >= valToReach); + res = (G_GetBestRings(levelnum, data) >= valToReach); break; case ET_NGRADE: // Requires NiGHTS grade on map >= x - res = (G_GetBestNightsGrade(levelnum, 0) >= valToReach); + res = (G_GetBestNightsGrade(levelnum, 0, data) >= valToReach); break; case ET_NTIME: // Requires NiGHTS time on map <= x - res = (G_GetBestNightsTime(levelnum, 0) <= (unsigned)valToReach); + res = (G_GetBestNightsTime(levelnum, 0, data) <= (unsigned)valToReach); break; default: // unreachable but shuts the compiler up. continue; } - emblemlocations[i].collected = res; + data->collected[i] = res; if (res) ++somethingUnlocked; } return somethingUnlocked; } -UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separate print when awarding emblems and it's sorta different enough. +UINT8 M_CompletionEmblems(gamedata_t *data) // Bah! Duplication sucks, but it's for a separate print when awarding emblems and it's sorta different enough. { INT32 i; INT32 embtype; @@ -342,7 +414,7 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].type != ET_MAP || emblemlocations[i].collected) + if (emblemlocations[i].type != ET_MAP || data->collected[i]) continue; levelnum = emblemlocations[i].level; @@ -358,9 +430,9 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa if (embtype & ME_PERFECT) flags |= MV_PERFECT; - res = ((mapvisited[levelnum - 1] & flags) == flags); + res = ((data->mapvisited[levelnum - 1] & flags) == flags); - emblemlocations[i].collected = res; + data->collected[i] = res; if (res) ++somethingUnlocked; } @@ -370,48 +442,54 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa // ------------------- // Quick unlock checks // ------------------- -UINT8 M_AnySecretUnlocked(void) +UINT8 M_AnySecretUnlocked(gamedata_t *data) { INT32 i; for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (!unlockables[i].nocecho && unlockables[i].unlocked) + if (!unlockables[i].nocecho && data->unlocked[i]) return true; } return false; } -UINT8 M_SecretUnlocked(INT32 type) +UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data) { INT32 i; for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (unlockables[i].type == type && unlockables[i].unlocked) + if (unlockables[i].type == type && data->unlocked[i]) return true; } return false; } -UINT8 M_MapLocked(INT32 mapnum) +UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) { if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0) + { return false; - if (!unlockables[mapheaderinfo[mapnum-1]->unlockrequired].unlocked) + } + + if (!data->unlocked[mapheaderinfo[mapnum-1]->unlockrequired]) + { return true; + } + return false; } -INT32 M_CountEmblems(void) +INT32 M_CountEmblems(gamedata_t *data) { INT32 found = 0, i; for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].collected) + if (data->collected[i]) found++; } for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected) + if (data->extraCollected[i]) found++; } return found; @@ -423,23 +501,23 @@ INT32 M_CountEmblems(void) // Theoretically faster than using M_CountEmblems() // Stops when it reaches the target number of emblems. -UINT8 M_GotEnoughEmblems(INT32 number) +UINT8 M_GotEnoughEmblems(INT32 number, gamedata_t *data) { INT32 i, gottenemblems = 0; for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].collected) + if (data->collected[i]) if (++gottenemblems >= number) return true; } for (i = 0; i < numextraemblems; ++i) { - if (extraemblems[i].collected) + if (data->extraCollected[i]) if (++gottenemblems >= number) return true; } return false; } -UINT8 M_GotHighEnoughScore(INT32 tscore) +UINT8 M_GotHighEnoughScore(INT32 tscore, gamedata_t *data) { INT32 mscore = 0; INT32 i; @@ -448,16 +526,16 @@ UINT8 M_GotHighEnoughScore(INT32 tscore) { if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i]) + if (!data->mainrecords[i]) continue; - if ((mscore += mainrecords[i]->score) > tscore) + if ((mscore += data->mainrecords[i]->score) > tscore) return true; } return false; } -UINT8 M_GotLowEnoughTime(INT32 tictime) +UINT8 M_GotLowEnoughTime(INT32 tictime, gamedata_t *data) { INT32 curtics = 0; INT32 i; @@ -467,15 +545,15 @@ UINT8 M_GotLowEnoughTime(INT32 tictime) if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i] || !mainrecords[i]->time) + if (!data->mainrecords[i] || !data->mainrecords[i]->time) return false; - else if ((curtics += mainrecords[i]->time) > tictime) + else if ((curtics += data->mainrecords[i]->time) > tictime) return false; } return true; } -UINT8 M_GotHighEnoughRings(INT32 trings) +UINT8 M_GotHighEnoughRings(INT32 trings, gamedata_t *data) { INT32 mrings = 0; INT32 i; @@ -484,10 +562,10 @@ UINT8 M_GotHighEnoughRings(INT32 trings) { if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i]) + if (!data->mainrecords[i]) continue; - if ((mrings += mainrecords[i]->rings) > trings) + if ((mrings += data->mainrecords[i]->rings) > trings) return true; } return false; diff --git a/src/m_cond.h b/src/m_cond.h index d49dc920b..6a3da79ec 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -10,7 +10,11 @@ /// \file m_cond.h /// \brief Unlockable condition system for SRB2 version 2.1 +#ifndef __M_COND__ +#define __M_COND__ + #include "doomdef.h" +#include "doomdata.h" // -------- // Typedefs @@ -61,8 +65,6 @@ typedef struct { UINT32 numconditions; /// <- number of conditions. condition_t *condition; /// <- All conditionals to be checked. - UINT8 achieved; /// <- Whether this conditional has been achieved already or not. - /// (Conditional checking is skipped if true -- it's assumed you can't relock an unlockable) } conditionset_t; // Emblem information @@ -94,7 +96,6 @@ typedef struct INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin) char *stringVar; ///< String version char hint[110]; ///< Hint for emblem hints menu - UINT8 collected; ///< Do you have this emblem? } emblem_t; typedef struct { @@ -104,7 +105,6 @@ typedef struct UINT8 showconditionset; ///< Condition set that shows this emblem. UINT8 sprite; ///< emblem sprite to use, 0 - 25 UINT16 color; ///< skincolor to use - UINT8 collected; ///< Do you have this emblem? } extraemblem_t; // Unlockable information @@ -120,7 +120,6 @@ typedef struct char *stringVar; UINT8 nocecho; UINT8 nochecklist; - UINT8 unlocked; } unlockable_t; #define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired @@ -143,6 +142,83 @@ typedef struct #define MAXEXTRAEMBLEMS 16 #define MAXUNLOCKABLES 32 +/** Time attack information, currently a very small structure. + */ +typedef struct +{ + tic_t time; ///< Time in which the level was finished. + UINT32 score; ///< Score when the level was finished. + UINT16 rings; ///< Rings when the level was finished. +} recorddata_t; + +/** Setup for one NiGHTS map. + * These are dynamically allocated because I am insane + */ +#define GRADE_F 0 +#define GRADE_E 1 +#define GRADE_D 2 +#define GRADE_C 3 +#define GRADE_B 4 +#define GRADE_A 5 +#define GRADE_S 6 + +typedef struct +{ + // 8 mares, 1 overall (0) + UINT8 nummares; + UINT32 score[9]; + UINT8 grade[9]; + tic_t time[9]; +} nightsdata_t; + +// mapvisited is now a set of flags that says what we've done in the map. +#define MV_VISITED 1 +#define MV_BEATEN 2 +#define MV_ALLEMERALDS 4 +#define MV_ULTIMATE 8 +#define MV_PERFECT 16 +#define MV_PERFECTRA 32 +#define MV_MAX 63 // used in gamedata check, update whenever MV's are added + +// Temporary holding place for nights data for the current map +extern nightsdata_t ntemprecords; + +// GAMEDATA STRUCTURE +// Everything that would get saved in gamedata.dat +typedef struct +{ + // WHENEVER OR NOT WE'RE READY TO SAVE + boolean loaded; + + // CONDITION SETS ACHIEVED + boolean achieved[MAXCONDITIONSETS]; + + // EMBLEMS COLLECTED + boolean collected[MAXEMBLEMS]; + + // EXTRA EMBLEMS COLLECTED + boolean extraCollected[MAXEXTRAEMBLEMS]; + + // UNLOCKABLES UNLOCKED + boolean unlocked[MAXUNLOCKABLES]; + + // TIME ATTACK DATA + recorddata_t *mainrecords[NUMMAPS]; + nightsdata_t *nightsrecords[NUMMAPS]; + UINT8 mapvisited[NUMMAPS]; + + // # OF TIMES THE GAME HAS BEEN BEATEN + UINT32 timesBeaten; + UINT32 timesBeatenWithEmeralds; + UINT32 timesBeatenUltimate; + + // PLAY TIME + UINT32 totalplaytime; +} gamedata_t; + +extern gamedata_t *clientGamedata; +extern gamedata_t *serverGamedata; + extern conditionset_t conditionSets[MAXCONDITIONSETS]; extern emblem_t emblemlocations[MAXEMBLEMS]; extern extraemblem_t extraemblems[MAXEXTRAEMBLEMS]; @@ -153,25 +229,30 @@ extern INT32 numextraemblems; extern UINT32 unlocktriggers; +gamedata_t *M_NewGameDataStruct(void); +void M_CopyGameData(gamedata_t *dest, gamedata_t *src); + // Condition set setup void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2); // Clearing secrets void M_ClearConditionSet(UINT8 set); -void M_ClearSecrets(void); +void M_ClearSecrets(gamedata_t *data); // Updating conditions and unlockables -void M_CheckUnlockConditions(void); -UINT8 M_UpdateUnlockablesAndExtraEmblems(void); -void M_SilentUpdateUnlockablesAndEmblems(void); -UINT8 M_CheckLevelEmblems(void); -UINT8 M_CompletionEmblems(void); +void M_CheckUnlockConditions(gamedata_t *data); +UINT8 M_UpdateUnlockablesAndExtraEmblems(gamedata_t *data); +void M_SilentUpdateUnlockablesAndEmblems(gamedata_t *data); +UINT8 M_CheckLevelEmblems(gamedata_t *data); +UINT8 M_CompletionEmblems(gamedata_t *data); + +void M_SilentUpdateSkinAvailabilites(void); // Checking unlockable status -UINT8 M_AnySecretUnlocked(void); -UINT8 M_SecretUnlocked(INT32 type); -UINT8 M_MapLocked(INT32 mapnum); -INT32 M_CountEmblems(void); +UINT8 M_AnySecretUnlocked(gamedata_t *data); +UINT8 M_SecretUnlocked(INT32 type, gamedata_t *data); +UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data); +INT32 M_CountEmblems(gamedata_t *data); // Emblem shit emblem_t *M_GetLevelEmblems(INT32 mapnum); @@ -183,12 +264,14 @@ const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big); // If you're looking to compare stats for unlocks or what not, use these // They stop checking upon reaching the target number so they // should be (theoretically?) slightly faster. -UINT8 M_GotEnoughEmblems(INT32 number); -UINT8 M_GotHighEnoughScore(INT32 tscore); -UINT8 M_GotLowEnoughTime(INT32 tictime); -UINT8 M_GotHighEnoughRings(INT32 trings); +UINT8 M_GotEnoughEmblems(INT32 number, gamedata_t *data); +UINT8 M_GotHighEnoughScore(INT32 tscore, gamedata_t *data); +UINT8 M_GotLowEnoughTime(INT32 tictime, gamedata_t *data); +UINT8 M_GotHighEnoughRings(INT32 trings, gamedata_t *data); INT32 M_UnlockableSkinNum(unlockable_t *unlock); INT32 M_EmblemSkinNum(emblem_t *emblem); -#define M_Achieved(a) ((a) >= MAXCONDITIONSETS || conditionSets[a].achieved) +#define M_Achieved(a, data) ((a) >= MAXCONDITIONSETS || data->achieved[a]) + +#endif diff --git a/src/m_menu.c b/src/m_menu.c index 64a1c9404..2214e6a6a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2284,6 +2284,7 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt); // Nextmap. Used for Level select. void Nextmap_OnChange(void) { + gamedata_t *data = clientGamedata; char *leveltitle; char tabase[256]; #ifdef OLDNREPLAYNAME @@ -2301,7 +2302,7 @@ void Nextmap_OnChange(void) { CV_StealthSetValue(&cv_dummymares, 0); // Hide the record changing CVAR if only one mare is available. - if (!nightsrecords[cv_nextmap.value-1] || nightsrecords[cv_nextmap.value-1]->nummares < 2) + if (!data->nightsrecords[cv_nextmap.value-1] || data->nightsrecords[cv_nextmap.value-1]->nummares < 2) SP_NightsAttackMenu[narecords].status = IT_DISABLED; else SP_NightsAttackMenu[narecords].status = IT_STRING|IT_CVAR; @@ -2432,14 +2433,15 @@ void Nextmap_OnChange(void) static void Dummymares_OnChange(void) { - if (!nightsrecords[cv_nextmap.value-1]) + gamedata_t *data = clientGamedata; + if (!data->nightsrecords[cv_nextmap.value-1]) { CV_StealthSetValue(&cv_dummymares, 0); return; } else { - UINT8 mares = nightsrecords[cv_nextmap.value-1]->nummares; + UINT8 mares = data->nightsrecords[cv_nextmap.value-1]->nummares; if (cv_dummymares.value < 0) CV_StealthSetValue(&cv_dummymares, mares); @@ -3670,9 +3672,9 @@ void M_StartControlPanel(void) if (!Playing()) { // Secret menu! - MainMenu[singleplr].alphaKey = (M_AnySecretUnlocked()) ? 76 : 84; - MainMenu[multiplr].alphaKey = (M_AnySecretUnlocked()) ? 84 : 92; - MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + MainMenu[singleplr].alphaKey = (M_AnySecretUnlocked(clientGamedata)) ? 76 : 84; + MainMenu[multiplr].alphaKey = (M_AnySecretUnlocked(clientGamedata)) ? 84 : 92; + MainMenu[secrets].status = (M_AnySecretUnlocked(clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); currentMenu = &MainDef; itemOn = singleplr; @@ -3680,14 +3682,14 @@ void M_StartControlPanel(void) else if (modeattacking) { currentMenu = &MAPauseDef; - MAPauseMenu[mapause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + MAPauseMenu[mapause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); itemOn = mapause_continue; } else if (!(netgame || multiplayer)) // Single Player { if (gamestate != GS_LEVEL || ultimatemode) // intermission, so gray out stuff. { - SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA)) ? (IT_GRAYEDOUT) : (IT_DISABLED); + SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA, serverGamedata)) ? (IT_GRAYEDOUT) : (IT_DISABLED); SPauseMenu[spause_retry].status = IT_GRAYEDOUT; } else @@ -3696,7 +3698,7 @@ void M_StartControlPanel(void) if (players[consoleplayer].playerstate != PST_LIVE) ++numlives; - SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // The list of things that can disable retrying is (was?) a little too complex // for me to want to use the short if statement syntax @@ -3710,7 +3712,7 @@ void M_StartControlPanel(void) SPauseMenu[spause_levelselect].status = (gamecomplete == 1) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // And emblem hints. - SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // Shift up Pandora's Box if both pandora and levelselect are active /*if (SPauseMenu[spause_pandora].status != (IT_DISABLED) @@ -4259,7 +4261,7 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y, boolean norecordatt x -= 4; lasttype = curtype; - if (emblem->collected) + if (clientGamedata->collected[emblem - emblemlocations]) V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else @@ -4692,6 +4694,8 @@ static void M_DrawGenericScrollMenu(void) static void M_DrawPauseMenu(void) { + gamedata_t *data = clientGamedata; + if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)) { emblem_t *emblem_detail[3] = {NULL, NULL, NULL}; @@ -4720,7 +4724,7 @@ static void M_DrawPauseMenu(void) { case ET_SCORE: snprintf(targettext, 9, "%d", emblem->var); - snprintf(currenttext, 9, "%u", G_GetBestScore(gamemap)); + snprintf(currenttext, 9, "%u", G_GetBestScore(gamemap, data)); targettext[8] = 0; currenttext[8] = 0; @@ -4734,7 +4738,7 @@ static void M_DrawPauseMenu(void) G_TicsToSeconds((tic_t)emblemslot), G_TicsToCentiseconds((tic_t)emblemslot)); - emblemslot = (INT32)G_GetBestTime(gamemap); // dumb hack pt ii + emblemslot = (INT32)G_GetBestTime(gamemap, data); // dumb hack pt ii if ((tic_t)emblemslot == UINT32_MAX) snprintf(currenttext, 9, "-:--.--"); else @@ -4750,7 +4754,7 @@ static void M_DrawPauseMenu(void) break; case ET_RINGS: snprintf(targettext, 9, "%d", emblem->var); - snprintf(currenttext, 9, "%u", G_GetBestRings(gamemap)); + snprintf(currenttext, 9, "%u", G_GetBestRings(gamemap, data)); targettext[8] = 0; currenttext[8] = 0; @@ -4758,8 +4762,8 @@ static void M_DrawPauseMenu(void) emblemslot = 2; break; case ET_NGRADE: - snprintf(targettext, 9, "%u", P_GetScoreForGradeOverall(gamemap, emblem->var)); - snprintf(currenttext, 9, "%u", G_GetBestNightsScore(gamemap, 0)); + snprintf(targettext, 9, "%u", P_GetScoreForGrade(gamemap, 0, emblem->var)); + snprintf(currenttext, 9, "%u", G_GetBestNightsScore(gamemap, 0, data)); targettext[8] = 0; currenttext[8] = 0; @@ -4773,7 +4777,7 @@ static void M_DrawPauseMenu(void) G_TicsToSeconds((tic_t)emblemslot), G_TicsToCentiseconds((tic_t)emblemslot)); - emblemslot = (INT32)G_GetBestNightsTime(gamemap, 0); // dumb hack pt iv + emblemslot = (INT32)G_GetBestNightsTime(gamemap, 0, data); // dumb hack pt iv if ((tic_t)emblemslot == UINT32_MAX) snprintf(currenttext, 9, "-:--.--"); else @@ -4807,7 +4811,7 @@ static void M_DrawPauseMenu(void) if (!emblem) continue; - if (emblem->collected) + if (data->collected[emblem - emblemlocations]) V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); else @@ -5019,7 +5023,9 @@ static void M_PatchSkinNameTable(void) // static boolean M_LevelAvailableOnPlatter(INT32 mapnum) { - if (M_MapLocked(mapnum+1)) + gamedata_t *data = serverGamedata; + + if (M_MapLocked(mapnum+1, data)) return false; // not unlocked switch (levellistmode) @@ -5032,7 +5038,7 @@ static boolean M_LevelAvailableOnPlatter(INT32 mapnum) return true; #ifndef DEVELOP - if (mapvisited[mapnum]) // MV_MP + if (data->mapvisited[mapnum]) #endif return true; @@ -5040,7 +5046,7 @@ static boolean M_LevelAvailableOnPlatter(INT32 mapnum) case LLM_RECORDATTACK: case LLM_NIGHTSATTACK: #ifndef DEVELOP - if (mapvisited[mapnum] & MV_MAX) + if (data->mapvisited[mapnum]) return true; if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) @@ -5071,7 +5077,7 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (!mapheaderinfo[mapnum]->lvlttl[0]) return false; - /*if (M_MapLocked(mapnum+1)) + /*if (M_MapLocked(mapnum+1, serverGamedata)) return false; // not unlocked*/ switch (levellistmode) @@ -6904,7 +6910,7 @@ static void M_HandleAddons(INT32 choice) closefilemenu(true); // secrets disabled by addfile... - MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + MainMenu[secrets].status = (M_AnySecretUnlocked(clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); if (currentMenu->prevMenu) M_SetupNextMenu(currentMenu->prevMenu); @@ -7150,7 +7156,9 @@ static boolean checklist_cangodown; // uuuueeerggghhhh HACK static void M_HandleChecklist(INT32 choice) { + gamedata_t *data = clientGamedata; INT32 j; + switch (choice) { case KEY_DOWNARROW: @@ -7167,7 +7175,7 @@ static void M_HandleChecklist(INT32 choice) continue; if (unlockables[j].conditionset > MAXCONDITIONSETS) continue; - if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset)) + if (!data->unlocked[j] && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset, data)) continue; if (unlockables[j].conditionset == unlockables[check_on].conditionset) continue; @@ -7192,7 +7200,7 @@ static void M_HandleChecklist(INT32 choice) continue; if (unlockables[j].conditionset > MAXCONDITIONSETS) continue; - if (!unlockables[j].unlocked && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset)) + if (!data->unlocked[j] && unlockables[j].showconditionset && !M_Achieved(unlockables[j].showconditionset, data)) continue; if (j && unlockables[j].conditionset == unlockables[j-1].conditionset) continue; @@ -7218,6 +7226,9 @@ static void M_HandleChecklist(INT32 choice) static void M_DrawChecklist(void) { + gamedata_t *data = clientGamedata; + INT32 emblemCount = M_CountEmblems(data); + INT32 i = check_on, j = 0, y = currentMenu->y, emblems = numemblems+numextraemblems; UINT32 condnum, previd, maxcond; condition_t *cond; @@ -7228,7 +7239,7 @@ static void M_DrawChecklist(void) // draw emblem counter if (emblems > 0) { - V_DrawString(42, 20, (emblems == M_CountEmblems()) ? V_GREENMAP : 0, va("%d/%d", M_CountEmblems(), emblems)); + V_DrawString(42, 20, (emblems == emblemCount) ? V_GREENMAP : 0, va("%d/%d", emblemCount, emblems)); V_DrawSmallScaledPatch(28, 20, 0, W_CachePatchName("EMBLICON", PU_PATCH)); } @@ -7239,13 +7250,13 @@ static void M_DrawChecklist(void) { if (unlockables[i].name[0] == 0 //|| unlockables[i].nochecklist || !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS - || (!unlockables[i].unlocked && unlockables[i].showconditionset && !M_Achieved(unlockables[i].showconditionset))) + || (!data->unlocked[i] && unlockables[i].showconditionset && !M_Achieved(unlockables[i].showconditionset, data))) { i += 1; continue; } - V_DrawString(currentMenu->x, y, ((unlockables[i].unlocked) ? V_GREENMAP : V_TRANSLUCENT)|V_ALLOWLOWERCASE, ((unlockables[i].unlocked || !unlockables[i].nochecklist) ? unlockables[i].name : M_CreateSecretMenuOption(unlockables[i].name))); + V_DrawString(currentMenu->x, y, ((data->unlocked[i]) ? V_GREENMAP : V_TRANSLUCENT)|V_ALLOWLOWERCASE, ((data->unlocked[i] || !unlockables[i].nochecklist) ? unlockables[i].name : M_CreateSecretMenuOption(unlockables[i].name))); for (j = i+1; j < MAXUNLOCKABLES; j++) { @@ -7323,7 +7334,7 @@ static void M_DrawChecklist(void) if (title) { - const char *level = ((M_MapLocked(cond[condnum].requirement) || !((mapheaderinfo[cond[condnum].requirement-1]->menuflags & LF2_NOVISITNEEDED) || (mapvisited[cond[condnum].requirement-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); + const char *level = ((M_MapLocked(cond[condnum].requirement, data) || !((mapheaderinfo[cond[condnum].requirement-1]->menuflags & LF2_NOVISITNEEDED) || (data->mapvisited[cond[condnum].requirement-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); switch (cond[condnum].type) { @@ -7356,7 +7367,7 @@ static void M_DrawChecklist(void) if (title) { - const char *level = ((M_MapLocked(cond[condnum].extrainfo1) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); + const char *level = ((M_MapLocked(cond[condnum].extrainfo1, data) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (data->mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); switch (cond[condnum].type) { @@ -7425,7 +7436,7 @@ static void M_DrawChecklist(void) if (title) { - const char *level = ((M_MapLocked(cond[condnum].extrainfo1) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); + const char *level = ((M_MapLocked(cond[condnum].extrainfo1, data) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || (data->mapvisited[cond[condnum].extrainfo1-1] & MV_MAX))) ? M_CreateSecretMenuOption(title) : title); switch (cond[condnum].type) { @@ -7488,7 +7499,7 @@ static void M_DrawChecklist(void) /*V_DrawString(160, 8+(24*j), V_RETURN8, V_WordWrap(160, 292, 0, unlockables[i].objective)); - if (unlockables[i].unlocked) + if (data->unlocked[i]) V_DrawString(308, 8+(24*j), V_YELLOWMAP, "Y"); else V_DrawString(308, 8+(24*j), V_YELLOWMAP, "N");*/ @@ -7517,7 +7528,7 @@ static void M_EmblemHints(INT32 choice) (void)choice; SR_EmblemHintMenu[0].status = (local > NUMHINTS*2) ? (IT_STRING | IT_ARROWS) : (IT_DISABLED); - SR_EmblemHintMenu[1].status = (M_SecretUnlocked(SECRET_ITEMFINDER)) ? (IT_CVAR|IT_STRING) : (IT_SECRET); + SR_EmblemHintMenu[1].status = (M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) ? (IT_CVAR|IT_STRING) : (IT_SECRET); hintpage = 1; SR_EmblemHintDef.prevMenu = currentMenu; M_SetupNextMenu(&SR_EmblemHintDef); @@ -7577,7 +7588,7 @@ static void M_DrawEmblemHints(void) if (totalemblems >= ((hintpage-1)*(NUMHINTS*2) + 1) && totalemblems < (hintpage*NUMHINTS*2)+1){ - if (emblem->collected) + if (clientGamedata->collected[i]) { collected = V_GREENMAP; V_DrawMappedPatch(x, y+4, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_PATCH), @@ -8117,7 +8128,7 @@ static void M_SecretsMenu(INT32 choice) SR_MainMenu[i].status = IT_SECRET; - if (unlockables[ul].unlocked) + if (clientGamedata->unlocked[ul]) { switch (unlockables[ul].type) { @@ -8216,7 +8227,7 @@ static void M_SinglePlayerMenu(INT32 choice) levellistmode = LLM_RECORDATTACK; if (M_GametypeHasLevels(-1)) - SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; + SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK, clientGamedata)) ? IT_CALL|IT_STRING : IT_SECRET; else // If Record Attack is nonexistent in the current add-on... { SP_MainMenu[sprecordattack].status = IT_NOTHING|IT_DISABLED; // ...hide and disable the Record Attack option... @@ -8226,7 +8237,7 @@ static void M_SinglePlayerMenu(INT32 choice) levellistmode = LLM_NIGHTSATTACK; if (M_GametypeHasLevels(-1)) - SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET; + SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE, clientGamedata)) ? IT_CALL|IT_STRING : IT_SECRET; else // If NiGHTS Mode is nonexistent in the current add-on... { SP_MainMenu[spnightsmode].status = IT_NOTHING|IT_DISABLED; // ...hide and disable the NiGHTS Mode option... @@ -8249,7 +8260,7 @@ static void M_SinglePlayerMenu(INT32 choice) SP_MainMenu[spnightsmode] .alphaKey += 8; } else // Otherwise, if Marathon Run is allowed and Record Attack is unlocked, unlock Marathon Run! - SP_MainMenu[spmarathon].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED : IT_SECRET; + SP_MainMenu[spmarathon].status = (M_SecretUnlocked(SECRET_RECORDATTACK, clientGamedata)) ? IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED : IT_SECRET; if (tutorialmap) // If there's a tutorial available in the current add-on... @@ -9626,7 +9637,7 @@ static void M_Statistics(INT32 choice) if (!(mapheaderinfo[i]->typeoflevel & TOL_SP) || (mapheaderinfo[i]->menuflags & LF2_HIDEINSTATS)) continue; - if (!(mapvisited[i] & MV_MAX)) + if (!(clientGamedata->mapvisited[i] & MV_MAX)) continue; statsMapList[j++] = i; @@ -9643,6 +9654,7 @@ static void M_Statistics(INT32 choice) static void M_DrawStatsMaps(int location) { + gamedata_t *data = clientGamedata; INT32 y = 80, i = -1; INT16 mnum; extraemblem_t *exemblem; @@ -9710,14 +9722,14 @@ static void M_DrawStatsMaps(int location) { exemblem = &extraemblems[i]; - if (exemblem->collected) + if (data->extraCollected[i]) V_DrawSmallMappedPatch(292, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE)); else V_DrawSmallScaledPatch(292, y, 0, W_CachePatchName("NEEDIT", PU_PATCH)); V_DrawString(20, y, V_YELLOWMAP|V_ALLOWLOWERCASE, - (!exemblem->collected && exemblem->showconditionset && !M_Achieved(exemblem->showconditionset)) + (!data->extraCollected[i] && exemblem->showconditionset && !M_Achieved(exemblem->showconditionset, data)) ? M_CreateSecretMenuOption(exemblem->description) : exemblem->description); } @@ -9734,6 +9746,7 @@ bottomarrow: static void M_DrawLevelStats(void) { + gamedata_t *data = clientGamedata; char beststr[40]; tic_t besttime = 0; @@ -9748,9 +9761,9 @@ static void M_DrawLevelStats(void) V_DrawString(20, 24, V_YELLOWMAP, "Total Play Time:"); V_DrawCenteredString(BASEVIDWIDTH/2, 32, 0, va("%i hours, %i minutes, %i seconds", - G_TicsToHours(totalplaytime), - G_TicsToMinutes(totalplaytime, false), - G_TicsToSeconds(totalplaytime))); + G_TicsToHours(data->totalplaytime), + G_TicsToMinutes(data->totalplaytime, false), + G_TicsToSeconds(data->totalplaytime))); for (i = 0; i < NUMMAPS; i++) { @@ -9759,25 +9772,25 @@ static void M_DrawLevelStats(void) if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) continue; - if (!mainrecords[i]) + if (!data->mainrecords[i]) { mapsunfinished++; bestunfinished[0] = bestunfinished[1] = bestunfinished[2] = true; continue; } - if (mainrecords[i]->score > 0) - bestscore += mainrecords[i]->score; + if (data->mainrecords[i]->score > 0) + bestscore += data->mainrecords[i]->score; else mapunfinished = bestunfinished[0] = true; - if (mainrecords[i]->time > 0) - besttime += mainrecords[i]->time; + if (data->mainrecords[i]->time > 0) + besttime += data->mainrecords[i]->time; else mapunfinished = bestunfinished[1] = true; - if (mainrecords[i]->rings > 0) - bestrings += mainrecords[i]->rings; + if (data->mainrecords[i]->rings > 0) + bestrings += data->mainrecords[i]->rings; else mapunfinished = bestunfinished[2] = true; @@ -9792,7 +9805,7 @@ static void M_DrawLevelStats(void) else V_DrawString(20, 56, V_GREENMAP, "(complete)"); - V_DrawString(36, 64, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems)); + V_DrawString(36, 64, 0, va("x %d/%d", M_CountEmblems(data), numemblems+numextraemblems)); V_DrawSmallScaledPatch(20, 64, 0, W_CachePatchName("EMBLICON", PU_PATCH)); sprintf(beststr, "%u", bestscore); @@ -9859,6 +9872,7 @@ static void M_HandleLevelStats(INT32 choice) // Drawing function for Time Attack void M_DrawTimeAttackMenu(void) { + gamedata_t *data = clientGamedata; INT32 i, x, y, empatx, empaty, cursory = 0; UINT16 dispstatus; patch_t *PictureOfUrFace; // my WHAT @@ -10017,7 +10031,7 @@ void M_DrawTimeAttackMenu(void) empatx = empatch->leftoffset / 2; empaty = empatch->topoffset / 2; - if (em->collected) + if (data->collected[em - emblemlocations]) V_DrawSmallMappedPatch(104+76+empatx, yHeight+lsheadingheight/2+empaty, 0, empatch, R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else @@ -10030,34 +10044,34 @@ void M_DrawTimeAttackMenu(void) // Draw in-level emblems. M_DrawMapEmblems(cv_nextmap.value, 288, 28, true); - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->score) + if (!data->mainrecords[cv_nextmap.value-1] || !data->mainrecords[cv_nextmap.value-1]->score) sprintf(beststr, "(none)"); else - sprintf(beststr, "%u", mainrecords[cv_nextmap.value-1]->score); + sprintf(beststr, "%u", data->mainrecords[cv_nextmap.value-1]->score); V_DrawString(104-72, 33+lsheadingheight/2, V_YELLOWMAP, "SCORE:"); V_DrawRightAlignedString(104+64, 33+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); V_DrawRightAlignedString(104+72, 43+lsheadingheight/2, V_ALLOWLOWERCASE, reqscore); - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) + if (!data->mainrecords[cv_nextmap.value-1] || !data->mainrecords[cv_nextmap.value-1]->time) sprintf(beststr, "(none)"); else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(mainrecords[cv_nextmap.value-1]->time, true), - G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), - G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); + sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(data->mainrecords[cv_nextmap.value-1]->time, true), + G_TicsToSeconds(data->mainrecords[cv_nextmap.value-1]->time), + G_TicsToCentiseconds(data->mainrecords[cv_nextmap.value-1]->time)); V_DrawString(104-72, 53+lsheadingheight/2, V_YELLOWMAP, "TIME:"); V_DrawRightAlignedString(104+64, 53+lsheadingheight/2, V_ALLOWLOWERCASE, beststr); V_DrawRightAlignedString(104+72, 63+lsheadingheight/2, V_ALLOWLOWERCASE, reqtime); - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->rings) + if (!data->mainrecords[cv_nextmap.value-1] || !data->mainrecords[cv_nextmap.value-1]->rings) sprintf(beststr, "(none)"); else - sprintf(beststr, "%hu", mainrecords[cv_nextmap.value-1]->rings); + sprintf(beststr, "%hu", data->mainrecords[cv_nextmap.value-1]->rings); V_DrawString(104-72, 73+lsheadingheight/2, V_YELLOWMAP, "RINGS:"); - V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE|((mapvisited[cv_nextmap.value-1] & MV_PERFECTRA) ? V_YELLOWMAP : 0), beststr); + V_DrawRightAlignedString(104+64, 73+lsheadingheight/2, V_ALLOWLOWERCASE|((data->mapvisited[cv_nextmap.value-1] & MV_PERFECTRA) ? V_YELLOWMAP : 0), beststr); V_DrawRightAlignedString(104+72, 83+lsheadingheight/2, V_ALLOWLOWERCASE, reqrings); } @@ -10151,6 +10165,7 @@ static void M_TimeAttack(INT32 choice) // Drawing function for Nights Attack void M_DrawNightsAttackMenu(void) { + gamedata_t *data = clientGamedata; INT32 i, x, y, cursory = 0; UINT16 dispstatus; @@ -10217,10 +10232,10 @@ void M_DrawNightsAttackMenu(void) lumpnum_t lumpnum; char beststr[40]; - //UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0); - UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value); - UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value); - tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value); + //UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0, data); + UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value, data); + UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value, data); + tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value, data); M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false); @@ -10301,7 +10316,7 @@ void M_DrawNightsAttackMenu(void) goto skipThisOne; } - if (em->collected) + if (data->collected[em - emblemlocations]) V_DrawSmallMappedPatch(xpos, yHeight+lsheadingheight/2, 0, W_CachePatchName(M_GetEmblemPatch(em, false), PU_PATCH), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); else @@ -12544,12 +12559,12 @@ static void M_EraseDataResponse(INT32 ch) // Delete the data if (erasecontext != 1) - G_ClearRecords(); + G_ClearRecords(clientGamedata); if (erasecontext != 0) - M_ClearSecrets(); + M_ClearSecrets(clientGamedata); if (erasecontext == 2) { - totalplaytime = 0; + clientGamedata->totalplaytime = 0; F_StartIntro(); } BwehHehHe(); diff --git a/src/m_random.c b/src/m_random.c index 3d0774a60..8b5138b9c 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -14,12 +14,11 @@ #include "doomdef.h" #include "doomtype.h" -#include "doomstat.h" // totalplaytime #include "m_random.h" #include "m_fixed.h" - +#include "m_cond.h" // totalplaytime // --------------------------- // RNG functions (not synched) @@ -252,5 +251,5 @@ void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed) */ UINT32 M_RandomizedSeed(void) { - return ((totalplaytime & 0xFFFF) << 16)|M_RandomFixed(); + return ((serverGamedata->totalplaytime & 0xFFFF) << 16) | M_RandomFixed(); } diff --git a/src/p_inter.c b/src/p_inter.c index 873448dcd..f2d20912f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -740,10 +740,22 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { if (demoplayback || (player->bot && player->bot != BOT_MPAI) || special->health <= 0 || special->health > MAXEMBLEMS) return; - emblemlocations[special->health-1].collected = true; - M_UpdateUnlockablesAndExtraEmblems(); - G_SaveGameData(); + if (emblemlocations[special->health-1].type == ET_SKIN) + { + INT32 skinnum = M_EmblemSkinNum(&emblemlocations[special->health-1]); + + if (player->skin != skinnum) + { + return; + } + } + + clientGamedata->collected[special->health-1] = serverGamedata->collected[special->health-1] = true; + + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + M_UpdateUnlockablesAndExtraEmblems(clientGamedata); + G_SaveGameData(clientGamedata); break; } diff --git a/src/p_mobj.c b/src/p_mobj.c index eeaf54776..6563e6f0a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12004,10 +12004,6 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) return false; // You already got this token break; - case MT_EMBLEM: - if (netgame || multiplayer) - return false; // Single player (You're next on my shit list) - break; default: break; } @@ -12175,15 +12171,20 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting mobj->color = (UINT16)emcolor; - validEmblem = !emblemlocations[j].collected; + validEmblem = true; - if (emblemlocations[j].type == ET_SKIN) + if (!netgame) { - INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]); + validEmblem = !serverGamedata->collected[j]; - if (players[0].skin != skinnum) + if (emblemlocations[j].type == ET_SKIN && !multiplayer) { - validEmblem = false; + INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]); + + if (players[0].skin != skinnum) + { + validEmblem = false; + } } } diff --git a/src/p_saveg.c b/src/p_saveg.c index 8c8a78322..c18319c69 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -47,6 +47,7 @@ UINT8 *save_p; #define ARCHIVEBLOCK_POBJS 0x7F928546 #define ARCHIVEBLOCK_THINKERS 0x7F37037C #define ARCHIVEBLOCK_SPECIALS 0x7F228378 +#define ARCHIVEBLOCK_EMBLEMS 0x7F4A5445 // Note: This cannot be bigger // than an UINT16 @@ -4339,6 +4340,8 @@ static void P_NetArchiveMisc(boolean resending) WRITEUINT32(save_p, hidetime); + WRITEUINT32(save_p, unlocktriggers); + // Is it paused? if (paused) WRITEUINT8(save_p, 0x2f); @@ -4437,6 +4440,8 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) hidetime = READUINT32(save_p); + unlocktriggers = READUINT32(save_p); + // Is it paused? if (READUINT8(save_p) == 0x2f) paused = true; @@ -4444,6 +4449,224 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) return true; } + +static inline void P_NetArchiveEmblems(void) +{ + gamedata_t *data = serverGamedata; + INT32 i, j; + UINT8 btemp; + INT32 curmare; + + WRITEUINT32(save_p, ARCHIVEBLOCK_EMBLEMS); + + // These should be synchronized before savegame loading by the wad files being the same anyway, + // but just in case, for now, we'll leave them here for testing. It would be very bad if they mismatch. + WRITEUINT8(save_p, (UINT8)savemoddata); + WRITEINT32(save_p, numemblems); + WRITEINT32(save_p, numextraemblems); + + // The rest of this is lifted straight from G_SaveGameData in g_game.c + // TODO: Optimize this to only send information about emblems, unlocks, etc. which actually exist + // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. + + WRITEUINT32(save_p, data->totalplaytime); + + // TODO put another cipher on these things? meh, I don't care... + for (i = 0; i < NUMMAPS; i++) + WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX)); + + // To save space, use one bit per collected/achieved/unlocked flag + for (i = 0; i < MAXEMBLEMS;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) + btemp |= (data->collected[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + for (i = 0; i < MAXEXTRAEMBLEMS;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) + btemp |= (data->extraCollected[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + for (i = 0; i < MAXUNLOCKABLES;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) + btemp |= (data->unlocked[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + for (i = 0; i < MAXCONDITIONSETS;) + { + btemp = 0; + for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) + btemp |= (data->achieved[j+i] << j); + WRITEUINT8(save_p, btemp); + i += j; + } + + WRITEUINT32(save_p, data->timesBeaten); + WRITEUINT32(save_p, data->timesBeatenWithEmeralds); + WRITEUINT32(save_p, data->timesBeatenUltimate); + + // Main records + for (i = 0; i < NUMMAPS; i++) + { + if (data->mainrecords[i]) + { + WRITEUINT32(save_p, data->mainrecords[i]->score); + WRITEUINT32(save_p, data->mainrecords[i]->time); + WRITEUINT16(save_p, data->mainrecords[i]->rings); + } + else + { + WRITEUINT32(save_p, 0); + WRITEUINT32(save_p, 0); + WRITEUINT16(save_p, 0); + } + } + + // NiGHTS records + for (i = 0; i < NUMMAPS; i++) + { + if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) + { + WRITEUINT8(save_p, 0); + continue; + } + + WRITEUINT8(save_p, data->nightsrecords[i]->nummares); + + for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) + { + WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]); + WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]); + WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); + } + } +} + +static inline void P_NetUnArchiveEmblems(void) +{ + gamedata_t *data = serverGamedata; + INT32 i, j; + UINT8 rtemp; + UINT32 recscore; + tic_t rectime; + UINT16 recrings; + UINT8 recmares; + INT32 curmare; + + if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS) + I_Error("Bad $$$.sav at archive block Emblems"); + + savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. + + if (numemblems != READINT32(save_p)) + I_Error("numemblems mismatch"); + if (numextraemblems != READINT32(save_p)) + I_Error("numextraemblems mismatch"); + + // This shouldn't happen, but if something really fucked up happens and you transfer + // the SERVER player's gamedata over your own CLIENT gamedata, + // then this prevents it from being saved over yours. + data->loaded = false; + + M_ClearSecrets(data); + G_ClearRecords(data); + + // The rest of this is lifted straight from G_LoadGameData in g_game.c + // TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist + // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. + + data->totalplaytime = READUINT32(save_p); + + // TODO put another cipher on these things? meh, I don't care... + for (i = 0; i < NUMMAPS; i++) + if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) + I_Error("Bad $$$.sav dearchiving Emblems"); + + // To save space, use one bit per collected/achieved/unlocked flag + for (i = 0; i < MAXEMBLEMS;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) + data->collected[j+i] = ((rtemp >> j) & 1); + i += j; + } + for (i = 0; i < MAXEXTRAEMBLEMS;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) + data->extraCollected[j+i] = ((rtemp >> j) & 1); + i += j; + } + for (i = 0; i < MAXUNLOCKABLES;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) + data->unlocked[j+i] = ((rtemp >> j) & 1); + i += j; + } + for (i = 0; i < MAXCONDITIONSETS;) + { + rtemp = READUINT8(save_p); + for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) + data->achieved[j+i] = ((rtemp >> j) & 1); + i += j; + } + + data->timesBeaten = READUINT32(save_p); + data->timesBeatenWithEmeralds = READUINT32(save_p); + data->timesBeatenUltimate = READUINT32(save_p); + + // Main records + for (i = 0; i < NUMMAPS; ++i) + { + recscore = READUINT32(save_p); + rectime = (tic_t)READUINT32(save_p); + recrings = READUINT16(save_p); + + if (recrings > 10000 || recscore > MAXSCORE) + I_Error("Bad $$$.sav dearchiving Emblems"); + + if (recscore || rectime || recrings) + { + G_AllocMainRecordData((INT16)i, data); + data->mainrecords[i]->score = recscore; + data->mainrecords[i]->time = rectime; + data->mainrecords[i]->rings = recrings; + } + } + + // Nights records + for (i = 0; i < NUMMAPS; ++i) + { + if ((recmares = READUINT8(save_p)) == 0) + continue; + + G_AllocNightsRecordData((INT16)i, data); + + for (curmare = 0; curmare < (recmares+1); ++curmare) + { + data->nightsrecords[i]->score[curmare] = READUINT32(save_p); + data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); + data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + + if (data->nightsrecords[i]->grade[curmare] > GRADE_S) + { + I_Error("Bad $$$.sav dearchiving Emblems"); + } + } + + data->nightsrecords[i]->nummares = recmares; + } +} + static inline void P_ArchiveLuabanksAndConsistency(void) { UINT8 i, banksinuse = NUM_LUABANKS; @@ -4507,6 +4730,7 @@ void P_SaveNetGame(boolean resending) CV_SaveNetVars(&save_p); P_NetArchiveMisc(resending); + P_NetArchiveEmblems(); // Assign the mobjnumber for pointer tracking for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) @@ -4559,6 +4783,7 @@ boolean P_LoadNetGame(boolean reloading) CV_LoadNetVars(&save_p); if (!P_NetUnArchiveMisc(reloading)) return false; + P_NetUnArchiveEmblems(); P_NetUnArchivePlayers(); if (gamestate == GS_LEVEL) { diff --git a/src/p_setup.c b/src/p_setup.c index c8b0936b8..70a2c0a8b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7460,7 +7460,7 @@ static void P_WriteLetter(void) { char *buf, *b; - if (!unlockables[28].unlocked) // pandora's box + if (!serverGamedata->unlocked[28]) // pandora's box return; if (modeattacking) @@ -7804,10 +7804,11 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) nextmapoverride = 0; skipstats = 0; - if (!(netgame || multiplayer || demoplayback)) - mapvisited[gamemap-1] |= MV_VISITED; - else if (netgame || multiplayer) - mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently + if (!demoplayback) + { + clientGamedata->mapvisited[gamemap-1] |= MV_VISITED; + serverGamedata->mapvisited[gamemap-1] |= MV_VISITED; + } levelloading = false; diff --git a/src/p_spec.c b/src/p_spec.c index aa04a723e..48185e908 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2937,7 +2937,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 441: // Trigger unlockable - if (!(netgame || multiplayer)) { INT32 trigid = line->args[0]; @@ -2948,10 +2947,12 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) unlocktriggers |= 1 << trigid; // Unlocked something? - if (M_UpdateUnlockablesAndExtraEmblems()) + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) { S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); // only save if unlocked something + G_SaveGameData(clientGamedata); // only save if unlocked something } } } diff --git a/src/p_tick.c b/src/p_tick.c index 0357258e8..b1fd367ed 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -675,7 +675,10 @@ void P_Ticker(boolean run) // Keep track of how long they've been playing! if (!demoplayback) // Don't increment if a demo is playing. - totalplaytime++; + { + clientGamedata->totalplaytime++; + serverGamedata->totalplaytime++; + } if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) P_DoSpecialStageStuff(); diff --git a/src/r_skins.c b/src/r_skins.c index e59e085b8..2c031ee85 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -194,7 +194,7 @@ UINT32 R_GetSkinAvailabilities(void) return 0; } - if (unlockables[i].unlocked) + if (clientGamedata->unlocked[i]) { response |= (1 << unlockShift); } @@ -242,11 +242,12 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) // Force 3. return true; } + if (playernum != -1 && players[playernum].bot) - { - //Force 4. - return true; - } + { + // Force 4. + return true; + } // We will now check if this skin is supposed to be locked or not. @@ -284,7 +285,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) else { // We want to check our global unlockables. - return (unlockables[unlockID].unlocked); + return (clientGamedata->unlocked[unlockID]); } } diff --git a/src/s_sound.c b/src/s_sound.c index 111b6ce25..ada1a0fd2 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1692,6 +1692,7 @@ UINT8 soundtestpage = 1; // boolean S_PrepareSoundTest(void) { + gamedata_t *data = clientGamedata; musicdef_t *def; INT32 pos = numsoundtestdefs = 0; @@ -1717,9 +1718,9 @@ boolean S_PrepareSoundTest(void) if (!(def->soundtestpage & soundtestpage)) continue; soundtestdefs[pos++] = def; - if (def->soundtestcond > 0 && !(mapvisited[def->soundtestcond-1] & MV_BEATEN)) + if (def->soundtestcond > 0 && !(data->mapvisited[def->soundtestcond-1] & MV_BEATEN)) continue; - if (def->soundtestcond < 0 && !M_Achieved(-1-def->soundtestcond)) + if (def->soundtestcond < 0 && !M_Achieved(-1-def->soundtestcond, data)) continue; def->allowed = true; } diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 67ee8d668..66eeffa30 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2352,7 +2352,7 @@ void I_Quit(void) #ifndef NONET D_SaveBan(); // save the ban list #endif - G_SaveGameData(); // Tails 12-08-2002 + G_SaveGameData(clientGamedata); // Tails 12-08-2002 //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. @@ -2436,7 +2436,7 @@ void I_Error(const char *error, ...) if (errorcount == 8) { M_SaveConfig(NULL); - G_SaveGameData(); + G_SaveGameData(clientGamedata); } if (errorcount > 20) { @@ -2469,7 +2469,7 @@ void I_Error(const char *error, ...) #ifndef NONET D_SaveBan(); // save the ban list #endif - G_SaveGameData(); // Tails 12-08-2002 + G_SaveGameData(clientGamedata); // Tails 12-08-2002 // Shutdown. Here might be other errors. if (demorecording) diff --git a/src/st_stuff.c b/src/st_stuff.c index 206c93273..1f0ca277f 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1697,7 +1697,7 @@ static void ST_drawNightsRecords(void) ST_DrawNightsOverlayNum((BASEVIDWIDTH/2 + 56)<lastmarescore, nightsnum, SKINCOLOR_AZURE); // If new record, say so! - if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1) <= stplyr->lastmarescore) + if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1, clientGamedata) <= stplyr->lastmarescore) { if (stplyr->texttimer & 16) V_DrawCenteredString(BASEVIDWIDTH/2, 184, V_YELLOWMAP|aflag, "* NEW RECORD *"); @@ -2563,8 +2563,11 @@ static void ST_doItemFinderIconsAndSound(void) emblems[stemblems++] = i; - if (!emblemlocations[i].collected) + if (!(clientGamedata->collected[i] && serverGamedata->collected[i])) + { + // It can be worth collecting again if the server doesn't have it. ++stunfound; + } if (stemblems >= 16) break; @@ -2723,7 +2726,7 @@ static void ST_overlayDrawer(void) ST_drawRaceHUD(); // Emerald Hunt Indicators - if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER)) + if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) ST_doItemFinderIconsAndSound(); else ST_doHuntIconsAndSound(); diff --git a/src/y_inter.c b/src/y_inter.c index 02d01233e..6e7d362a7 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1092,12 +1092,14 @@ void Y_Ticker(void) S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching! // Update when done with tally - if (!(netgame || multiplayer) && !demoplayback) + if (!demoplayback) { - if (M_UpdateUnlockablesAndExtraEmblems()) + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); + G_SaveGameData(clientGamedata); } } else if (!(intertic & 1)) @@ -1228,12 +1230,14 @@ void Y_Ticker(void) S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching! // Update when done with tally - if (!(netgame || multiplayer) && !demoplayback) + if (!demoplayback) { - if (M_UpdateUnlockablesAndExtraEmblems()) + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) S_StartSound(NULL, sfx_s3k68); - G_SaveGameData(); + G_SaveGameData(clientGamedata); } } else if (!(intertic & 1)) From 303d636f8e31358f63bb9b31ffef290fb74144b5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 10:58:18 -0500 Subject: [PATCH 125/478] Individual emblems mode --- src/deh_soc.c | 4 ++ src/doomstat.h | 3 ++ src/g_game.c | 1 + src/p_inter.c | 100 ++++++++++++++++++++++++++++++++++++++++++------- src/p_local.h | 2 + src/p_mobj.c | 48 ++++++------------------ src/p_setup.c | 2 +- src/st_stuff.c | 3 +- 8 files changed, 110 insertions(+), 53 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 81adbc9d2..f2f3e04b8 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3839,6 +3839,10 @@ void readmaincfg(MYFILE *f) { useContinues = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); } + else if (fastcmp(word, "SHAREEMBLEMS")) + { + shareEmblems = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); + } else if (fastcmp(word, "GAMEDATA")) { diff --git a/src/doomstat.h b/src/doomstat.h index 5875bd01f..a812cc304 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -543,9 +543,12 @@ extern UINT8 useBlackRock; extern UINT8 use1upSound; extern UINT8 maxXtraLife; // Max extra lives from rings + extern UINT8 useContinues; #define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0)))) +extern UINT8 shareEmblems; + extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations // For racing diff --git a/src/g_game.c b/src/g_game.c index 854bf9bbb..066b43cad 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -215,6 +215,7 @@ UINT8 ammoremovaltics = 2*TICRATE; UINT8 use1upSound = 0; UINT8 maxXtraLife = 2; // Max extra lives from rings UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes +UINT8 shareEmblems = 0; // Set to 1 to share all picked up emblems in multiplayer UINT8 introtoplay; UINT8 creditscutscene; diff --git a/src/p_inter.c b/src/p_inter.c index f2d20912f..02ae222e3 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -164,6 +164,62 @@ boolean P_CanPickupItem(player_t *player, boolean weapon) return true; } +boolean P_CanPickupEmblem(player_t *player, INT32 emblemID) +{ + emblem_t *emblem = NULL; + + if (emblemID < 0 || emblemID >= numemblems) + { + // Invalid emblem ID, can't pickup. + return false; + } + + emblem = &emblemlocations[emblemID]; + + if (demoplayback) + { + // Never collect emblems in replays. + return false; + } + + if (player->bot && player->bot != BOT_MPAI) + { + // Your little lap-dog can't grab these for you. + return false; + } + + if (emblem->type == ET_SKIN) + { + INT32 skinnum = M_EmblemSkinNum(emblem); + + if (player->skin != skinnum) + { + // Incorrect skin to pick up this emblem. + return false; + } + } + + return true; +} + +boolean P_EmblemWasCollected(INT32 emblemID) +{ + if (emblemID < 0 || emblemID >= numemblems) + { + // Invalid emblem ID, can't pickup. + return true; + } + + if (shareEmblems && !serverGamedata->collected[emblemID]) + { + // It can be worth collecting again if we're sharing emblems + // and the server doesn't have it. + return false; + } + + return clientGamedata->collected[emblemID]; +} + // // P_DoNightsScore // @@ -738,25 +794,41 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Secret emblem thingy case MT_EMBLEM: { - if (demoplayback || (player->bot && player->bot != BOT_MPAI) || special->health <= 0 || special->health > MAXEMBLEMS) - return; + mobj_t *spark = NULL; + boolean prevCollected; - if (emblemlocations[special->health-1].type == ET_SKIN) + if (!P_CanPickupEmblem(player, special->health - 1)) { - INT32 skinnum = M_EmblemSkinNum(&emblemlocations[special->health-1]); - - if (player->skin != skinnum) - { - return; - } + return; } - clientGamedata->collected[special->health-1] = serverGamedata->collected[special->health-1] = true; + prevCollected = P_EmblemWasCollected(special->health - 1); - M_SilentUpdateUnlockablesAndEmblems(serverGamedata); - M_UpdateUnlockablesAndExtraEmblems(clientGamedata); - G_SaveGameData(clientGamedata); - break; + if (((player - players) == serverplayer) || shareEmblems) + { + serverGamedata->collected[special->health-1] = true; + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + } + + if (P_IsLocalPlayer(player) || shareEmblems) + { + clientGamedata->collected[special->health-1] = true; + M_UpdateUnlockablesAndExtraEmblems(clientGamedata); + G_SaveGameData(clientGamedata); + } + + // This always spawns the object to prevent mobjnum issues, + // but makes the effect invisible to whoever it doesn't matter to. + spark = P_SpawnMobjFromMobj(special, 0, 0, 0, MT_SPARK); + if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) + { + S_StartSound(special, special->info->deathsound); + } + else + { + spark->flags2 |= MF2_DONTDRAW; + } + return; } // CTF Flags diff --git a/src/p_local.h b/src/p_local.h index cc060e4ee..3c84d6fe2 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -510,6 +510,8 @@ void P_ClearStarPost(INT32 postnum); void P_ResetStarposts(void); boolean P_CanPickupItem(player_t *player, boolean weapon); +boolean P_CanPickupEmblem(player_t *player, INT32 emblemID); +boolean P_EmblemWasCollected(INT32 emblemID); void P_DoNightsScore(player_t *player); void P_DoMatchSuper(player_t *player); diff --git a/src/p_mobj.c b/src/p_mobj.c index 6563e6f0a..f198a1a69 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9716,6 +9716,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) A_AttractChase(mobj); break; case MT_EMBLEM: + if (P_EmblemWasCollected(mobj->health - 1) || !P_CanPickupEmblem(&players[consoleplayer], mobj->health - 1)) + mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); + else + mobj->frame &= ~FF_TRANSMASK; + if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); break; @@ -12146,7 +12151,6 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) INT32 j; emblem_t* emblem = M_GetLevelEmblems(gamemap); skincolornum_t emcolor; - boolean validEmblem = true; while (emblem) { @@ -12171,47 +12175,19 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting mobj->color = (UINT16)emcolor; - validEmblem = true; + mobj->frame &= ~FF_TRANSMASK; - if (!netgame) + if (emblemlocations[j].type == ET_GLOBAL) { - validEmblem = !serverGamedata->collected[j]; - - if (emblemlocations[j].type == ET_SKIN && !multiplayer) + mobj->reactiontime = emblemlocations[j].var; + if (emblemlocations[j].var & GE_NIGHTSITEM) { - INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]); - - if (players[0].skin != skinnum) - { - validEmblem = false; - } + mobj->flags |= MF_NIGHTSITEM; + mobj->flags &= ~MF_SPECIAL; + mobj->flags2 |= MF2_DONTDRAW; } } - if (validEmblem == false) - { - P_UnsetThingPosition(mobj); - mobj->flags |= MF_NOCLIP; - mobj->flags &= ~MF_SPECIAL; - mobj->flags |= MF_NOBLOCKMAP; - mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); - P_SetThingPosition(mobj); - } - else - { - mobj->frame &= ~FF_TRANSMASK; - - if (emblemlocations[j].type == ET_GLOBAL) - { - mobj->reactiontime = emblemlocations[j].var; - if (emblemlocations[j].var & GE_NIGHTSITEM) - { - mobj->flags |= MF_NIGHTSITEM; - mobj->flags &= ~MF_SPECIAL; - mobj->flags2 |= MF2_DONTDRAW; - } - } - } return true; } diff --git a/src/p_setup.c b/src/p_setup.c index 70a2c0a8b..74645e877 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -876,7 +876,7 @@ static void P_SpawnMapThings(boolean spawnemblems) size_t i; mapthing_t *mt; - // Spawn axis points first so they are at the front of the list for fast searching. + // Spawn axis points first so they are at the front of the list for fast searching. for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { switch (mt->type) diff --git a/src/st_stuff.c b/src/st_stuff.c index 1f0ca277f..986b71219 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2563,9 +2563,8 @@ static void ST_doItemFinderIconsAndSound(void) emblems[stemblems++] = i; - if (!(clientGamedata->collected[i] && serverGamedata->collected[i])) + if (!P_EmblemWasCollected(i)) { - // It can be worth collecting again if the server doesn't have it. ++stunfound; } From 29c61fac88f88aa63474444f8fad73a3f9a49e13 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 10:58:34 -0500 Subject: [PATCH 126/478] Allow completion emblems in multiplayer --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 066b43cad..c26968ac0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3843,7 +3843,7 @@ static void G_UpdateVisited(gamedata_t *data, boolean silent) { boolean spec = G_IsSpecialStage(gamemap); // Update visitation flags? - if (!multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode + if (!demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode && !stagefailed) // Did not fail the stage { UINT8 earnedEmblems; From d7c5e16f6c0c82a9d8ca214b010094f65b5e61f3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 11:50:12 -0500 Subject: [PATCH 127/478] Play sound globally if emblems are shared --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 02ae222e3..b5266e09f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -822,7 +822,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) spark = P_SpawnMobjFromMobj(special, 0, 0, 0, MT_SPARK); if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) { - S_StartSound(special, special->info->deathsound); + S_StartSound((shareEmblems ? NULL : special), special->info->deathsound); } else { From 30f6ae6e5606bbdb6564558fef18918a127ac0f3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 13:48:59 -0500 Subject: [PATCH 128/478] Add read access to shareEmblems (as well as a few other MAINCFG variables that weren't) --- src/lua_script.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 9c7636ebe..75e9c29a0 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -306,6 +306,18 @@ int LUA_PushGlobals(lua_State *L, const char *word) lua_pushinteger(L, ammoremovaltics); return 1; // end timers + } else if (fastcmp(word,"use1upSound")) { + lua_pushinteger(L, use1upSound); + return 1; + } else if (fastcmp(word,"maxXtraLife")) { + lua_pushinteger(L, maxXtraLife); + return 1; + } else if (fastcmp(word,"useContinues")) { + lua_pushinteger(L, useContinues); + return 1; + } else if (fastcmp(word,"shareEmblems")) { + lua_pushinteger(L, shareEmblems); + return 1; } else if (fastcmp(word,"gametype")) { lua_pushinteger(L, gametype); return 1; From ffb76334ff37a0c5b2064450d0b895773515a4fe Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 13:58:23 -0500 Subject: [PATCH 129/478] Don't check time attack emblems in multiplayer (Maybe some day...) --- src/g_game.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index c26968ac0..b3dffd0e6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3869,7 +3869,8 @@ static void G_UpdateVisited(gamedata_t *data, boolean silent) if (silent) { - M_CheckLevelEmblems(data); + if (modeattacking) + M_CheckLevelEmblems(data); } else { From ffe591afeee2b48875235e86bc3480ce99850cb3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 17:36:02 -0500 Subject: [PATCH 130/478] Tie emblem spawning to Coop gametypes --- src/g_game.c | 6 +++++- src/p_mobj.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index b3dffd0e6..106682aee 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3843,16 +3843,19 @@ static void G_UpdateVisited(gamedata_t *data, boolean silent) { boolean spec = G_IsSpecialStage(gamemap); // Update visitation flags? - if (!demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode + if (!demoplayback + && G_CoopGametype() // Campaign mode && !stagefailed) // Did not fail the stage { UINT8 earnedEmblems; // Update visitation flags data->mapvisited[gamemap-1] |= MV_BEATEN; + // eh, what the hell if (ultimatemode) data->mapvisited[gamemap-1] |= MV_ULTIMATE; + // may seem incorrect but IS possible in what the main game uses as mp special stages, and nummaprings will be -1 in NiGHTS if (nummaprings > 0 && players[consoleplayer].rings >= nummaprings) { @@ -3860,6 +3863,7 @@ static void G_UpdateVisited(gamedata_t *data, boolean silent) if (modeattacking) data->mapvisited[gamemap-1] |= MV_PERFECTRA; } + if (!spec) { // not available to special stages because they can only really be done in one order in an unmodified game, so impossible for first six and trivial for seventh diff --git a/src/p_mobj.c b/src/p_mobj.c index f198a1a69..e79977c48 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12009,6 +12009,10 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) return false; // You already got this token break; + case MT_EMBLEM: + if (!G_CoopGametype()) + return false; // Gametype's not right + break; default: break; } From 122ddade61d60259f8b7d66fd27cb2c60ed44452 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 18:52:38 -0500 Subject: [PATCH 131/478] Draw level stats on pause & emblem hints menus in multiplayer --- src/m_menu.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 2214e6a6a..2d8db8b24 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -555,19 +555,22 @@ static menuitem_t MPauseMenu[] = {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_MapChange, 24}, + {IT_STRING | IT_CALL, NULL, "Emblem Hints...", M_EmblemHints, 32}, - {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,40}, - {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen - {IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen + {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,48}, - {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, - {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, - {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, - {IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone - {IT_STRING | IT_CALL, NULL, "Options", M_Options, 64}, + {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 56}, // splitscreen + {IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 64}, - {IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 80}, - {IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 88}, + {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 56}, // alone + {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 56}, + {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 56}, + {IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 64}, + + {IT_STRING | IT_CALL, NULL, "Options", M_Options, 72}, + + {IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 88}, + {IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 96}, }; typedef enum @@ -575,6 +578,7 @@ typedef enum mpause_addons = 0, mpause_scramble, mpause_switchmap, + mpause_hints, mpause_continue, mpause_psetupsplit, @@ -3747,12 +3751,10 @@ void M_StartControlPanel(void) if (splitscreen) { MPauseMenu[mpause_psetupsplit].status = MPauseMenu[mpause_psetupsplit2].status = IT_STRING | IT_CALL; - MPauseMenu[mpause_psetup].text = "Player 1 Setup"; } else { MPauseMenu[mpause_psetup].status = IT_STRING | IT_CALL; - MPauseMenu[mpause_psetup].text = "Player Setup"; if (G_GametypeHasTeams()) MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; @@ -3762,6 +3764,8 @@ void M_StartControlPanel(void) MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT; } + MPauseMenu[mpause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata) && G_CoopGametype()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + currentMenu = &MPauseDef; itemOn = mpause_continue; } @@ -4696,7 +4700,7 @@ static void M_DrawPauseMenu(void) { gamedata_t *data = clientGamedata; - if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)) + if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) { emblem_t *emblem_detail[3] = {NULL, NULL, NULL}; char emblem_text[3][20]; From fb5b8ce1be2a88c7afae55816c62e1928a5b88f5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 19:14:02 -0500 Subject: [PATCH 132/478] Show tab emblems in Coop --- src/hu_stuff.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index eceb6bbaf..091e2b2fb 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2862,18 +2862,6 @@ static void HU_DrawRankings(void) V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value)); } } - else if (gametyperankings[gametype] == GT_COOP) - { - INT32 totalscore = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - totalscore += players[i].score; - } - - V_DrawCenteredString(256, 8, 0, "TOTAL SCORE"); - V_DrawCenteredString(256, 16, 0, va("%u", totalscore)); - } else { if (circuitmap) @@ -3029,6 +3017,15 @@ static void HU_DrawNetplayCoopOverlay(void) V_DrawSmallScaledPatch(148, 6, 0, tokenicon); } + if (G_CoopGametype() && LUA_HudEnabled(hud_tabemblems)) + { + V_DrawCenteredString(256, 14, 0, "/"); + V_DrawString(256 + 4, 14, 0, va("%d", numemblems + numextraemblems)); + V_DrawRightAlignedString(256 - 4, 14, 0, va("%d", M_CountEmblems(clientGamedata))); + + V_DrawSmallScaledPatch(256 - (emblemicon->width / 4), 6, 0, emblemicon); + } + if (!LUA_HudEnabled(hud_coopemeralds)) return; From 87e468f365d58f012b62a3a0a7851d4bf26a9872 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 3 Mar 2022 10:26:04 -0500 Subject: [PATCH 133/478] Allow emerald hunt radar to function if emblem radar is on but all emblems have been collected. --- src/st_stuff.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 986b71219..7eab0442f 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2545,7 +2545,7 @@ static void ST_doHuntIconsAndSound(void) S_StartSound(NULL, sfx_emfind); } -static void ST_doItemFinderIconsAndSound(void) +static boolean ST_doItemFinderIconsAndSound(void) { INT32 emblems[16]; thinker_t *th; @@ -2556,6 +2556,12 @@ static void ST_doItemFinderIconsAndSound(void) INT32 interval = 0, newinterval = 0; INT32 soffset; + if (!(cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata))) + { + // Not unlocked, or not enabled. Use emerald hunt radar. + return false; + } + for (i = 0; i < numemblems; ++i) { if (emblemlocations[i].type > ET_SKIN || emblemlocations[i].level != gamemap) @@ -2573,7 +2579,10 @@ static void ST_doItemFinderIconsAndSound(void) } // Found all/none exist? Don't waste our time if (!stunfound) - return; + { + // Allow emerald hunt radar to function after they're all collected. + return false; + } // Scan thinkers to find emblem mobj with these ids for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) @@ -2607,6 +2616,8 @@ static void ST_doItemFinderIconsAndSound(void) if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0 && renderisnewtic) S_StartSound(NULL, sfx_emfind); + + return true; } // @@ -2725,9 +2736,7 @@ static void ST_overlayDrawer(void) ST_drawRaceHUD(); // Emerald Hunt Indicators - if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata)) - ST_doItemFinderIconsAndSound(); - else + if (!ST_doItemFinderIconsAndSound()); ST_doHuntIconsAndSound(); if(!P_IsLocalPlayer(stplyr)) From cb54b1e5ce1daee0cd5e20bb507eeb375cb6ff5e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 3 Mar 2022 10:26:36 -0500 Subject: [PATCH 134/478] Fix check that does LevelEmblems but not CompletionEmblems on startup --- src/m_cond.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/m_cond.c b/src/m_cond.c index 55f35830a..a54988f67 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -329,6 +329,7 @@ void M_SilentUpdateUnlockablesAndEmblems(gamedata_t *data) // Just in case they aren't to sync M_CheckUnlockConditions(data); M_CheckLevelEmblems(data); + M_CompletionEmblems(data); // Go through extra emblems for (i = 0; i < numextraemblems; ++i) From bc00b1335848e9827f492161baa14e2401dc45af Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 4 Mar 2022 11:29:02 -0500 Subject: [PATCH 135/478] Fix Emblem Radar detecting already collected emblems --- src/st_stuff.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 7eab0442f..42f1f89ec 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2577,6 +2577,7 @@ static boolean ST_doItemFinderIconsAndSound(void) if (stemblems >= 16) break; } + // Found all/none exist? Don't waste our time if (!stunfound) { @@ -2602,6 +2603,9 @@ static boolean ST_doItemFinderIconsAndSound(void) { if (mo2->health == emblems[i] + 1) { + if (P_EmblemWasCollected(emblems[i])) + break; + soffset = (i * 20) - ((stemblems - 1) * 10); newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); @@ -2736,7 +2740,7 @@ static void ST_overlayDrawer(void) ST_drawRaceHUD(); // Emerald Hunt Indicators - if (!ST_doItemFinderIconsAndSound()); + if (!ST_doItemFinderIconsAndSound()) ST_doHuntIconsAndSound(); if(!P_IsLocalPlayer(stplyr)) From 903a47966d62df8571250646bc11858fc1c222bd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 4 Mar 2022 11:31:41 -0500 Subject: [PATCH 136/478] Swap hints & level select on multiplayer pause menu This makes it consistent with SP's pause menu order. (Although admittedly I prefer how the other order looks.) --- src/m_menu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 2d8db8b24..0ad9183c7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -554,8 +554,8 @@ static menuitem_t MPauseMenu[] = { {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_MapChange, 24}, - {IT_STRING | IT_CALL, NULL, "Emblem Hints...", M_EmblemHints, 32}, + {IT_STRING | IT_CALL, NULL, "Emblem Hints...", M_EmblemHints, 24}, + {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_MapChange, 32}, {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,48}, @@ -577,8 +577,8 @@ typedef enum { mpause_addons = 0, mpause_scramble, - mpause_switchmap, mpause_hints, + mpause_switchmap, mpause_continue, mpause_psetupsplit, From 9b6a47783dbfbc32998e1a30ca5e9717b1fc2552 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 4 Mar 2022 12:32:23 -0500 Subject: [PATCH 137/478] Show the level select option used to start the level in the pause menu. Previously, level select only appeared in the SP pause menu if you load a complete save file. Now, entering the game through an Extras menu level select shows that level select. Simply makes it more convenient, as you don't need to exit to the main menu again whenever you want to get to another level from an unlocked level select. Tested all ways you can start a new map from the menu that I can think of (New Save File, Complete Save File, Mid-game Save File, several different Level Select types, custom Warp, Record Attack, Marathon, Tutorial), and could not smuggle wrong level selects into any. --- src/m_menu.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 0ad9183c7..a40eddae9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -241,6 +241,7 @@ static void M_EmblemHints(INT32 choice); static void M_HandleEmblemHints(INT32 choice); UINT32 hintpage = 1; static void M_HandleChecklist(INT32 choice); +static void M_PauseLevelSelect(INT32 choice); menu_t SR_MainDef, SR_UnlockChecklistDef; static UINT8 check_on; @@ -601,7 +602,7 @@ static menuitem_t SPauseMenu[] = // Pandora's Box will be shifted up if both options are available {IT_CALL | IT_STRING, NULL, "Pandora's Box...", M_PandorasBox, 16}, {IT_CALL | IT_STRING, NULL, "Emblem Hints...", M_EmblemHints, 24}, - {IT_CALL | IT_STRING, NULL, "Level Select...", M_LoadGameLevelSelect, 32}, + {IT_CALL | IT_STRING, NULL, "Level Select...", M_PauseLevelSelect, 32}, {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,48}, {IT_CALL | IT_STRING, NULL, "Retry", M_Retry, 56}, @@ -3713,7 +3714,7 @@ void M_StartControlPanel(void) } // We can always use level select though. :33 - SPauseMenu[spause_levelselect].status = (gamecomplete == 1) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_levelselect].status = (maplistoption != 0) ? (IT_STRING | IT_CALL) : (IT_DISABLED); // And emblem hints. SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); @@ -7138,7 +7139,6 @@ static void M_LevelSelectWarp(INT32 choice) } startmap = (INT16)(cv_nextmap.value); - fromlevelselect = true; if (fromloadgame) @@ -7662,6 +7662,26 @@ static void M_HandleEmblemHints(INT32 choice) } +static void M_PauseLevelSelect(INT32 choice) +{ + (void)choice; + + SP_LevelSelectDef.prevMenu = currentMenu; + levellistmode = LLM_LEVELSELECT; + + // maplistoption is NOT specified, so that this + // transfers the level select list from the menu + // used to enter the game to the pause menu. + + if (!M_PrepareLevelPlatter(-1, true)) + { + M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); + return; + } + + M_SetupNextMenu(&SP_LevelSelectDef); +} + /*static void M_DrawSkyRoom(void) { INT32 i, y = 0; @@ -8169,6 +8189,7 @@ INT32 ultimate_selectable = false; static void M_NewGame(void) { fromlevelselect = false; + maplistoption = 0; startmap = spstage_start; CV_SetValue(&cv_newgametype, GT_COOP); // Graue 09-08-2004 @@ -8180,6 +8201,7 @@ static void M_CustomWarp(INT32 choice) { INT32 ul = skyRoomMenuTranslations[choice-1]; + maplistoption = 0; startmap = (INT16)(unlockables[ul].variable); M_SetupChoosePlayer(0); @@ -8372,6 +8394,7 @@ static void M_StartTutorial(INT32 choice) M_ClearMenus(true); gamecomplete = 0; cursaveslot = 0; + maplistoption = 0; G_DeferedInitNew(false, G_BuildMapName(tutorialmap), 0, false, false); } @@ -8734,6 +8757,10 @@ static void M_LoadSelect(INT32 choice) { (void)choice; + // Reset here, if we want a level select + // M_LoadGameLevelSelect will set it for us. + maplistoption = 0; + if (saveSlotSelected == NOSAVESLOT) //last slot is play without saving { M_NewGame(); @@ -10674,6 +10701,7 @@ static void M_Marathon(INT32 choice) } fromlevelselect = false; + maplistoption = 0; startmap = spmarathon_start; CV_SetValue(&cv_newgametype, GT_COOP); // Graue 09-08-2004 From 897b81b8400522ec0d6a761d19bc2eb49c3e74f4 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 4 Mar 2022 15:28:11 -0500 Subject: [PATCH 138/478] Don't load game from pause level select without save slot --- src/m_menu.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index a40eddae9..ef149cec5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1829,6 +1829,10 @@ menu_t SP_LevelSelectDef = MAPPLATTERMENUSTYLE( MTREE4(MN_SP_MAIN, MN_SP_LOAD, MN_SP_PLAYER, MN_SP_LEVELSELECT), NULL, SP_LevelSelectMenu); +menu_t SP_PauseLevelSelectDef = MAPPLATTERMENUSTYLE( + MTREE4(MN_SP_MAIN, MN_SP_LOAD, MN_SP_PLAYER, MN_SP_LEVELSELECT), + NULL, SP_LevelSelectMenu); + menu_t SP_LevelStatsDef = { MTREE2(MN_SP_MAIN, MN_SP_LEVELSTATS), @@ -7129,6 +7133,7 @@ static void M_DestroyRobots(INT32 choice) static void M_LevelSelectWarp(INT32 choice) { boolean fromloadgame = (currentMenu == &SP_LevelSelectDef); + boolean frompause = (currentMenu == &SP_PauseLevelSelectDef); (void)choice; @@ -7146,7 +7151,20 @@ static void M_LevelSelectWarp(INT32 choice) else { cursaveslot = 0; - M_SetupChoosePlayer(0); + + if (frompause) + { + M_ClearMenus(true); + + D_MapChange(startmap, gametype, false, false, 1, false, fromlevelselect); + COM_BufAddText("dummyconsvar 1\n"); + + if (levelselect.rows) + Z_Free(levelselect.rows); + levelselect.rows = NULL; + } + else + M_SetupChoosePlayer(0); } } @@ -7666,7 +7684,7 @@ static void M_PauseLevelSelect(INT32 choice) { (void)choice; - SP_LevelSelectDef.prevMenu = currentMenu; + SP_PauseLevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; // maplistoption is NOT specified, so that this @@ -7679,7 +7697,7 @@ static void M_PauseLevelSelect(INT32 choice) return; } - M_SetupNextMenu(&SP_LevelSelectDef); + M_SetupNextMenu(&SP_PauseLevelSelectDef); } /*static void M_DrawSkyRoom(void) From d8f6ad217c02ab04d1dceb3e084ce2857a8ad886 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 5 Mar 2022 01:41:24 -0500 Subject: [PATCH 139/478] Don't give completion emblems when getting a game over in multiplayer (or any other kind of level reset) --- src/g_game.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index 106682aee..aafbdea76 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3153,6 +3153,9 @@ void G_DoReborn(INT32 playernum) if (resetlevel) { + // Don't give completion emblems for reloading the level... + stagefailed = true; + // reload the level from scratch if (countdowntimeup) { From 3b15d9b4fe0c3f9b3a0fc1b6d3d947f39ac65e5a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 6 Mar 2022 22:52:20 -0500 Subject: [PATCH 140/478] Make the level select behave more identically to G_LoadGame Noticed some oddities with D_MapChange here with very rarely not changing player position when the map is loaded. --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index ef149cec5..c025ae286 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7156,8 +7156,8 @@ static void M_LevelSelectWarp(INT32 choice) { M_ClearMenus(true); - D_MapChange(startmap, gametype, false, false, 1, false, fromlevelselect); - COM_BufAddText("dummyconsvar 1\n"); + G_DeferedInitNew(false, G_BuildMapName(startmap), cv_skin.value, false, fromlevelselect); // Not sure about using cv_skin here, but it seems fine in testing. + COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this if (levelselect.rows) Z_Free(levelselect.rows); From 9cce2195d4e41f537a911a1de9aa17a0caba0b91 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 7 Mar 2022 16:31:10 -0500 Subject: [PATCH 141/478] Make ShareEmblems more Top Down style --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index b5266e09f..750e9cc34 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -810,7 +810,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) M_SilentUpdateUnlockablesAndEmblems(serverGamedata); } - if (P_IsLocalPlayer(player) || shareEmblems) + if (P_IsLocalPlayer(player) /*|| shareEmblems*/) { clientGamedata->collected[special->health-1] = true; M_UpdateUnlockablesAndExtraEmblems(clientGamedata); From d751ad5cf262b0557a86a2e5d028cabce0c06909 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 9 Mar 2022 03:28:38 -0500 Subject: [PATCH 142/478] Remove "Multiplayer games can't unlock extras!" --- src/f_finale.c | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 4bb640d50..929a08eaf 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1642,37 +1642,27 @@ void F_GameEvaluationTicker(void) if (finalecount == 5*TICRATE) { - if (netgame || multiplayer) // modify this when we finally allow unlocking stuff in 2P + serverGamedata->timesBeaten++; + clientGamedata->timesBeaten++; + + if (ALL7EMERALDS(emeralds)) { - HU_SetCEchoFlags(V_YELLOWMAP|V_RETURN8); - HU_SetCEchoDuration(6); - HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Multiplayer games can't unlock extras!"); + serverGamedata->timesBeatenWithEmeralds++; + clientGamedata->timesBeatenWithEmeralds++; + } + + if (ultimatemode) + { + serverGamedata->timesBeatenUltimate++; + clientGamedata->timesBeatenUltimate++; + } + + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + + if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) S_StartSound(NULL, sfx_s3k68); - } - else - { - serverGamedata->timesBeaten++; - clientGamedata->timesBeaten++; - if (ALL7EMERALDS(emeralds)) - { - serverGamedata->timesBeatenWithEmeralds++; - clientGamedata->timesBeatenWithEmeralds++; - } - - if (ultimatemode) - { - serverGamedata->timesBeatenUltimate++; - clientGamedata->timesBeatenUltimate++; - } - - M_SilentUpdateUnlockablesAndEmblems(serverGamedata); - - if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata)) - S_StartSound(NULL, sfx_s3k68); - - G_SaveGameData(clientGamedata); - } + G_SaveGameData(clientGamedata); } } From 29f55471ddc163bddaa8bf5fba75ef4aec2fef63 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 12 Oct 2022 01:18:02 -0400 Subject: [PATCH 143/478] Fix instances reverted to old unlocked variable --- src/m_cheat.c | 6 +++--- src/p_spec.c | 10 +++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index 934779982..e370335f8 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -79,9 +79,9 @@ static UINT8 cheatf_warp(void) // Temporarily unlock stuff. G_SetUsedCheats(false); - unlockables[31].unlocked = true; // credits - unlockables[30].unlocked = true; // sound test - unlockables[28].unlocked = true; // level select + clientGamedata->unlocked[31] = true; // credits + clientGamedata->unlocked[30] = true; // sound test + clientGamedata->unlocked[28] = true; // level select // Refresh secrets menu existing. M_ClearMenus(true); diff --git a/src/p_spec.c b/src/p_spec.c index 48185e908..71ea145b9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1795,9 +1795,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { // Unlockable triggers required INT32 trigid = triggerline->args[1]; - if (netgame || multiplayer) - return false; - else if (trigid < 0 || trigid > 31) // limited by 32 bit variable + if (trigid < 0 || trigid > 31) // limited by 32 bit variable { CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid); return false; @@ -1810,14 +1808,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { // An unlockable itself must be unlocked! INT32 unlockid = triggerline->args[1]; - if (netgame || multiplayer) - return false; - else if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count + if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count { CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); return false; } - else if (!(unlockables[unlockid-1].unlocked)) + else if (!(serverGamedata->unlocked[unlockid-1])) return false; } break; From c1e641be437ae0e3e037f1f518466734ff47a8ab Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 31 Oct 2022 18:09:18 -0400 Subject: [PATCH 144/478] Improve emblem sharing conditions --- src/p_inter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 750e9cc34..bd3c15a45 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -796,6 +796,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { mobj_t *spark = NULL; boolean prevCollected; + const boolean isServer = ((player - players) == serverplayer); if (!P_CanPickupEmblem(player, special->health - 1)) { @@ -804,13 +805,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) prevCollected = P_EmblemWasCollected(special->health - 1); - if (((player - players) == serverplayer) || shareEmblems) + if (isServer || shareEmblems) { serverGamedata->collected[special->health-1] = true; M_SilentUpdateUnlockablesAndEmblems(serverGamedata); } - if (P_IsLocalPlayer(player) /*|| shareEmblems*/) + if (P_IsLocalPlayer(player) || (isServer && shareEmblems)) { clientGamedata->collected[special->health-1] = true; M_UpdateUnlockablesAndExtraEmblems(clientGamedata); From 645dd7d66278372c8fd9ec3357286887683c8f0b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 31 Oct 2022 18:26:41 -0400 Subject: [PATCH 145/478] Stop endlessly chasing NIGHTSPULL emblems --- src/p_inter.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index bd3c15a45..907388a8c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -798,6 +798,17 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) boolean prevCollected; const boolean isServer = ((player - players) == serverplayer); + if ((special->flags2 & MF2_NIGHTSPULL) + && (toucher == special->tracer)) + { + // Since collecting may not remove the object, + // we need to manually stop it from chasing. + P_SetTarget(&special->tracer, NULL); + special->flags2 &= ~MF2_NIGHTSPULL; + special->movefactor = 0; + special->momx = special->momy = special->momz = 0; + } + if (!P_CanPickupEmblem(player, special->health - 1)) { return; From cf228757a1c310cf0ba22452f2b5967f54a9583f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 31 Oct 2022 18:46:47 -0400 Subject: [PATCH 146/478] Emblems disappear on collection again, only for SP --- src/p_inter.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 907388a8c..5adfdb852 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -794,9 +794,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Secret emblem thingy case MT_EMBLEM: { - mobj_t *spark = NULL; - boolean prevCollected; - const boolean isServer = ((player - players) == serverplayer); + const boolean toucherIsServer = ((player - players) == serverplayer); + const boolean consoleIsServer = (consoleplayer == serverplayer); + boolean prevCollected = false; if ((special->flags2 & MF2_NIGHTSPULL) && (toucher == special->tracer)) @@ -816,31 +816,48 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) prevCollected = P_EmblemWasCollected(special->health - 1); - if (isServer || shareEmblems) + if (toucherIsServer || shareEmblems) { serverGamedata->collected[special->health-1] = true; M_SilentUpdateUnlockablesAndEmblems(serverGamedata); } - if (P_IsLocalPlayer(player) || (isServer && shareEmblems)) + if (P_IsLocalPlayer(player) || (consoleIsServer && shareEmblems)) { clientGamedata->collected[special->health-1] = true; M_UpdateUnlockablesAndExtraEmblems(clientGamedata); G_SaveGameData(clientGamedata); } - // This always spawns the object to prevent mobjnum issues, - // but makes the effect invisible to whoever it doesn't matter to. - spark = P_SpawnMobjFromMobj(special, 0, 0, 0, MT_SPARK); - if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) + if (netgame) { - S_StartSound((shareEmblems ? NULL : special), special->info->deathsound); + // This always spawns the object to prevent mobjnum issues, + // but makes the effect invisible to whoever it doesn't matter to. + mobj_t *spark = P_SpawnMobjFromMobj(special, 0, 0, 0, MT_SPARK); + + if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) + { + // Play the sound if it was collected. + S_StartSound((shareEmblems ? NULL : special), special->info->deathsound); + } + else + { + // We didn't collect it, make it invisible to us. + spark->flags2 |= MF2_DONTDRAW; + } + + return; } else { - spark->flags2 |= MF2_DONTDRAW; + if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) + { + // Disappear when collecting for local games. + break; + } + + return; } - return; } // CTF Flags From e06956a53b06872b4eb2c9bd184177c3b1322b77 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 16 Nov 2022 12:40:46 -0500 Subject: [PATCH 147/478] Fix skin-only emblems on emblem radar --- src/st_stuff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 42f1f89ec..59c50b168 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2569,7 +2569,7 @@ static boolean ST_doItemFinderIconsAndSound(void) emblems[stemblems++] = i; - if (!P_EmblemWasCollected(i)) + if (!P_EmblemWasCollected(i) && P_CanPickupEmblem(stplyr, i)) { ++stunfound; } @@ -2603,7 +2603,7 @@ static boolean ST_doItemFinderIconsAndSound(void) { if (mo2->health == emblems[i] + 1) { - if (P_EmblemWasCollected(emblems[i])) + if (P_EmblemWasCollected(emblems[i]) || !P_CanPickupEmblem(stplyr, emblems[i])) break; soffset = (i * 20) - ((stemblems - 1) * 10); From 35b676e313378a08d9369a503612ddd0d795832a Mon Sep 17 00:00:00 2001 From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com> Date: Fri, 2 Jun 2023 19:52:03 -0500 Subject: [PATCH 148/478] Fix Camera Interpolation Not Being Reset --- src/r_main.c | 63 +++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/r_main.c b/src/r_main.c index ebf7a28bf..55bb9c4ff 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1092,34 +1092,12 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y) void R_SetupFrame(player_t *player) { camera_t *thiscam; - boolean chasecam = false; - - if (splitscreen && player == &players[secondarydisplayplayer] - && player != &players[consoleplayer]) - { + boolean chasecam = R_ViewpointHasChasecam(player); + + if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]) thiscam = &camera2; - chasecam = (cv_chasecam2.value != 0); - R_SetViewContext(VIEWCONTEXT_PLAYER2); - } else - { thiscam = &camera; - chasecam = (cv_chasecam.value != 0); - R_SetViewContext(VIEWCONTEXT_PLAYER1); - } - - if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) - chasecam = true; // force chasecam on - else if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off - - if (chasecam && !thiscam->chase) - { - P_ResetCamera(player, thiscam); - thiscam->chase = true; - } - else if (!chasecam) - thiscam->chase = false; newview->sky = false; @@ -1348,11 +1326,37 @@ boolean R_ViewpointHasChasecam(player_t *player) { camera_t *thiscam; boolean chasecam = false; + boolean isplayer2 = (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]); - if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]) + if (isplayer2) { thiscam = &camera2; chasecam = (cv_chasecam2.value != 0); + } + else + { + thiscam = &camera; + chasecam = (cv_chasecam.value != 0); + } + + if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) + chasecam = true; // force chasecam on + else if (player->spectator) // no spectator chasecam + chasecam = false; // force chasecam off + + if (chasecam && !thiscam->chase) + { + P_ResetCamera(player, thiscam); + thiscam->chase = true; + } + else if (!chasecam && thiscam->chase) + { + P_ResetCamera(player, thiscam); + thiscam->chase = false; + } + + if (isplayer2) + { R_SetViewContext(VIEWCONTEXT_PLAYER2); if (thiscam->reset) { @@ -1362,8 +1366,6 @@ boolean R_ViewpointHasChasecam(player_t *player) } else { - thiscam = &camera; - chasecam = (cv_chasecam.value != 0); R_SetViewContext(VIEWCONTEXT_PLAYER1); if (thiscam->reset) { @@ -1372,11 +1374,6 @@ boolean R_ViewpointHasChasecam(player_t *player) } } - if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) - chasecam = true; // force chasecam on - else if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off - return chasecam; } From aa43aa7c8c0a1c17174b7b84ffa9e9a282f4264c Mon Sep 17 00:00:00 2001 From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com> Date: Sat, 3 Jun 2023 15:43:58 -0500 Subject: [PATCH 149/478] Call P_ResetCamera Upon Switching To/From an Away View Camera --- src/lua_playerlib.c | 4 ++++ src/p_spec.c | 5 +++++ src/p_user.c | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f7e14e78f..f79b1e45e 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -710,6 +710,10 @@ static int player_set(lua_State *L) if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->awayviewmobj, mo); + if (plr == &players[displayplayer]) + P_ResetCamera(plr, &camera); // reset p1 camera on p1 getting an awayviewmobj + else if (splitscreen && plr == &players[secondarydisplayplayer]) + P_ResetCamera(plr, &camera2); // reset p2 camera on p2 getting an awayviewmobj } else if (fastcmp(field,"awayviewtics")) { diff --git a/src/p_spec.c b/src/p_spec.c index aa04a723e..8489a227f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2669,6 +2669,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { P_SetTarget(&mo->player->awayviewmobj, altview); mo->player->awayviewtics = line->args[1]; + + if (mo->player == &players[displayplayer]) + P_ResetCamera(mo->player, &camera); // reset p1 camera on p1 getting an awayviewmobj + else if (splitscreen && mo->player == &players[secondarydisplayplayer]) + P_ResetCamera(mo->player, &camera2); // reset p2 camera on p2 getting an awayviewmobj } aim = udmf ? altview->spawnpoint->pitch : line->args[2]; diff --git a/src/p_user.c b/src/p_user.c index 0f3282da5..42fd0c310 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11507,15 +11507,24 @@ void P_PlayerThink(player_t *player) if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { P_SetTarget(&player->awayviewmobj, NULL); // remove awayviewmobj asap if invalid - player->awayviewtics = 0; // reset to zero + player->awayviewtics = 1; // reset to one, the below code will immediately set it to zero + } + + if (player->awayviewtics && player->awayviewtics != -1) + { + player->awayviewtics--; + if (!(player->awayviewtics)) + { + if (player == &players[displayplayer]) + P_ResetCamera(player, &camera); // reset p1 camera on p1 running out of awayviewtics + else if (splitscreen && player == &players[secondarydisplayplayer]) + P_ResetCamera(player, &camera2); // reset p2 camera on p2 running out of awayviewtics + } } if (player->flashcount) player->flashcount--; - if (player->awayviewtics && player->awayviewtics != -1) - player->awayviewtics--; - /// \note do this in the cheat code if (player->pflags & PF_NOCLIP) player->mo->flags |= MF_NOCLIP; From 7fa7653494dace135afd2fb84184c73bd51c1609 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 5 Jun 2023 13:54:09 -0400 Subject: [PATCH 150/478] Port increment_move radius clamps from Ring Racers Fixes inconsistencies with thin players, like with Liftoff Gantry's scale section, and with large characters colliding with steep slopes instead of going up them. --- src/p_map.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 27d5ea781..107048957 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2728,8 +2728,22 @@ increment_move fixed_t thingtop; floatok = false; - if (radius < MAXRADIUS/2) - radius = MAXRADIUS/2; + // This makes sure that there are no freezes from computing extremely small movements. + // Originally was MAXRADIUS/2, but that can cause some bad inconsistencies for small players. + radius = max(radius, thing->scale); + + // And we also have to prevent Big Large (tm) movements, as those can skip too far + // across slopes and cause us to fail step up checks on them when we otherwise shouldn't. + radius = min(radius, 16 * thing->scale); + + // (This whole "step" system is flawed; it was OK before, but the addition of slopes has + // exposed the problems with doing it like this. The right thing to do would be to use + // raycasting for physics to fix colliding in weird order, double-checking collisions, + // randomly colliding with slopes instead of going up them, etc. I don't feel like porting + // that from RR, as its both a huge sweeping change and still incomplete at the time of + // writing. Clamping radius to make our steps more precise will work just fine as long + // as you keep all of your crazy intentions to poke any of the other deep-rooted movement + // code to yourself. -- Sal 6/5/2023) do { if (thing->flags & MF_NOCLIP) { From 1cc870485dd93445bb4933be98dc58b1cdafee5b Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 15 Mar 2022 20:35:06 +0100 Subject: [PATCH 151/478] Increase unlockable limits: - MAXUNLOCKABLES from 32 to 80 - MAXEXTRAEMBLEMS from 16 to 48 - COMPAT_GAMEDATA_ID is used to account for the old values to prevent losing records. - Also fixes linedef actions 319/320. --- src/g_game.c | 32 +++++++++++++++++++++++--------- src/m_cond.h | 4 ++-- src/m_menu.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/r_skins.c | 3 ++- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index b23980044..47e670bfe 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4309,6 +4309,12 @@ void G_LoadGameData(gamedata_t *data) // Stop saving, until we successfully load it again. data->loaded = false; + // Backwards compat stuff + INT32 max_emblems = MAXEMBLEMS; + INT32 max_extraemblems = MAXEXTRAEMBLEMS; + INT32 max_unlockables = MAXUNLOCKABLES; + INT32 max_conditionsets = MAXCONDITIONSETS; + // Clear things so previously read gamedata doesn't transfer // to new gamedata G_ClearRecords(data); // main and nights records @@ -4325,7 +4331,7 @@ void G_LoadGameData(gamedata_t *data) { // Don't load, but do save. (essentially, reset) data->loaded = true; - return; + return; } length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer); @@ -4355,6 +4361,14 @@ void G_LoadGameData(gamedata_t *data) I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } +#ifdef COMPAT_GAMEDATA_ID // Account for lower MAXUNLOCKABLES and MAXEXTRAEMBLEMS from older versions + if (versionID == COMPAT_GAMEDATA_ID) + { + max_extraemblems = 16; + max_unlockables = 32; + } +#endif + data->totalplaytime = READUINT32(save_p); #ifdef COMPAT_GAMEDATA_ID @@ -4393,31 +4407,31 @@ void G_LoadGameData(gamedata_t *data) goto datacorrupt; // To save space, use one bit per collected/achieved/unlocked flag - for (i = 0; i < MAXEMBLEMS;) + for (i = 0; i < max_emblems;) { rtemp = READUINT8(save_p); - for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) + for (j = 0; j < 8 && j+i < max_emblems; ++j) data->collected[j+i] = ((rtemp >> j) & 1); i += j; } - for (i = 0; i < MAXEXTRAEMBLEMS;) + for (i = 0; i < max_extraemblems;) { rtemp = READUINT8(save_p); - for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) + for (j = 0; j < 8 && j+i < max_extraemblems; ++j) data->extraCollected[j+i] = ((rtemp >> j) & 1); i += j; } - for (i = 0; i < MAXUNLOCKABLES;) + for (i = 0; i < max_unlockables;) { rtemp = READUINT8(save_p); - for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) + for (j = 0; j < 8 && j+i < max_unlockables; ++j) data->unlocked[j+i] = ((rtemp >> j) & 1); i += j; } - for (i = 0; i < MAXCONDITIONSETS;) + for (i = 0; i < max_conditionsets;) { rtemp = READUINT8(save_p); - for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) + for (j = 0; j < 8 && j+i < max_conditionsets; ++j) data->achieved[j+i] = ((rtemp >> j) & 1); i += j; } diff --git a/src/m_cond.h b/src/m_cond.h index 6a3da79ec..95c3e1ebe 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -139,8 +139,8 @@ typedef struct // you seriously need to get a life. #define MAXCONDITIONSETS 128 #define MAXEMBLEMS 512 -#define MAXEXTRAEMBLEMS 16 -#define MAXUNLOCKABLES 32 +#define MAXEXTRAEMBLEMS 48 +#define MAXUNLOCKABLES 80 /** Time attack information, currently a very small structure. */ diff --git a/src/m_menu.c b/src/m_menu.c index f9f52335d..1c064d228 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -728,6 +728,54 @@ static menuitem_t SR_MainMenu[] = {IT_DISABLED, NULL, "", NULL, 0}, // Custom30 {IT_DISABLED, NULL, "", NULL, 0}, // Custom31 {IT_DISABLED, NULL, "", NULL, 0}, // Custom32 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom33 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom34 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom35 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom36 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom37 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom38 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom39 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom40 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom41 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom42 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom43 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom44 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom45 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom46 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom47 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom48 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom49 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom50 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom51 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom52 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom53 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom54 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom55 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom56 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom57 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom58 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom59 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom60 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom61 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom62 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom63 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom64 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom65 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom66 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom67 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom68 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom69 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom70 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom71 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom72 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom73 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom74 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom75 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom76 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom77 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom78 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom79 + {IT_DISABLED, NULL, "", NULL, 0}, // Custom80 }; diff --git a/src/r_skins.c b/src/r_skins.c index 2c031ee85..5bcde27b1 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -190,7 +190,8 @@ UINT32 R_GetSkinAvailabilities(void) // This crash is impossible to trigger as is, // but it could happen if MAXUNLOCKABLES is ever made higher than 32, // and someone makes a mod that has 33+ unlockable characters. :V - I_Error("Too many unlockable characters\n"); + // 2022/03/15: MAXUNLOCKABLES is now higher than 32 + I_Error("Too many unlockable characters! (maximum is 32)\n"); return 0; } From 99f09339866e3fc30d100d7353d0866a41ed0981 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 20 Mar 2022 14:10:18 +0100 Subject: [PATCH 152/478] Change how SR_MainMenu is initialized. --- src/m_menu.c | 93 ++++------------------------------------------------ 1 file changed, 7 insertions(+), 86 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1c064d228..51f5b7173 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -693,90 +693,10 @@ static menuitem_t SR_PandorasBox[] = }; // Sky Room Custom Unlocks -static menuitem_t SR_MainMenu[] = +static menuitem_t SR_MainMenu[MAXUNLOCKABLES+1] = { {IT_STRING|IT_SUBMENU,NULL, "Extras Checklist", &SR_UnlockChecklistDef, 0}, - {IT_DISABLED, NULL, "", NULL, 0}, // Custom1 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom2 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom3 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom4 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom5 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom6 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom7 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom8 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom9 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom10 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom11 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom12 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom13 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom14 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom15 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom16 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom17 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom18 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom19 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom20 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom21 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom22 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom23 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom24 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom25 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom26 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom27 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom28 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom29 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom30 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom31 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom32 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom33 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom34 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom35 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom36 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom37 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom38 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom39 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom40 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom41 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom42 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom43 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom44 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom45 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom46 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom47 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom48 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom49 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom50 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom51 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom52 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom53 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom54 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom55 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom56 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom57 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom58 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom59 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom60 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom61 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom62 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom63 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom64 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom65 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom66 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom67 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom68 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom69 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom70 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom71 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom72 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom73 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom74 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom75 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom76 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom77 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom78 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom79 - {IT_DISABLED, NULL, "", NULL, 0}, // Custom80 - + // The remaining (MAXUNLOCKABLES) items are now initialized in M_SecretsMenu }; static menuitem_t SR_LevelSelectMenu[] = @@ -8177,14 +8097,15 @@ static void M_SecretsMenu(INT32 choice) (void)choice; - // Clear all before starting - for (i = 1; i < MAXUNLOCKABLES+1; ++i) - SR_MainMenu[i].status = IT_DISABLED; + // Initialize array with placeholder entries + menuitem_t placeholder = {IT_DISABLED, NULL, "", NULL, 0}; + for (i = 1; i <= MAXUNLOCKABLES; ++i) + SR_MainMenu[i] = placeholder; memset(skyRoomMenuTranslations, 0, sizeof(skyRoomMenuTranslations)); memset(done, 0, sizeof(done)); - for (i = 1; i < MAXUNLOCKABLES+1; ++i) + for (i = 1; i <= MAXUNLOCKABLES; ++i) { curheight = UINT16_MAX; ul = -1; From d9937953ad1d1e57c08da5f684c7021dcd5a5663 Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 24 May 2023 12:54:19 +0200 Subject: [PATCH 153/478] Fix linedef type 319/320 again --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 71ea145b9..d1973d951 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1808,7 +1808,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { // An unlockable itself must be unlocked! INT32 unlockid = triggerline->args[1]; - if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count + if (unlockid <= 0 || unlockid > MAXUNLOCKABLES) // limited by unlockable count { CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); return false; From d8dd9884511b9be445dbd4211fbe94747d5cf9ff Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 16 Mar 2023 11:47:21 +0100 Subject: [PATCH 154/478] Don't cancel P_LinedefExecute early --- src/p_spec.c | 52 ++++++++++++++++++++++++---------------------------- src/p_spec.h | 2 +- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 71ea145b9..2f6e89c28 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1741,14 +1741,13 @@ static boolean P_ActivateLinedefExecutorsInSector(line_t *triggerline, mobj_t *a /** Used by P_LinedefExecute to check a trigger linedef's conditions * The linedef executor specials in the trigger linedef's sector are run if all conditions are met. - * Return false cancels P_LinedefExecute, this happens if a condition is not met. * * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. * \param actor Object initiating the action; should not be NULL. * \param caller Sector in which the action was started. May be NULL. * \sa P_ProcessLineSpecial, P_LinedefExecute */ -boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) +void P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) { INT16 specialtype = triggerline->special; @@ -1761,12 +1760,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (caller->triggerer == TO_PLAYEREMERALDS) { if (!(ALL7EMERALDS(emeralds))) - return false; + return; } else if (caller->triggerer == TO_PLAYERNIGHTS) { if (!P_CheckPlayerMareOld(triggerline)) - return false; + return; } } @@ -1774,22 +1773,22 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller { case 303: if (!P_CheckPlayerRings(triggerline, actor)) - return false; + return; break; case 305: if (!(actor && actor->player && actor->player->charability == triggerline->args[1])) - return false; + return; break; case 309: // Only red/blue team members can activate this. if (!(actor && actor->player)) - return false; + return; if (actor->player->ctfteam != ((triggerline->args[1] == TMT_RED) ? 1 : 2)) - return false; + return; break; case 314: if (!P_CheckPushables(triggerline, caller)) - return false; + return; break; case 317: { // Unlockable triggers required @@ -1798,10 +1797,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (trigid < 0 || trigid > 31) // limited by 32 bit variable { CONS_Debug(DBG_GAMELOGIC, "Unlockable trigger (sidedef %hu): bad trigger ID %d\n", triggerline->sidenum[0], trigid); - return false; + return; } else if (!(unlocktriggers & (1 << trigid))) - return false; + return; } break; case 319: @@ -1811,10 +1810,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (unlockid < 0 || unlockid >= MAXUNLOCKABLES) // limited by unlockable count { CONS_Debug(DBG_GAMELOGIC, "Unlockable check (sidedef %hu): bad unlockable ID %d\n", triggerline->sidenum[0], unlockid); - return false; + return; } else if (!(serverGamedata->unlocked[unlockid-1])) - return false; + return; } break; case 321: @@ -1822,7 +1821,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (triggerline->callcount > 0) { if (--triggerline->callcount > 0) - return false; + return; } break; case 323: // nightserize @@ -1830,15 +1829,15 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller case 327: // nights lap case 329: // nights egg capsule touch if (!P_CheckNightsTriggerLine(triggerline, actor)) - return false; + return; break; case 331: if (!(actor && actor->player)) - return false; + return; if (!triggerline->stringargs[0]) - return false; + return; if (!(stricmp(triggerline->stringargs[0], skins[actor->player->skin].name) == 0) ^ !!(triggerline->args[1])) - return false; + return; break; case 334: // object dye { @@ -1846,22 +1845,22 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color); if (!!(triggerline->args[1]) ^ (triggercolor != color)) - return false; + return; } break; case 337: // emerald check if (!P_CheckEmeralds(triggerline->args[2], (UINT16)triggerline->args[1])) - return false; + return; break; case 340: // NiGHTS mare if (!P_CheckPlayerMare(triggerline)) - return false; + return; break; case 343: // gravity check if (triggerline->args[1] == TMG_TEMPREVERSE && (!(actor->flags2 & MF2_OBJECTFLIP) != !(actor->player->powers[pw_gravityboots]))) - return false; + return; if ((triggerline->args[1] == TMG_NORMAL) != !(actor->eflags & MFE_VERTICALFLIP)) - return false; + return; break; default: break; @@ -1872,7 +1871,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller ///////////////////////////////// if (!P_ActivateLinedefExecutorsInSector(triggerline, actor, caller)) - return false; + return; // "Trigger on X calls" linedefs reset if args[2] is set if (specialtype == 321 && triggerline->args[2]) @@ -1905,8 +1904,6 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller && triggerline->args[0] == TMT_ONCE) triggerline->special = 0; } - - return true; } /** Runs a linedef executor. @@ -1959,8 +1956,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) if (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls continue; - if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) - return; // cancel P_LinedefExecute if function returns false + P_RunTriggerLinedef(&lines[masterline], actor, caller); // Even if it fails, there might be more linedefs to trigger } } diff --git a/src/p_spec.h b/src/p_spec.h index 91dfccb70..c8701749f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -527,7 +527,7 @@ boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec); void P_SwitchWeather(INT32 weathernum); -boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); +void P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); void P_RunNightserizeExecutors(mobj_t *actor); void P_RunDeNightserizeExecutors(mobj_t *actor); From b8a25ae53c5db7017adf2411ebae254ac2ed85c1 Mon Sep 17 00:00:00 2001 From: sphere Date: Tue, 13 Jun 2023 00:05:58 +0000 Subject: [PATCH 155/478] Add interpolation to hitbox viewer, tweak hitbox colors --- src/d_netcmd.c | 1 + src/hardware/hw_main.c | 19 ++++++++++++++++--- src/r_bbox.c | 14 ++++++++++++-- src/r_things.c | 22 ++++++++++++++++++---- src/screen.h | 2 +- 5 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 420621a77..0f859a569 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -873,6 +873,7 @@ void D_RegisterClientCommands(void) // screen.c CV_RegisterVar(&cv_fullscreen); CV_RegisterVar(&cv_renderview); + CV_RegisterVar(&cv_renderhitboxinterpolation); CV_RegisterVar(&cv_renderhitbox); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 09235ce62..e7550fd6e 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5686,9 +5686,22 @@ static void HWR_ProjectBoundingBox(mobj_t *thing) if (!R_ThingBoundingBoxVisible(thing)) return; + // uncapped/interpolation + boolean interpolate = cv_renderhitboxinterpolation.value; + interpmobjstate_t interp = {0}; + + if (R_UsingFrameInterpolation() && !paused && interpolate) + { + R_InterpolateMobjState(thing, rendertimefrac, &interp); + } + else + { + R_InterpolateMobjState(thing, FRACUNIT, &interp); + } + // transform the origin point - tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; - tr_y = FIXED_TO_FLOAT(thing->y) - gl_viewy; + tr_x = FIXED_TO_FLOAT(interp.x) - gl_viewx; + tr_y = FIXED_TO_FLOAT(interp.y) - gl_viewy; // rotation around vertical axis tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); @@ -5707,7 +5720,7 @@ static void HWR_ProjectBoundingBox(mobj_t *thing) vis->x2 = tr_x + rad; vis->z1 = tr_y - rad; vis->z2 = tr_y + rad; - vis->gz = FIXED_TO_FLOAT(thing->z); + vis->gz = FIXED_TO_FLOAT(interp.z); vis->gzt = vis->gz + FIXED_TO_FLOAT(thing->height); vis->mobj = thing; diff --git a/src/r_bbox.c b/src/r_bbox.c index b45007bb2..7ed693fd0 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -35,6 +35,7 @@ static CV_PossibleValue_t renderhitbox_cons_t[] = { {0}}; consvar_t cv_renderhitbox = CVAR_INIT ("renderhitbox", "Off", 0, renderhitbox_cons_t, NULL); +consvar_t cv_renderhitboxinterpolation = CVAR_INIT ("renderhitbox_interpolation", "On", CV_SAVE, CV_OnOff, NULL); struct bbox_col { INT32 x; @@ -179,12 +180,21 @@ UINT8 R_GetBoundingBoxColor(mobj_t *thing) if (flags & (MF_NOCLIPTHING)) return 7; // BFBFBF - if (flags & (MF_BOSS|MF_MISSILE|MF_ENEMY|MF_PAIN)) + if (flags & (MF_BOSS|MF_ENEMY)) return 35; // F00 + if (flags & (MF_MISSILE|MF_PAIN)) + return 54; // F70 + if (flags & (MF_SPECIAL|MF_MONITOR)) return 73; // FF0 + if (flags & MF_PUSHABLE) + return 112; // 0F0 + + if (flags & (MF_SPRING)) + return 181; // F0F + if (flags & (MF_NOCLIP)) return 152; // 00F @@ -299,7 +309,7 @@ boolean R_ThingBoundingBoxVisible(mobj_t *thing) return is_tangible(thing); case RENDERHITBOX_RINGS: - return (thing->type == MT_RING); + return (thing->type == MT_RING || thing->type == MT_BLUESPHERE); default: return false; diff --git a/src/r_things.c b/src/r_things.c index 7eecb041e..38237e5b3 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1436,19 +1436,33 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) return; } + // uncapped/interpolation + boolean interpolate = cv_renderhitboxinterpolation.value; + interpmobjstate_t interp = {0}; + + // do interpolation + if (R_UsingFrameInterpolation() && !paused && interpolate) + { + R_InterpolateMobjState(thing, rendertimefrac, &interp); + } + else + { + R_InterpolateMobjState(thing, FRACUNIT, &interp); + } + // 1--3 // | | // 0--2 // start in the (0) corner - gx = thing->x - thing->radius - viewx; - gy = thing->y - thing->radius - viewy; + gx = interp.x - thing->radius - viewx; + gy = interp.y - thing->radius - viewy; tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); // thing is behind view plane? // if parent vis is visible, ignore this - if (!vis && (tz < FixedMul(MINZ, thing->scale))) + if (!vis && (tz < FixedMul(MINZ, interp.scale))) { return; } @@ -1473,7 +1487,7 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) box->scale = 2 * FixedMul(thing->radius, viewsin); box->xscale = 2 * FixedMul(thing->radius, viewcos); - box->pz = thing->z; + box->pz = interp.z; box->pzt = box->pz + box->thingheight; box->gzt = box->pzt; diff --git a/src/screen.h b/src/screen.h index a0e04f85e..b021a419d 100644 --- a/src/screen.h +++ b/src/screen.h @@ -199,7 +199,7 @@ extern CV_PossibleValue_t cv_renderer_t[]; extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders -extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_renderhitbox, cv_fullscreen; +extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_renderhitbox, cv_renderhitboxinterpolation, cv_fullscreen; // wait for page flipping to end or not extern consvar_t cv_vidwait; extern consvar_t cv_timescale; From 37223f13f1319df814d683f86b3a61ff83b1b123 Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 13 Jun 2023 10:38:44 +0200 Subject: [PATCH 156/478] Remove debug print on generic item circle spawn --- src/p_mobj.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index e79977c48..a04351ae7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13687,7 +13687,6 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) UINT8 numitemtypes; if (!udmf) return; - CONS_Printf("Itemstring: %s\n", mthing->stringargs[0]); P_ParseItemTypes(mthing->stringargs[0], itemtypes, &numitemtypes); P_SpawnItemCircle(mthing, itemtypes, numitemtypes, mthing->args[0], mthing->args[1] << FRACBITS, bonustime); return; From 4d4910c918fde1a45bec771c84f688d8ef28cfc9 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Tue, 13 Jun 2023 14:02:19 +0200 Subject: [PATCH 157/478] Use 99999999 instead of 86400, make "MIN" 0 Nines might be more pleasing than an exact number for con_hudtime It'd be bad to make "MIN" in an old config suddenly start displaying lines for con_hudlines --- src/console.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/console.c b/src/console.c index b99b13720..d432bba72 100644 --- a/src/console.c +++ b/src/console.c @@ -125,12 +125,12 @@ static void CONS_backcolor_Change(void); static char con_buffer[CON_BUFFERSIZE]; // how many seconds the hud messages lasts on the screen -// CV_Unsigned can overflow when multiplied by TICRATE later, so let's use a 24-hour limit instead -static CV_PossibleValue_t hudtime_cons_t[] = {{0, "MIN"}, {86400, "MAX"}, {0, NULL}}; +// CV_Unsigned can overflow when multiplied by TICRATE later, so let's use a 3-year limit instead +static CV_PossibleValue_t hudtime_cons_t[] = {{0, "MIN"}, {99999999, "MAX"}, {0, NULL}}; static consvar_t cons_hudtime = CVAR_INIT ("con_hudtime", "5", CV_SAVE, hudtime_cons_t, NULL); // number of lines displayed on the HUD -static CV_PossibleValue_t hudlines_cons_t[] = {{1, "MIN"}, {MAXHUDLINES, "MAX"}, {0, "None"}, {0, NULL}}; +static CV_PossibleValue_t hudlines_cons_t[] = {{0, "MIN"}, {MAXHUDLINES, "MAX"}, {0, NULL}}; static consvar_t cons_hudlines = CVAR_INIT ("con_hudlines", "5", CV_CALL|CV_SAVE, hudlines_cons_t, CONS_hudlines_Change); // number of lines console move per frame From f921a9987d11dc805aaca944577ce982ed800068 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Tue, 13 Jun 2023 19:06:12 +0200 Subject: [PATCH 158/478] Interpolate models when scaling mobjs --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 6b1d0c6fc..38e8e8fc4 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1660,7 +1660,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) #endif // SRB2CBTODO: MD2 scaling support - finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); + finalscale *= FIXED_TO_FLOAT(interp.scale); p.flip = atransform.flip; #ifdef USE_FTRANSFORM_MIRROR From 5c3f66dc36371beb02f4e7a74ecca79fc7c5beed Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 13 Jun 2023 21:26:40 -0400 Subject: [PATCH 159/478] Remove "singletics" code in F_WriteText This was added in 2.1 for whatever reason. All instances of F_WriteText are already capped to the framerate properly by other means; so this code being present just makes timing differences between different netgame clients / other inaccuracies cause the text speed to slow down more than intended. --- src/f_finale.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index f529b4564..299a6a054 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -224,7 +224,6 @@ static INT32 cutscene_writeptr = 0; static INT32 cutscene_textcount = 0; static INT32 cutscene_textspeed = 0; static UINT8 cutscene_boostspeed = 0; -static tic_t cutscene_lasttextwrite = 0; // STJR Intro char stjrintro[9] = "STJRI000"; @@ -240,11 +239,6 @@ static UINT8 F_WriteText(void) { INT32 numtowrite = 1; const char *c; - tic_t ltw = I_GetTime(); - - if (cutscene_lasttextwrite == ltw) - return 1; // singletics prevention - cutscene_lasttextwrite = ltw; if (cutscene_boostspeed) { From bed7e434e7fbc340fa36424a4f1eb67848e8b164 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 10 Jun 2023 12:12:41 +0200 Subject: [PATCH 160/478] Add absolute z height flag for mapthings in UDMF --- src/doomdata.h | 4 ++++ src/p_mobj.c | 17 +++++++++-------- src/p_mobj.h | 2 +- src/p_setup.c | 2 ++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/doomdata.h b/src/doomdata.h index 4c5bdefaf..45cbb2557 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -62,6 +62,10 @@ enum #define MTF_AMBUSH 8 // Do not use bit five or after, as they are used for object z-offsets. +// Unless it's exclusive to UDMF. + +// Flag to use Z as absolute spawn height, ignoring the floor and ceiling. +#define MTF_ABSOLUTEZ 16 #if defined(_MSC_VER) #pragma pack(1) diff --git a/src/p_mobj.c b/src/p_mobj.c index a04351ae7..0622ff601 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11812,7 +11812,7 @@ void P_MovePlayerToStarpost(INT32 playernum) mapthing_t *huntemeralds[MAXHUNTEMERALDS]; INT32 numhuntemeralds; -fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale) +fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale, const boolean absolutez) { const subsector_t *ss = R_PointInSubsector(x, y); @@ -11822,9 +11822,9 @@ fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const f // Establish height. if (flip) - return P_GetSectorCeilingZAt(ss->sector, x, y) - dz - FixedMul(scale, offset + mobjinfo[mobjtype].height); + return (absolutez ? dz : P_GetSectorCeilingZAt(ss->sector, x, y) - dz) - FixedMul(scale, offset + mobjinfo[mobjtype].height); else - return P_GetSectorFloorZAt(ss->sector, x, y) + dz + FixedMul(scale, offset); + return (absolutez ? dz : P_GetSectorFloorZAt(ss->sector, x, y) + dz) + FixedMul(scale, offset); } fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y) @@ -11832,6 +11832,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt fixed_t dz = mthing->z << FRACBITS; // Base offset from the floor. fixed_t offset = 0; // Specific scaling object offset. boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); + boolean absolutez = !!(mthing->options & MTF_ABSOLUTEZ); switch (mobjtype) { @@ -11887,7 +11888,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt offset += mthing->args[0] ? 0 : 24*FRACUNIT; } - if (!(dz + offset)) // Snap to the surfaces when there's no offset set. + if (!(dz + offset) && !absolutez) // Snap to the surfaces when there's no offset set. { if (flip) return ONCEILINGZ; @@ -11895,7 +11896,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt return ONFLOORZ; } - return P_GetMobjSpawnHeight(mobjtype, x, y, dz, offset, flip, mthing->scale); + return P_GetMobjSpawnHeight(mobjtype, x, y, dz, offset, flip, mthing->scale, absolutez); } static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) @@ -13389,7 +13390,7 @@ void P_SpawnHoop(mapthing_t *mthing) vector4_t v, res; fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; - fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale); + fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale, !!(mthing->options & MTF_ABSOLUTEZ)); hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); hoopcenter->spawnpoint = mthing; @@ -13516,7 +13517,7 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numi itemtypes[r] = P_GetMobjtypeSubstitute(&dummything, itemtypes[r]); } } - z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale); + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale, !!(mthing->options & MTF_ABSOLUTEZ)); for (r = 0; r < numitems; r++) { @@ -13575,7 +13576,7 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n itemtypes[i] = P_GetMobjtypeSubstitute(&dummything, itemtypes[i]); } } - z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale); + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale, !!(mthing->options & MTF_ABSOLUTEZ)); for (i = 0; i < numitems; i++) { diff --git a/src/p_mobj.h b/src/p_mobj.h index 6717c4add..d7d660078 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -489,7 +489,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing); void P_MovePlayerToStarpost(INT32 playernum); void P_AfterPlayerSpawn(INT32 playernum); -fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale); +fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale, const boolean absolutez); fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y); mobj_t *P_SpawnMapThing(mapthing_t *mthing); diff --git a/src/p_setup.c b/src/p_setup.c index 74645e877..167e1baac 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1916,6 +1916,8 @@ static void ParseTextmapThingParameter(UINT32 i, const char *param, const char * // Flags else if (fastcmp(param, "flip") && fastcmp("true", val)) mapthings[i].options |= MTF_OBJECTFLIP; + else if (fastcmp(param, "absolutez") && fastcmp("true", val)) + mapthings[i].options |= MTF_ABSOLUTEZ; else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9) { From f416c6a98d78cefc6acd9d94396ce9e438f784c3 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 11 Jun 2023 12:42:10 +0200 Subject: [PATCH 161/478] Add absolute Z flag to MAPTHINGFLAG_LIST --- src/deh_lua.c | 4 ++-- src/deh_tables.c | 5 +++-- src/deh_tables.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 6dabb7e2d..a8bc63377 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -271,8 +271,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) } else if (fastncmp("MTF_", word, 4)) { p = word+4; - for (i = 0; i < 4; i++) - if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) { + for (i = 0; MAPTHINGFLAG_LIST[i]; i++) + if (fastcmp(p, MAPTHINGFLAG_LIST[i])) { CacheAndPushConstant(L, word, ((lua_Integer)1< \t"\1", // \2 extern const char *const MOBJEFLAG_LIST[]; -extern const char *const MAPTHINGFLAG_LIST[4]; +extern const char *const MAPTHINGFLAG_LIST[]; extern const char *const PLAYERFLAG_LIST[]; extern const char *const GAMETYPERULE_LIST[]; extern const char *const ML_LIST[]; // Linedef flags From 90d95d13057a24b1556dd43fa02dd8b78a8a0b7f Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 11 Jun 2023 13:40:18 +0200 Subject: [PATCH 162/478] Clean options field of binary-converted things --- src/p_mobj.c | 6 +++--- src/p_setup.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 0622ff601..b7295da4c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13390,7 +13390,7 @@ void P_SpawnHoop(mapthing_t *mthing) vector4_t v, res; fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; - fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale, !!(mthing->options & MTF_ABSOLUTEZ)); + fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale, mthing->options & MTF_ABSOLUTEZ); hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); hoopcenter->spawnpoint = mthing; @@ -13517,7 +13517,7 @@ static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numi itemtypes[r] = P_GetMobjtypeSubstitute(&dummything, itemtypes[r]); } } - z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale, !!(mthing->options & MTF_ABSOLUTEZ)); + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale, mthing->options & MTF_ABSOLUTEZ); for (r = 0; r < numitems; r++) { @@ -13576,7 +13576,7 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n itemtypes[i] = P_GetMobjtypeSubstitute(&dummything, itemtypes[i]); } } - z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale, !!(mthing->options & MTF_ABSOLUTEZ)); + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale, mthing->options & MTF_ABSOLUTEZ); for (i = 0; i < numitems; i++) { diff --git a/src/p_setup.c b/src/p_setup.c index 167e1baac..482330599 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -6681,7 +6681,6 @@ static void P_ConvertBinaryThingTypes(void) break; case 1704: //NiGHTS bumper mapthings[i].pitch = 30 * (((mapthings[i].options & 15) + 9) % 12); - mapthings[i].options &= ~0xF; break; case 1705: //Hoop case 1713: //Hoop (Customizable) @@ -6690,7 +6689,6 @@ static void P_ConvertBinaryThingTypes(void) mapthings[i].angle = (mapthings[i].extrainfo == 1) ? oldangle - 90 : ((oldangle >> 8)*360)/256; mapthings[i].pitch = (mapthings[i].extrainfo == 1) ? oldangle / 360 : ((oldangle & 255)*360)/256; mapthings[i].args[0] = (mapthings[i].type == 1705) ? 96 : (mapthings[i].options & 0xF)*16 + 32; - mapthings[i].options &= ~0xF; mapthings[i].type = 1713; break; } @@ -6718,6 +6716,9 @@ static void P_ConvertBinaryThingTypes(void) default: break; } + + // Clear binary thing height hacks, to prevent interfering with UDMF-only flags + mapthings[i].options &= 8; } } From 056d3dcf31ea2c7443b27eaf6982eda9f63d243f Mon Sep 17 00:00:00 2001 From: spherallic Date: Sun, 11 Jun 2023 17:15:36 +0200 Subject: [PATCH 163/478] Actually clear options field properly --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 482330599..66d7bff42 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -6718,7 +6718,7 @@ static void P_ConvertBinaryThingTypes(void) } // Clear binary thing height hacks, to prevent interfering with UDMF-only flags - mapthings[i].options &= 8; + mapthings[i].options &= 0xF; } } From 2f2de7d3d357e6e27369cb2fb51fceadefb1899b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 18 Jun 2023 18:05:16 +0200 Subject: [PATCH 164/478] Optimize field lookups in Lua metatables --- src/lua_consolelib.c | 56 +- src/lua_hudlib.c | 14 +- src/lua_infolib.c | 231 ++++++-- src/lua_maplib.c | 308 ++++++++--- src/lua_mobjlib.c | 235 +++++--- src/lua_playerlib.c | 1243 +++++++++++++++++++++++++++++++----------- src/lua_script.c | 36 +- src/lua_script.h | 4 +- src/lua_skinlib.c | 7 +- 9 files changed, 1597 insertions(+), 537 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index dcaad1416..1d15b3b14 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -566,27 +566,59 @@ static luaL_Reg lib[] = { {NULL, NULL} }; +enum cvar_e +{ + cvar_name, + cvar_defaultvalue, + cvar_flags, + cvar_value, + cvar_string, + cvar_changed, +}; + +static const char *const cvar_opt[] = { + "name", + "defaultvalue", + "flags", + "value", + "string", + "changed", + NULL, +}; + +static int cvar_fields_ref = LUA_NOREF; + static int cvar_get(lua_State *L) { consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); - const char *field = luaL_checkstring(L, 2); + enum cvar_e field = Lua_optoption(L, 2, -1, cvar_fields_ref); - if(fastcmp(field,"name")) + switch (field) + { + case cvar_name: lua_pushstring(L, cvar->name); - else if(fastcmp(field,"defaultvalue")) + break; + case cvar_defaultvalue: lua_pushstring(L, cvar->defaultvalue); - else if(fastcmp(field,"flags")) + break; + case cvar_flags: lua_pushinteger(L, cvar->flags); - else if(fastcmp(field,"value")) + break; + case cvar_value: lua_pushinteger(L, cvar->value); - else if(fastcmp(field,"string")) + break; + case cvar_string: lua_pushstring(L, cvar->string); - else if(fastcmp(field,"changed")) + break; + case cvar_changed: lua_pushboolean(L, cvar->changed); - else if (devparm) - return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field); - else - return 0; + break; + default: + if (devparm) + return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS, field); + else + return 0; + } return 1; } @@ -598,6 +630,8 @@ int LUA_ConsoleLib(lua_State *L) lua_setfield(L, -2, "__index"); lua_pop(L,1); + cvar_fields_ref = Lua_CreateFieldTable(L, cvar_opt); + // Set empty registry tables lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, "COM_Command"); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 1a0599757..c7f67e93a 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -95,6 +95,8 @@ static const char *const patch_opt[] = { "topoffset", NULL}; +static int patch_fields_ref = LUA_NOREF; + // alignment types for v.drawString enum align { align_left = 0, @@ -196,6 +198,8 @@ static const char *const camera_opt[] = { "momz", NULL}; +static int camera_fields_ref = LUA_NOREF; + static int lib_getHudInfo(lua_State *L) { UINT32 i; @@ -276,7 +280,7 @@ static int colormap_get(lua_State *L) static int patch_get(lua_State *L) { patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); - enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); + enum patch field = Lua_optoption(L, 2, -1, patch_fields_ref); // patches are invalidated when switching renderers if (!patch) { @@ -316,7 +320,7 @@ static int patch_set(lua_State *L) static int camera_get(lua_State *L) { camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA)); - enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt); + enum cameraf field = Lua_optoption(L, 2, -1, camera_fields_ref); // cameras should always be valid unless I'm a nutter I_Assert(cam != NULL); @@ -372,7 +376,7 @@ static int camera_get(lua_State *L) static int camera_set(lua_State *L) { camera_t *cam = *((camera_t **)luaL_checkudata(L, 1, META_CAMERA)); - enum cameraf field = luaL_checkoption(L, 2, NULL, camera_opt); + enum cameraf field = Lua_optoption(L, 2, -1, camera_fields_ref); I_Assert(cam != NULL); @@ -1444,6 +1448,8 @@ int LUA_HudLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + patch_fields_ref = Lua_CreateFieldTable(L, patch_opt); + luaL_newmetatable(L, META_CAMERA); lua_pushcfunction(L, camera_get); lua_setfield(L, -2, "__index"); @@ -1452,6 +1458,8 @@ int LUA_HudLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + camera_fields_ref = Lua_CreateFieldTable(L, camera_opt); + luaL_register(L, "hud", lib_hud); return 0; } diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 7388632d3..fb07ccebb 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1106,75 +1106,161 @@ static int lib_mobjinfolen(lua_State *L) return 1; } +enum mobjinfo_e +{ + mobjinfo_doomednum, + mobjinfo_spawnstate, + mobjinfo_spawnhealth, + mobjinfo_seestate, + mobjinfo_seesound, + mobjinfo_reactiontime, + mobjinfo_attacksound, + mobjinfo_painstate, + mobjinfo_painchance, + mobjinfo_painsound, + mobjinfo_meleestate, + mobjinfo_missilestate, + mobjinfo_deathstate, + mobjinfo_xdeathstate, + mobjinfo_deathsound, + mobjinfo_speed, + mobjinfo_radius, + mobjinfo_height, + mobjinfo_dispoffset, + mobjinfo_mass, + mobjinfo_damage, + mobjinfo_activesound, + mobjinfo_flags, + mobjinfo_raisestate, +}; + +const char *const mobjinfo_opt[] = { + "doomednum", + "spawnstate", + "spawnhealth", + "seestate", + "seesound", + "reactiontime", + "attacksound", + "painstate", + "painchance", + "painsound", + "meleestate", + "missilestate", + "deathstate", + "xdeathstate", + "deathsound", + "speed", + "radius", + "height", + "dispoffset", + "mass", + "damage", + "activesound", + "flags", + "raisestate", + NULL, +}; + +static int mobjinfo_fields_ref = LUA_NOREF; + // mobjinfo_t *, field -> number static int mobjinfo_get(lua_State *L) { mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO)); - const char *field = luaL_checkstring(L, 2); + enum mobjinfo_e field = luaL_checkoption(L, 2, mobjinfo_opt[0], mobjinfo_opt); I_Assert(info != NULL); I_Assert(info >= mobjinfo); - if (fastcmp(field,"doomednum")) + switch (field) + { + case mobjinfo_doomednum: lua_pushinteger(L, info->doomednum); - else if (fastcmp(field,"spawnstate")) + break; + case mobjinfo_spawnstate: lua_pushinteger(L, info->spawnstate); - else if (fastcmp(field,"spawnhealth")) + break; + case mobjinfo_spawnhealth: lua_pushinteger(L, info->spawnhealth); - else if (fastcmp(field,"seestate")) + break; + case mobjinfo_seestate: lua_pushinteger(L, info->seestate); - else if (fastcmp(field,"seesound")) + break; + case mobjinfo_seesound: lua_pushinteger(L, info->seesound); - else if (fastcmp(field,"reactiontime")) + break; + case mobjinfo_reactiontime: lua_pushinteger(L, info->reactiontime); - else if (fastcmp(field,"attacksound")) + break; + case mobjinfo_attacksound: lua_pushinteger(L, info->attacksound); - else if (fastcmp(field,"painstate")) + break; + case mobjinfo_painstate: lua_pushinteger(L, info->painstate); - else if (fastcmp(field,"painchance")) + break; + case mobjinfo_painchance: lua_pushinteger(L, info->painchance); - else if (fastcmp(field,"painsound")) + break; + case mobjinfo_painsound: lua_pushinteger(L, info->painsound); - else if (fastcmp(field,"meleestate")) + break; + case mobjinfo_meleestate: lua_pushinteger(L, info->meleestate); - else if (fastcmp(field,"missilestate")) + break; + case mobjinfo_missilestate: lua_pushinteger(L, info->missilestate); - else if (fastcmp(field,"deathstate")) + break; + case mobjinfo_deathstate: lua_pushinteger(L, info->deathstate); - else if (fastcmp(field,"xdeathstate")) + break; + case mobjinfo_xdeathstate: lua_pushinteger(L, info->xdeathstate); - else if (fastcmp(field,"deathsound")) + break; + case mobjinfo_deathsound: lua_pushinteger(L, info->deathsound); - else if (fastcmp(field,"speed")) + break; + case mobjinfo_speed: lua_pushinteger(L, info->speed); // sometimes it's fixed_t, sometimes it's not... - else if (fastcmp(field,"radius")) + break; + case mobjinfo_radius: lua_pushfixed(L, info->radius); - else if (fastcmp(field,"height")) + break; + case mobjinfo_height: lua_pushfixed(L, info->height); - else if (fastcmp(field,"dispoffset")) + break; + case mobjinfo_dispoffset: lua_pushinteger(L, info->dispoffset); - else if (fastcmp(field,"mass")) + break; + case mobjinfo_mass: lua_pushinteger(L, info->mass); - else if (fastcmp(field,"damage")) + break; + case mobjinfo_damage: lua_pushinteger(L, info->damage); - else if (fastcmp(field,"activesound")) + break; + case mobjinfo_activesound: lua_pushinteger(L, info->activesound); - else if (fastcmp(field,"flags")) + break; + case mobjinfo_flags: lua_pushinteger(L, info->flags); - else if (fastcmp(field,"raisestate")) + break; + case mobjinfo_raisestate: lua_pushinteger(L, info->raisestate); - else { + break; + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, info); lua_rawget(L, -2); if (!lua_istable(L, -1)) { // no extra values table - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2)); return 0; } - lua_getfield(L, -1, field); + lua_pushvalue(L, 2); // field name + lua_gettable(L, -2); if (lua_isnil(L, -1)) // no value for this field - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "mobjinfo_t", lua_tostring(L, 2)); + break; } return 1; } @@ -1183,7 +1269,7 @@ static int mobjinfo_get(lua_State *L) static int mobjinfo_set(lua_State *L) { mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO)); - const char *field = luaL_checkstring(L, 2); + enum mobjinfo_e field = Lua_optoption(L, 2, -1, mobjinfo_fields_ref); if (hud_running) return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!"); @@ -1193,55 +1279,81 @@ static int mobjinfo_set(lua_State *L) I_Assert(info != NULL); I_Assert(info >= mobjinfo); - if (fastcmp(field,"doomednum")) + switch (field) + { + case mobjinfo_doomednum: info->doomednum = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"spawnstate")) + break; + case mobjinfo_spawnstate: info->spawnstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"spawnhealth")) + break; + case mobjinfo_spawnhealth: info->spawnhealth = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"seestate")) + break; + case mobjinfo_seestate: info->seestate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"seesound")) + break; + case mobjinfo_seesound: info->seesound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"reactiontime")) + break; + case mobjinfo_reactiontime: info->reactiontime = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"attacksound")) + break; + case mobjinfo_attacksound: info->attacksound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"painstate")) + break; + case mobjinfo_painstate: info->painstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"painchance")) + break; + case mobjinfo_painchance: info->painchance = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"painsound")) + break; + case mobjinfo_painsound: info->painsound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"meleestate")) + break; + case mobjinfo_meleestate: info->meleestate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"missilestate")) + break; + case mobjinfo_missilestate: info->missilestate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"deathstate")) + break; + case mobjinfo_deathstate: info->deathstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"xdeathstate")) + break; + case mobjinfo_xdeathstate: info->xdeathstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"deathsound")) + break; + case mobjinfo_deathsound: info->deathsound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"speed")) + break; + case mobjinfo_speed: info->speed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"radius")) + break; + case mobjinfo_radius: info->radius = luaL_checkfixed(L, 3); - else if (fastcmp(field,"height")) + break; + case mobjinfo_height: info->height = luaL_checkfixed(L, 3); - else if (fastcmp(field,"dispoffset")) + break; + case mobjinfo_dispoffset: info->dispoffset = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"mass")) + break; + case mobjinfo_mass: info->mass = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"damage")) + break; + case mobjinfo_damage: info->damage = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"activesound")) + break; + case mobjinfo_activesound: info->activesound = luaL_checkinteger(L, 3); - else if (fastcmp(field,"flags")) + break; + case mobjinfo_flags: info->flags = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"raisestate")) + break; + case mobjinfo_raisestate: info->raisestate = luaL_checkinteger(L, 3); - else { + break; + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, info); @@ -1249,18 +1361,17 @@ static int mobjinfo_set(lua_State *L) if (lua_isnil(L, -1)) { // This index doesn't have a table for extra values yet, let's make one. lua_pop(L, 1); - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "mobjinfo_t", lua_tostring(L, 2)); lua_newtable(L); lua_pushlightuserdata(L, info); lua_pushvalue(L, -2); // ext value table lua_rawset(L, -4); // LREG_EXTVARS table } + lua_pushvalue(L, 2); // key lua_pushvalue(L, 3); // value to store - lua_setfield(L, -2, field); + lua_settable(L, -3); lua_pop(L, 2); } - //else - //return luaL_error(L, LUA_QL("mobjinfo_t") " has no field named " LUA_QS, field); return 0; } @@ -1788,6 +1899,8 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + mobjinfo_fields_ref = Lua_CreateFieldTable(L, mobjinfo_opt); + luaL_newmetatable(L, META_SKINCOLOR); lua_pushcfunction(L, skincolor_get); lua_setfield(L, -2, "__index"); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 898651520..dc477c81f 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -88,6 +88,8 @@ static const char *const sector_opt[] = { "gravity", NULL}; +static int sector_fields_ref = LUA_NOREF; + enum subsector_e { subsector_valid = 0, subsector_sector, @@ -104,6 +106,8 @@ static const char *const subsector_opt[] = { "polyList", NULL}; +static int subsector_fields_ref = LUA_NOREF; + enum line_e { line_valid = 0, line_v1, @@ -156,6 +160,8 @@ static const char *const line_opt[] = { "callcount", NULL}; +static int line_fields_ref = LUA_NOREF; + enum side_e { side_valid = 0, side_textureoffset, @@ -184,6 +190,8 @@ static const char *const side_opt[] = { "text", NULL}; +static int side_fields_ref = LUA_NOREF; + enum vertex_e { vertex_valid = 0, vertex_x, @@ -204,6 +212,8 @@ static const char *const vertex_opt[] = { "ceilingzset", NULL}; +static int vertex_fields_ref = LUA_NOREF; + enum ffloor_e { ffloor_valid = 0, ffloor_topheight, @@ -256,6 +266,8 @@ static const char *const ffloor_opt[] = { "bouncestrength", NULL}; +static int ffloor_fields_ref = LUA_NOREF; + #ifdef HAVE_LUA_SEGS enum seg_e { seg_valid = 0, @@ -285,6 +297,8 @@ static const char *const seg_opt[] = { "polyseg", NULL}; +static int seg_fields_ref = LUA_NOREF; + enum node_e { node_valid = 0, node_x, @@ -305,6 +319,8 @@ static const char *const node_opt[] = { "children", NULL}; +static int node_fields_ref = LUA_NOREF; + enum nodechild_e { nodechild_valid = 0, nodechild_right, @@ -356,6 +372,8 @@ static const char *const slope_opt[] = { "flags", NULL}; +static int slope_fields_ref = LUA_NOREF; + // shared by both vector2_t and vector3_t enum vector_e { vector_x = 0, @@ -575,7 +593,7 @@ static int sectorlines_num(lua_State *L) static int sector_get(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); - enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt); + enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref); INT16 i; if (!sector) @@ -697,7 +715,7 @@ static int sector_get(lua_State *L) static int sector_set(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); - enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt); + enum sector_e field = Lua_optoption(L, 2, sector_valid, sector_fields_ref); if (!sector) return luaL_error(L, "accessed sector_t doesn't exist anymore."); @@ -814,7 +832,7 @@ static int sector_num(lua_State *L) static int subsector_get(lua_State *L) { subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR)); - enum subsector_e field = luaL_checkoption(L, 2, subsector_opt[0], subsector_opt); + enum subsector_e field = Lua_optoption(L, 2, subsector_valid, subsector_fields_ref); if (!subsector) { @@ -898,7 +916,7 @@ static int linestringargs_len(lua_State *L) static int line_get(lua_State *L) { line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); - enum line_e field = luaL_checkoption(L, 2, line_opt[0], line_opt); + enum line_e field = Lua_optoption(L, 2, line_valid, line_fields_ref); if (!line) { @@ -1057,7 +1075,7 @@ static int sidenum_get(lua_State *L) static int side_get(lua_State *L) { side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); - enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt); + enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref); if (!side) { @@ -1110,7 +1128,7 @@ static int side_get(lua_State *L) static int side_set(lua_State *L) { side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); - enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt); + enum side_e field = Lua_optoption(L, 2, side_valid, side_fields_ref); if (!side) { @@ -1166,7 +1184,7 @@ static int side_num(lua_State *L) static int vertex_get(lua_State *L) { vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX)); - enum vertex_e field = luaL_checkoption(L, 2, vertex_opt[0], vertex_opt); + enum vertex_e field = Lua_optoption(L, 2, vertex_valid, vertex_fields_ref); if (!vertex) { @@ -1220,7 +1238,7 @@ static int vertex_num(lua_State *L) static int seg_get(lua_State *L) { seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); - enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt); + enum seg_e field = Lua_optoption(L, 2, seg_valid, seg_fields_ref); if (!seg) { @@ -1284,7 +1302,7 @@ static int seg_num(lua_State *L) static int node_get(lua_State *L) { node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); - enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt); + enum node_e field = Lua_optoption(L, 2, node_valid, node_fields_ref); if (!node) { @@ -1920,7 +1938,7 @@ static INT32 P_GetOldFOFFlags(ffloor_t *fflr) static int ffloor_get(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); - enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt); + enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref); INT16 i; if (!ffloor) @@ -2102,7 +2120,7 @@ static void P_SetOldFOFFlags(ffloor_t *fflr, oldffloortype_e oldflags) static int ffloor_set(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); - enum ffloor_e field = luaL_checkoption(L, 2, ffloor_opt[0], ffloor_opt); + enum ffloor_e field = Lua_optoption(L, 2, ffloor_valid, ffloor_fields_ref); if (!ffloor) return luaL_error(L, "accessed ffloor_t doesn't exist anymore."); @@ -2197,7 +2215,7 @@ static int ffloor_set(lua_State *L) static int slope_get(lua_State *L) { pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); - enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref); if (!slope) { @@ -2241,7 +2259,7 @@ static int slope_get(lua_State *L) static int slope_set(lua_State *L) { pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); - enum slope_e field = luaL_checkoption(L, 2, slope_opt[0], slope_opt); + enum slope_e field = Lua_optoption(L, 2, slope_valid, slope_fields_ref); if (!slope) return luaL_error(L, "accessed pslope_t doesn't exist anymore."); @@ -2405,110 +2423,258 @@ static int lib_nummapheaders(lua_State *L) // mapheader_t // ///////////////// +enum mapheaderinfo_e +{ + mapheaderinfo_lvlttl, + mapheaderinfo_subttl, + mapheaderinfo_actnum, + mapheaderinfo_typeoflevel, + mapheaderinfo_nextlevel, + mapheaderinfo_marathonnext, + mapheaderinfo_keywords, + mapheaderinfo_musname, + mapheaderinfo_mustrack, + mapheaderinfo_muspos, + mapheaderinfo_musinterfadeout, + mapheaderinfo_musintername, + mapheaderinfo_muspostbossname, + mapheaderinfo_muspostbosstrack, + mapheaderinfo_muspostbosspos, + mapheaderinfo_muspostbossfadein, + mapheaderinfo_musforcereset, + mapheaderinfo_forcecharacter, + mapheaderinfo_weather, + mapheaderinfo_skynum, + mapheaderinfo_skybox_scalex, + mapheaderinfo_skybox_scaley, + mapheaderinfo_skybox_scalez, + mapheaderinfo_interscreen, + mapheaderinfo_runsoc, + mapheaderinfo_scriptname, + mapheaderinfo_precutscenenum, + mapheaderinfo_cutscenenum, + mapheaderinfo_countdown, + mapheaderinfo_palette, + mapheaderinfo_numlaps, + mapheaderinfo_unlockrequired, + mapheaderinfo_levelselect, + mapheaderinfo_bonustype, + mapheaderinfo_ltzzpatch, + mapheaderinfo_ltzztext, + mapheaderinfo_ltactdiamond, + mapheaderinfo_maxbonuslives, + mapheaderinfo_levelflags, + mapheaderinfo_menuflags, + mapheaderinfo_selectheading, + mapheaderinfo_startrings, + mapheaderinfo_sstimer, + mapheaderinfo_ssspheres, + mapheaderinfo_gravity, +}; + +static const char *const mapheaderinfo_opt[] = { + "lvlttl", + "subttl", + "actnum", + "typeoflevel", + "nextlevel", + "marathonnext", + "keywords", + "musname", + "mustrack", + "muspos", + "musinterfadeout", + "musintername", + "muspostbossname", + "muspostbosstrack", + "muspostbosspos", + "muspostbossfadein", + "musforcereset", + "forcecharacter", + "weather", + "skynum", + "skybox_scalex", + "skybox_scaley", + "skybox_scalez", + "interscreen", + "runsoc", + "scriptname", + "precutscenenum", + "cutscenenum", + "countdown", + "palette", + "numlaps", + "unlockrequired", + "levelselect", + "bonustype", + "ltzzpatch", + "ltzztext", + "ltactdiamond", + "maxbonuslives", + "levelflags", + "menuflags", + "selectheading", + "startrings", + "sstimer", + "ssspheres", + "gravity", + NULL, +}; + +static int mapheaderinfo_fields_ref = LUA_NOREF; + static int mapheaderinfo_get(lua_State *L) { mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER)); - const char *field = luaL_checkstring(L, 2); + enum mapheaderinfo_e field = Lua_optoption(L, 2, -1, mapheaderinfo_fields_ref); INT16 i; - if (fastcmp(field,"lvlttl")) + + switch (field) + { + case mapheaderinfo_lvlttl: lua_pushstring(L, header->lvlttl); - else if (fastcmp(field,"subttl")) + break; + case mapheaderinfo_subttl: lua_pushstring(L, header->subttl); - else if (fastcmp(field,"actnum")) + break; + case mapheaderinfo_actnum: lua_pushinteger(L, header->actnum); - else if (fastcmp(field,"typeoflevel")) + break; + case mapheaderinfo_typeoflevel: lua_pushinteger(L, header->typeoflevel); - else if (fastcmp(field,"nextlevel")) + break; + case mapheaderinfo_nextlevel: lua_pushinteger(L, header->nextlevel); - else if (fastcmp(field,"marathonnext")) + break; + case mapheaderinfo_marathonnext: lua_pushinteger(L, header->marathonnext); - else if (fastcmp(field,"keywords")) + break; + case mapheaderinfo_keywords: lua_pushstring(L, header->keywords); - else if (fastcmp(field,"musname")) + break; + case mapheaderinfo_musname: lua_pushstring(L, header->musname); - else if (fastcmp(field,"mustrack")) + break; + case mapheaderinfo_mustrack: lua_pushinteger(L, header->mustrack); - else if (fastcmp(field,"muspos")) + break; + case mapheaderinfo_muspos: lua_pushinteger(L, header->muspos); - else if (fastcmp(field,"musinterfadeout")) + break; + case mapheaderinfo_musinterfadeout: lua_pushinteger(L, header->musinterfadeout); - else if (fastcmp(field,"musintername")) + break; + case mapheaderinfo_musintername: lua_pushstring(L, header->musintername); - else if (fastcmp(field,"muspostbossname")) + break; + case mapheaderinfo_muspostbossname: lua_pushstring(L, header->muspostbossname); - else if (fastcmp(field,"muspostbosstrack")) + break; + case mapheaderinfo_muspostbosstrack: lua_pushinteger(L, header->muspostbosstrack); - else if (fastcmp(field,"muspostbosspos")) + break; + case mapheaderinfo_muspostbosspos: lua_pushinteger(L, header->muspostbosspos); - else if (fastcmp(field,"muspostbossfadein")) + break; + case mapheaderinfo_muspostbossfadein: lua_pushinteger(L, header->muspostbossfadein); - else if (fastcmp(field,"musforcereset")) + break; + case mapheaderinfo_musforcereset: lua_pushinteger(L, header->musforcereset); - else if (fastcmp(field,"forcecharacter")) + break; + case mapheaderinfo_forcecharacter: lua_pushstring(L, header->forcecharacter); - else if (fastcmp(field,"weather")) + break; + case mapheaderinfo_weather: lua_pushinteger(L, header->weather); - else if (fastcmp(field,"skynum")) + break; + case mapheaderinfo_skynum: lua_pushinteger(L, header->skynum); - else if (fastcmp(field,"skybox_scalex")) + break; + case mapheaderinfo_skybox_scalex: lua_pushinteger(L, header->skybox_scalex); - else if (fastcmp(field,"skybox_scaley")) + break; + case mapheaderinfo_skybox_scaley: lua_pushinteger(L, header->skybox_scaley); - else if (fastcmp(field,"skybox_scalez")) + break; + case mapheaderinfo_skybox_scalez: lua_pushinteger(L, header->skybox_scalez); - else if (fastcmp(field,"interscreen")) { + break; + case mapheaderinfo_interscreen: for (i = 0; i < 8; i++) if (!header->interscreen[i]) break; lua_pushlstring(L, header->interscreen, i); - } else if (fastcmp(field,"runsoc")) + break; + case mapheaderinfo_runsoc: lua_pushstring(L, header->runsoc); - else if (fastcmp(field,"scriptname")) + break; + case mapheaderinfo_scriptname: lua_pushstring(L, header->scriptname); - else if (fastcmp(field,"precutscenenum")) + break; + case mapheaderinfo_precutscenenum: lua_pushinteger(L, header->precutscenenum); - else if (fastcmp(field,"cutscenenum")) + break; + case mapheaderinfo_cutscenenum: lua_pushinteger(L, header->cutscenenum); - else if (fastcmp(field,"countdown")) + break; + case mapheaderinfo_countdown: lua_pushinteger(L, header->countdown); - else if (fastcmp(field,"palette")) + break; + case mapheaderinfo_palette: lua_pushinteger(L, header->palette); - else if (fastcmp(field,"numlaps")) + break; + case mapheaderinfo_numlaps: lua_pushinteger(L, header->numlaps); - else if (fastcmp(field,"unlockrequired")) + break; + case mapheaderinfo_unlockrequired: lua_pushinteger(L, header->unlockrequired); - else if (fastcmp(field,"levelselect")) + break; + case mapheaderinfo_levelselect: lua_pushinteger(L, header->levelselect); - else if (fastcmp(field,"bonustype")) + break; + case mapheaderinfo_bonustype: lua_pushinteger(L, header->bonustype); - else if (fastcmp(field,"ltzzpatch")) + break; + case mapheaderinfo_ltzzpatch: lua_pushstring(L, header->ltzzpatch); - else if (fastcmp(field,"ltzztext")) + break; + case mapheaderinfo_ltzztext: lua_pushstring(L, header->ltzztext); - else if (fastcmp(field,"ltactdiamond")) + break; + case mapheaderinfo_ltactdiamond: lua_pushstring(L, header->ltactdiamond); - else if (fastcmp(field,"maxbonuslives")) + break; + case mapheaderinfo_maxbonuslives: lua_pushinteger(L, header->maxbonuslives); - else if (fastcmp(field,"levelflags")) + break; + case mapheaderinfo_levelflags: lua_pushinteger(L, header->levelflags); - else if (fastcmp(field,"menuflags")) + break; + case mapheaderinfo_menuflags: lua_pushinteger(L, header->menuflags); - else if (fastcmp(field,"selectheading")) + break; + case mapheaderinfo_selectheading: lua_pushstring(L, header->selectheading); - else if (fastcmp(field,"startrings")) + break; + case mapheaderinfo_startrings: lua_pushinteger(L, header->startrings); - else if (fastcmp(field, "sstimer")) + break; + case mapheaderinfo_sstimer: lua_pushinteger(L, header->sstimer); - else if (fastcmp(field, "ssspheres")) + break; + case mapheaderinfo_ssspheres: lua_pushinteger(L, header->ssspheres); - else if (fastcmp(field, "gravity")) + break; + case mapheaderinfo_gravity: lua_pushfixed(L, header->gravity); + break; // TODO add support for reading numGradedMares and grades - else { + default: // Read custom vars now // (note: don't include the "LUA." in your lua scripts!) UINT8 j = 0; - for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j); + for (;j < header->numCustomOptions && !fastcmp(lua_tostring(L, 2), header->customopts[j].option); ++j); if(j < header->numCustomOptions) lua_pushstring(L, header->customopts[j].value); @@ -2539,6 +2705,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + sector_fields_ref = Lua_CreateFieldTable(L, sector_opt); + luaL_newmetatable(L, META_SUBSECTOR); lua_pushcfunction(L, subsector_get); lua_setfield(L, -2, "__index"); @@ -2547,6 +2715,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + subsector_fields_ref = Lua_CreateFieldTable(L, subsector_opt); + luaL_newmetatable(L, META_LINE); lua_pushcfunction(L, line_get); lua_setfield(L, -2, "__index"); @@ -2555,6 +2725,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + line_fields_ref = Lua_CreateFieldTable(L, line_opt); + luaL_newmetatable(L, META_LINEARGS); lua_pushcfunction(L, lineargs_get); lua_setfield(L, -2, "__index"); @@ -2587,6 +2759,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + side_fields_ref = Lua_CreateFieldTable(L, side_opt); + luaL_newmetatable(L, META_VERTEX); lua_pushcfunction(L, vertex_get); lua_setfield(L, -2, "__index"); @@ -2595,6 +2769,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + vertex_fields_ref = Lua_CreateFieldTable(L, vertex_opt); + luaL_newmetatable(L, META_FFLOOR); lua_pushcfunction(L, ffloor_get); lua_setfield(L, -2, "__index"); @@ -2603,6 +2779,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + ffloor_fields_ref = Lua_CreateFieldTable(L, ffloor_opt); + #ifdef HAVE_LUA_SEGS luaL_newmetatable(L, META_SEG); lua_pushcfunction(L, seg_get); @@ -2612,6 +2790,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + seg_fields_ref = Lua_CreateFieldTable(L, seg_opt); + luaL_newmetatable(L, META_NODE); lua_pushcfunction(L, node_get); lua_setfield(L, -2, "__index"); @@ -2620,6 +2800,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + node_fields_ref = Lua_CreateFieldTable(L, node_opt); + luaL_newmetatable(L, META_NODEBBOX); //lua_pushcfunction(L, nodebbox_get); //lua_setfield(L, -2, "__index"); @@ -2646,6 +2828,8 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); + slope_fields_ref = Lua_CreateFieldTable(L, slope_opt); + luaL_newmetatable(L, META_VECTOR2); lua_pushcfunction(L, vector2_get); lua_setfield(L, -2, "__index"); @@ -2664,6 +2848,8 @@ int LUA_MapLib(lua_State *L) //lua_setfield(L, -2, "__len"); lua_pop(L, 1); + mapheaderinfo_fields_ref = Lua_CreateFieldTable(L, mapheaderinfo_opt); + LUA_PushTaggableObjectArray(L, "sectors", lib_iterateSectors, lib_getSector, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 5c2b8b4d3..09d244c91 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -179,10 +179,12 @@ static const char *const mobj_opt[] = { #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) +static int mobj_fields_ref = LUA_NOREF; + static int mobj_get(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt); + enum mobj_e field = Lua_optoption(L, 2, -1, mobj_fields_ref); lua_settop(L, 2); if (!mo || !ISINLEVEL) { @@ -467,7 +469,7 @@ static int mobj_get(lua_State *L) static int mobj_set(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - enum mobj_e field = Lua_optoption(L, 2, mobj_opt[0], mobj_opt); + enum mobj_e field = Lua_optoption(L, 2, mobj_valid, mobj_fields_ref); lua_settop(L, 3); INLEVEL @@ -876,14 +878,55 @@ static int thingstringargs_len(lua_State *L) return 1; } +enum mapthing_e { + mapthing_valid = 0, + mapthing_x, + mapthing_y, + mapthing_angle, + mapthing_pitch, + mapthing_roll, + mapthing_type, + mapthing_options, + mapthing_scale, + mapthing_z, + mapthing_extrainfo, + mapthing_tag, + mapthing_taglist, + mapthing_args, + mapthing_stringargs, + mapthing_mobj, +}; + +const char *const mapthing_opt[] = { + "valid", + "x", + "y", + "angle", + "pitch", + "roll", + "type", + "options", + "scale", + "z", + "extrainfo", + "tag", + "taglist", + "args", + "stringargs", + "mobj", + NULL, +}; + +static int mapthing_fields_ref = LUA_NOREF; + static int mapthing_get(lua_State *L) { mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); - const char *field = luaL_checkstring(L, 2); - lua_Integer number; + enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref); + lua_settop(L, 2); if (!mt) { - if (fastcmp(field,"valid")) { + if (field == mapthing_valid) { lua_pushboolean(L, false); return 1; } @@ -892,62 +935,71 @@ static int mapthing_get(lua_State *L) return 0; } - if (fastcmp(field,"valid")) { - lua_pushboolean(L, true); - return 1; - } else if(fastcmp(field,"x")) - number = mt->x; - else if(fastcmp(field,"y")) - number = mt->y; - else if(fastcmp(field,"angle")) - number = mt->angle; - else if(fastcmp(field,"pitch")) - number = mt->pitch; - else if(fastcmp(field,"roll")) - number = mt->roll; - else if(fastcmp(field,"type")) - number = mt->type; - else if(fastcmp(field,"options")) - number = mt->options; - else if(fastcmp(field,"scale")) - number = mt->scale; - else if(fastcmp(field,"z")) - number = mt->z; - else if(fastcmp(field,"extrainfo")) - number = mt->extrainfo; - else if(fastcmp(field,"tag")) - number = Tag_FGet(&mt->tags); - else if(fastcmp(field,"taglist")) + switch (field) { - LUA_PushUserdata(L, &mt->tags, META_TAGLIST); - return 1; + case mapthing_valid: + lua_pushboolean(L, true); + break; + case mapthing_x: + lua_pushinteger(L, mt->x); + break; + case mapthing_y: + lua_pushinteger(L, mt->y); + break; + case mapthing_angle: + lua_pushinteger(L, mt->angle); + break; + case mapthing_pitch: + lua_pushinteger(L, mt->pitch); + break; + case mapthing_roll: + lua_pushinteger(L, mt->roll); + break; + case mapthing_type: + lua_pushinteger(L, mt->type); + break; + case mapthing_options: + lua_pushinteger(L, mt->options); + break; + case mapthing_scale: + lua_pushinteger(L, mt->scale); + break; + case mapthing_z: + lua_pushinteger(L, mt->z); + break; + case mapthing_extrainfo: + lua_pushinteger(L, mt->extrainfo); + break; + case mapthing_tag: + lua_pushinteger(L, Tag_FGet(&mt->tags)); + break; + case mapthing_taglist: + LUA_PushUserdata(L, &mt->tags, META_TAGLIST); + break; + case mapthing_args: + LUA_PushUserdata(L, mt->args, META_THINGARGS); + break; + case mapthing_stringargs: + LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS); + break; + case mapthing_mobj: + LUA_PushUserdata(L, mt->mobj, META_MOBJ); + break; + default: + if (devparm) + return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); + else + return 0; } - else if(fastcmp(field,"args")) - { - LUA_PushUserdata(L, mt->args, META_THINGARGS); - return 1; - } - else if(fastcmp(field,"stringargs")) - { - LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS); - return 1; - } - else if(fastcmp(field,"mobj")) { - LUA_PushUserdata(L, mt->mobj, META_MOBJ); - return 1; - } else if (devparm) - return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); - else - return 0; - lua_pushinteger(L, number); return 1; } static int mapthing_set(lua_State *L) { mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); - const char *field = luaL_checkstring(L, 2); + enum mapthing_e field = Lua_optoption(L, 2, -1, mapthing_fields_ref); + lua_settop(L, 3); if (!mt) return luaL_error(L, "accessed mapthing_t doesn't exist anymore."); @@ -957,39 +1009,52 @@ static int mapthing_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter mapthing_t in CMD building code!"); - if(fastcmp(field,"x")) - mt->x = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"y")) - mt->y = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"angle")) - mt->angle = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"pitch")) - mt->pitch = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"roll")) - mt->roll = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"type")) - mt->type = (UINT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"options")) - mt->options = (UINT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"scale")) - mt->scale = luaL_checkfixed(L, 3); - else if(fastcmp(field,"z")) - mt->z = (INT16)luaL_checkinteger(L, 3); - else if(fastcmp(field,"extrainfo")) + switch (field) { - INT32 extrainfo = luaL_checkinteger(L, 3); - if (extrainfo & ~15) - return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); - mt->extrainfo = (UINT8)extrainfo; + case mapthing_x: + mt->x = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_y: + mt->y = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_angle: + mt->angle = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_pitch: + mt->pitch = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_roll: + mt->roll = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_type: + mt->type = (UINT16)luaL_checkinteger(L, 3); + break; + case mapthing_options: + mt->options = (UINT16)luaL_checkinteger(L, 3); + break; + case mapthing_scale: + mt->scale = luaL_checkfixed(L, 3); + break; + case mapthing_z: + mt->z = (INT16)luaL_checkinteger(L, 3); + break; + case mapthing_extrainfo: + INT32 extrainfo = luaL_checkinteger(L, 3); + if (extrainfo & ~15) + return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); + mt->extrainfo = (UINT8)extrainfo; + break; + case mapthing_tag: + Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3)); + break; + case mapthing_taglist: + return LUA_ErrSetDirectly(L, "mapthing_t", "taglist"); + case mapthing_mobj: + mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + break; + default: + return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); } - else if (fastcmp(field,"tag")) - Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3)); - else if (fastcmp(field,"taglist")) - return LUA_ErrSetDirectly(L, "mapthing_t", "taglist"); - else if(fastcmp(field,"mobj")) - mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); - else - return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); return 0; } @@ -1051,6 +1116,8 @@ int LUA_MobjLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + mobj_fields_ref = Lua_CreateFieldTable(L, mobj_opt); + luaL_newmetatable(L, META_THINGARGS); lua_pushcfunction(L, thingargs_get); lua_setfield(L, -2, "__index"); @@ -1078,6 +1145,8 @@ int LUA_MobjLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + mapthing_fields_ref = Lua_CreateFieldTable(L, mapthing_opt); + LUA_PushTaggableObjectArray(L, "mapthings", lib_iterateMapthings, lib_getMapthing, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f7e14e78f..1d06e081b 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -80,322 +80,764 @@ static int lib_lenPlayer(lua_State *L) return 1; } +enum player_e +{ + player_valid, + player_name, + player_realmo, + player_mo, + player_cmd, + player_playerstate, + player_camerascale, + player_shieldscale, + player_viewz, + player_viewheight, + player_deltaviewheight, + player_bob, + player_viewrollangle, + player_aiming, + player_drawangle, + player_rings, + player_spheres, + player_pity, + player_currentweapon, + player_ringweapons, + player_ammoremoval, + player_ammoremovaltimer, + player_ammoremovalweapon, + player_powers, + player_pflags, + player_panim, + player_flashcount, + player_flashpal, + player_skincolor, + player_skin, + player_availabilities, + player_score, + player_dashspeed, + player_normalspeed, + player_runspeed, + player_thrustfactor, + player_accelstart, + player_acceleration, + player_charability, + player_charability2, + player_charflags, + player_thokitem, + player_spinitem, + player_revitem, + player_followitem, + player_followmobj, + player_actionspd, + player_mindash, + player_maxdash, + player_jumpfactor, + player_height, + player_spinheight, + player_lives, + player_continues, + player_xtralife, + player_gotcontinue, + player_speed, + player_secondjump, + player_fly1, + player_scoreadd, + player_glidetime, + player_climbing, + player_deadtimer, + player_exiting, + player_homing, + player_dashmode, + player_skidtime, + player_cmomx, + player_cmomy, + player_rmomx, + player_rmomy, + player_numboxes, + player_totalring, + player_realtime, + player_laps, + player_ctfteam, + player_gotflag, + player_weapondelay, + player_tossdelay, + player_starpostx, + player_starposty, + player_starpostz, + player_starpostnum, + player_starposttime, + player_starpostangle, + player_starpostscale, + player_angle_pos, + player_old_angle_pos, + player_axis1, + player_axis2, + player_bumpertime, + player_flyangle, + player_drilltimer, + player_linkcount, + player_linktimer, + player_anotherflyangle, + player_nightstime, + player_drillmeter, + player_drilldelay, + player_bonustime, + player_capsule, + player_drone, + player_oldscale, + player_mare, + player_marelap, + player_marebonuslap, + player_marebegunat, + player_startedtime, + player_finishedtime, + player_lapbegunat, + player_lapstartedtime, + player_finishedspheres, + player_finishedrings, + player_marescore, + player_lastmarescore, + player_totalmarescore, + player_lastmare, + player_lastmarelap, + player_lastmarebonuslap, + player_totalmarelap, + player_totalmarebonuslap, + player_maxlink, + player_texttimer, + player_textvar, + player_lastsidehit, + player_lastlinehit, + player_losstime, + player_timeshit, + player_onconveyor, + player_awayviewmobj, + player_awayviewtics, + player_awayviewaiming, + player_spectator, + player_outofcoop, + player_bot, + player_botleader, + player_lastbuttons, + player_blocked, + player_jointime, + player_quittime, +#ifdef HWRENDER + player_fovadd, +#endif +}; + +static const char *const player_opt[] = { + "valid", + "name", + "realmo", + "mo", + "cmd", + "playerstate", + "camerascale", + "shieldscale", + "viewz", + "viewheight", + "deltaviewheight", + "bob", + "viewrollangle", + "aiming", + "drawangle", + "rings", + "spheres", + "pity", + "currentweapon", + "ringweapons", + "ammoremoval", + "ammoremovaltimer", + "ammoremovalweapon", + "powers", + "pflags", + "panim", + "flashcount", + "flashpal", + "skincolor", + "skin", + "availabilities", + "score", + "dashspeed", + "normalspeed", + "runspeed", + "thrustfactor", + "accelstart", + "acceleration", + "charability", + "charability2", + "charflags", + "thokitem", + "spinitem", + "revitem", + "followitem", + "followmobj", + "actionspd", + "mindash", + "maxdash", + "jumpfactor", + "height", + "spinheight", + "lives", + "continues", + "xtralife", + "gotcontinue", + "speed", + "secondjump", + "fly1", + "scoreadd", + "glidetime", + "climbing", + "deadtimer", + "exiting", + "homing", + "dashmode", + "skidtime", + "cmomx", + "cmomy", + "rmomx", + "rmomy", + "numboxes", + "totalring", + "realtime", + "laps", + "ctfteam", + "gotflag", + "weapondelay", + "tossdelay", + "starpostx", + "starposty", + "starpostz", + "starpostnum", + "starposttime", + "starpostangle", + "starpostscale", + "angle_pos", + "old_angle_pos", + "axis1", + "axis2", + "bumpertime", + "flyangle", + "drilltimer", + "linkcount", + "linktimer", + "anotherflyangle", + "nightstime", + "drillmeter", + "drilldelay", + "bonustime", + "capsule", + "drone", + "oldscale", + "mare", + "marelap", + "marebonuslap", + "marebegunat", + "startedtime", + "finishedtime", + "lapbegunat", + "lapstartedtime", + "finishedspheres", + "finishedrings", + "marescore", + "lastmarescore", + "totalmarescore", + "lastmare", + "lastmarelap", + "lastmarebonuslap", + "totalmarelap", + "totalmarebonuslap", + "maxlink", + "texttimer", + "textvar", + "lastsidehit", + "lastlinehit", + "losstime", + "timeshit", + "onconveyor", + "awayviewmobj", + "awayviewtics", + "awayviewaiming", + "spectator", + "outofcoop", + "bot", + "botleader", + "lastbuttons", + "blocked", + "jointime", + "quittime", +#ifdef HWRENDER + "fovadd", +#endif + NULL, +}; + +static int player_fields_ref = LUA_NOREF; + static int player_get(lua_State *L) { player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - const char *field = luaL_checkstring(L, 2); + enum player_e field = Lua_optoption(L, 2, -1, player_fields_ref); + lua_settop(L, 2); - if (!plr) { - if (fastcmp(field,"valid")) { + if (!plr) + { + if (field == player_valid) + { lua_pushboolean(L, false); return 1; } return LUA_ErrInvalid(L, "player_t"); } - if (fastcmp(field,"valid")) + switch (field) + { + case player_valid: lua_pushboolean(L, true); - else if (fastcmp(field,"name")) + break; + case player_name: lua_pushstring(L, player_names[plr-players]); - else if (fastcmp(field,"realmo")) + break; + case player_realmo: LUA_PushUserdata(L, plr->mo, META_MOBJ); + break; // Kept for backward-compatibility // Should be fixed to work like "realmo" later - else if (fastcmp(field,"mo")) - { + case player_mo: if (plr->spectator) lua_pushnil(L); else LUA_PushUserdata(L, plr->mo, META_MOBJ); - } - else if (fastcmp(field,"cmd")) + break; + case player_cmd: LUA_PushUserdata(L, &plr->cmd, META_TICCMD); - else if (fastcmp(field,"playerstate")) + break; + case player_playerstate: lua_pushinteger(L, plr->playerstate); - else if (fastcmp(field,"camerascale")) + break; + case player_camerascale: lua_pushfixed(L, plr->camerascale); - else if (fastcmp(field,"shieldscale")) + break; + case player_shieldscale: lua_pushfixed(L, plr->shieldscale); - else if (fastcmp(field,"viewz")) + break; + case player_viewz: lua_pushfixed(L, plr->viewz); - else if (fastcmp(field,"viewheight")) + break; + case player_viewheight: lua_pushfixed(L, plr->viewheight); - else if (fastcmp(field,"deltaviewheight")) + break; + case player_deltaviewheight: lua_pushfixed(L, plr->deltaviewheight); - else if (fastcmp(field,"bob")) + break; + case player_bob: lua_pushfixed(L, plr->bob); - else if (fastcmp(field,"viewrollangle")) + break; + case player_viewrollangle: lua_pushangle(L, plr->viewrollangle); - else if (fastcmp(field,"aiming")) + break; + case player_aiming: lua_pushangle(L, plr->aiming); - else if (fastcmp(field,"drawangle")) + break; + case player_drawangle: lua_pushangle(L, plr->drawangle); - else if (fastcmp(field,"rings")) + break; + case player_rings: lua_pushinteger(L, plr->rings); - else if (fastcmp(field,"spheres")) + break; + case player_spheres: lua_pushinteger(L, plr->spheres); - else if (fastcmp(field,"pity")) + break; + case player_pity: lua_pushinteger(L, plr->pity); - else if (fastcmp(field,"currentweapon")) + break; + case player_currentweapon: lua_pushinteger(L, plr->currentweapon); - else if (fastcmp(field,"ringweapons")) + break; + case player_ringweapons: lua_pushinteger(L, plr->ringweapons); - else if (fastcmp(field,"ammoremoval")) + break; + case player_ammoremoval: lua_pushinteger(L, plr->ammoremoval); - else if (fastcmp(field,"ammoremovaltimer")) + break; + case player_ammoremovaltimer: lua_pushinteger(L, plr->ammoremovaltimer); - else if (fastcmp(field,"ammoremovalweapon")) + break; + case player_ammoremovalweapon: lua_pushinteger(L, plr->ammoremovalweapon); - else if (fastcmp(field,"powers")) + break; + case player_powers: LUA_PushUserdata(L, plr->powers, META_POWERS); - else if (fastcmp(field,"pflags")) + break; + case player_pflags: lua_pushinteger(L, plr->pflags); - else if (fastcmp(field,"panim")) + break; + case player_panim: lua_pushinteger(L, plr->panim); - else if (fastcmp(field,"flashcount")) + break; + case player_flashcount: lua_pushinteger(L, plr->flashcount); - else if (fastcmp(field,"flashpal")) + break; + case player_flashpal: lua_pushinteger(L, plr->flashpal); - else if (fastcmp(field,"skincolor")) + break; + case player_skincolor: lua_pushinteger(L, plr->skincolor); - else if (fastcmp(field,"skin")) + break; + case player_skin: lua_pushinteger(L, plr->skin); - else if (fastcmp(field,"availabilities")) + break; + case player_availabilities: lua_pushinteger(L, plr->availabilities); - else if (fastcmp(field,"score")) + break; + case player_score: lua_pushinteger(L, plr->score); - else if (fastcmp(field,"dashspeed")) + break; + case player_dashspeed: lua_pushfixed(L, plr->dashspeed); - else if (fastcmp(field,"normalspeed")) + break; + case player_normalspeed: lua_pushfixed(L, plr->normalspeed); - else if (fastcmp(field,"runspeed")) + break; + case player_runspeed: lua_pushfixed(L, plr->runspeed); - else if (fastcmp(field,"thrustfactor")) + break; + case player_thrustfactor: lua_pushinteger(L, plr->thrustfactor); - else if (fastcmp(field,"accelstart")) + break; + case player_accelstart: lua_pushinteger(L, plr->accelstart); - else if (fastcmp(field,"acceleration")) + break; + case player_acceleration: lua_pushinteger(L, plr->acceleration); - else if (fastcmp(field,"charability")) + break; + case player_charability: lua_pushinteger(L, plr->charability); - else if (fastcmp(field,"charability2")) + break; + case player_charability2: lua_pushinteger(L, plr->charability2); - else if (fastcmp(field,"charflags")) + break; + case player_charflags: lua_pushinteger(L, plr->charflags); - else if (fastcmp(field,"thokitem")) + break; + case player_thokitem: lua_pushinteger(L, plr->thokitem); - else if (fastcmp(field,"spinitem")) + break; + case player_spinitem: lua_pushinteger(L, plr->spinitem); - else if (fastcmp(field,"revitem")) + break; + case player_revitem: lua_pushinteger(L, plr->revitem); - else if (fastcmp(field,"followitem")) + break; + case player_followitem: lua_pushinteger(L, plr->followitem); - else if (fastcmp(field,"followmobj")) + break; + case player_followmobj: LUA_PushUserdata(L, plr->followmobj, META_MOBJ); - else if (fastcmp(field,"actionspd")) + break; + case player_actionspd: lua_pushfixed(L, plr->actionspd); - else if (fastcmp(field,"mindash")) + break; + case player_mindash: lua_pushfixed(L, plr->mindash); - else if (fastcmp(field,"maxdash")) + break; + case player_maxdash: lua_pushfixed(L, plr->maxdash); - else if (fastcmp(field,"jumpfactor")) + break; + case player_jumpfactor: lua_pushfixed(L, plr->jumpfactor); - else if (fastcmp(field,"height")) + break; + case player_height: lua_pushfixed(L, plr->height); - else if (fastcmp(field,"spinheight")) + break; + case player_spinheight: lua_pushfixed(L, plr->spinheight); - else if (fastcmp(field,"lives")) + break; + case player_lives: lua_pushinteger(L, plr->lives); - else if (fastcmp(field,"continues")) + break; + case player_continues: lua_pushinteger(L, plr->continues); - else if (fastcmp(field,"xtralife")) + break; + case player_xtralife: lua_pushinteger(L, plr->xtralife); - else if (fastcmp(field,"gotcontinue")) + break; + case player_gotcontinue: lua_pushinteger(L, plr->gotcontinue); - else if (fastcmp(field,"speed")) + break; + case player_speed: lua_pushfixed(L, plr->speed); - else if (fastcmp(field,"secondjump")) + break; + case player_secondjump: lua_pushinteger(L, plr->secondjump); - else if (fastcmp(field,"fly1")) + break; + case player_fly1: lua_pushinteger(L, plr->fly1); - else if (fastcmp(field,"scoreadd")) + break; + case player_scoreadd: lua_pushinteger(L, plr->scoreadd); - else if (fastcmp(field,"glidetime")) + break; + case player_glidetime: lua_pushinteger(L, plr->glidetime); - else if (fastcmp(field,"climbing")) + break; + case player_climbing: lua_pushinteger(L, plr->climbing); - else if (fastcmp(field,"deadtimer")) + break; + case player_deadtimer: lua_pushinteger(L, plr->deadtimer); - else if (fastcmp(field,"exiting")) + break; + case player_exiting: lua_pushinteger(L, plr->exiting); - else if (fastcmp(field,"homing")) + break; + case player_homing: lua_pushinteger(L, plr->homing); - else if (fastcmp(field,"dashmode")) + break; + case player_dashmode: lua_pushinteger(L, plr->dashmode); - else if (fastcmp(field,"skidtime")) + break; + case player_skidtime: lua_pushinteger(L, plr->skidtime); - else if (fastcmp(field,"cmomx")) + break; + case player_cmomx: lua_pushfixed(L, plr->cmomx); - else if (fastcmp(field,"cmomy")) + break; + case player_cmomy: lua_pushfixed(L, plr->cmomy); - else if (fastcmp(field,"rmomx")) + break; + case player_rmomx: lua_pushfixed(L, plr->rmomx); - else if (fastcmp(field,"rmomy")) + break; + case player_rmomy: lua_pushfixed(L, plr->rmomy); - else if (fastcmp(field,"numboxes")) + break; + case player_numboxes: lua_pushinteger(L, plr->numboxes); - else if (fastcmp(field,"totalring")) + break; + case player_totalring: lua_pushinteger(L, plr->totalring); - else if (fastcmp(field,"realtime")) + break; + case player_realtime: lua_pushinteger(L, plr->realtime); - else if (fastcmp(field,"laps")) + break; + case player_laps: lua_pushinteger(L, plr->laps); - else if (fastcmp(field,"ctfteam")) + break; + case player_ctfteam: lua_pushinteger(L, plr->ctfteam); - else if (fastcmp(field,"gotflag")) + break; + case player_gotflag: lua_pushinteger(L, plr->gotflag); - else if (fastcmp(field,"weapondelay")) + break; + case player_weapondelay: lua_pushinteger(L, plr->weapondelay); - else if (fastcmp(field,"tossdelay")) + break; + case player_tossdelay: lua_pushinteger(L, plr->tossdelay); - else if (fastcmp(field,"starpostx")) + break; + case player_starpostx: lua_pushinteger(L, plr->starpostx); - else if (fastcmp(field,"starposty")) + break; + case player_starposty: lua_pushinteger(L, plr->starposty); - else if (fastcmp(field,"starpostz")) + break; + case player_starpostz: lua_pushinteger(L, plr->starpostz); - else if (fastcmp(field,"starpostnum")) + break; + case player_starpostnum: lua_pushinteger(L, plr->starpostnum); - else if (fastcmp(field,"starposttime")) + break; + case player_starposttime: lua_pushinteger(L, plr->starposttime); - else if (fastcmp(field,"starpostangle")) + break; + case player_starpostangle: lua_pushangle(L, plr->starpostangle); - else if (fastcmp(field,"starpostscale")) + break; + case player_starpostscale: lua_pushfixed(L, plr->starpostscale); - else if (fastcmp(field,"angle_pos")) + break; + case player_angle_pos: lua_pushangle(L, plr->angle_pos); - else if (fastcmp(field,"old_angle_pos")) + break; + case player_old_angle_pos: lua_pushangle(L, plr->old_angle_pos); - else if (fastcmp(field,"axis1")) + break; + case player_axis1: LUA_PushUserdata(L, plr->axis1, META_MOBJ); - else if (fastcmp(field,"axis2")) + break; + case player_axis2: LUA_PushUserdata(L, plr->axis2, META_MOBJ); - else if (fastcmp(field,"bumpertime")) + break; + case player_bumpertime: lua_pushinteger(L, plr->bumpertime); - else if (fastcmp(field,"flyangle")) + break; + case player_flyangle: lua_pushinteger(L, plr->flyangle); - else if (fastcmp(field,"drilltimer")) + break; + case player_drilltimer: lua_pushinteger(L, plr->drilltimer); - else if (fastcmp(field,"linkcount")) + break; + case player_linkcount: lua_pushinteger(L, plr->linkcount); - else if (fastcmp(field,"linktimer")) + break; + case player_linktimer: lua_pushinteger(L, plr->linktimer); - else if (fastcmp(field,"anotherflyangle")) + break; + case player_anotherflyangle: lua_pushinteger(L, plr->anotherflyangle); - else if (fastcmp(field,"nightstime")) + break; + case player_nightstime: lua_pushinteger(L, plr->nightstime); - else if (fastcmp(field,"drillmeter")) + break; + case player_drillmeter: lua_pushinteger(L, plr->drillmeter); - else if (fastcmp(field,"drilldelay")) + break; + case player_drilldelay: lua_pushinteger(L, plr->drilldelay); - else if (fastcmp(field,"bonustime")) + break; + case player_bonustime: lua_pushboolean(L, plr->bonustime); - else if (fastcmp(field,"capsule")) + break; + case player_capsule: LUA_PushUserdata(L, plr->capsule, META_MOBJ); - else if (fastcmp(field,"drone")) + break; + case player_drone: LUA_PushUserdata(L, plr->drone, META_MOBJ); - else if (fastcmp(field,"oldscale")) + break; + case player_oldscale: lua_pushfixed(L, plr->oldscale); - else if (fastcmp(field,"mare")) + break; + case player_mare: lua_pushinteger(L, plr->mare); - else if (fastcmp(field,"marelap")) + break; + case player_marelap: lua_pushinteger(L, plr->marelap); - else if (fastcmp(field,"marebonuslap")) + break; + case player_marebonuslap: lua_pushinteger(L, plr->marebonuslap); - else if (fastcmp(field,"marebegunat")) + break; + case player_marebegunat: lua_pushinteger(L, plr->marebegunat); - else if (fastcmp(field,"startedtime")) + break; + case player_startedtime: lua_pushinteger(L, plr->startedtime); - else if (fastcmp(field,"finishedtime")) + break; + case player_finishedtime: lua_pushinteger(L, plr->finishedtime); - else if (fastcmp(field,"lapbegunat")) + break; + case player_lapbegunat: lua_pushinteger(L, plr->lapbegunat); - else if (fastcmp(field,"lapstartedtime")) + break; + case player_lapstartedtime: lua_pushinteger(L, plr->lapstartedtime); - else if (fastcmp(field,"finishedspheres")) + break; + case player_finishedspheres: lua_pushinteger(L, plr->finishedspheres); - else if (fastcmp(field,"finishedrings")) + break; + case player_finishedrings: lua_pushinteger(L, plr->finishedrings); - else if (fastcmp(field,"marescore")) + break; + case player_marescore: lua_pushinteger(L, plr->marescore); - else if (fastcmp(field,"lastmarescore")) + break; + case player_lastmarescore: lua_pushinteger(L, plr->lastmarescore); - else if (fastcmp(field,"totalmarescore")) + break; + case player_totalmarescore: lua_pushinteger(L, plr->totalmarescore); - else if (fastcmp(field,"lastmare")) + break; + case player_lastmare: lua_pushinteger(L, plr->lastmare); - else if (fastcmp(field,"lastmarelap")) + break; + case player_lastmarelap: lua_pushinteger(L, plr->lastmarelap); - else if (fastcmp(field,"lastmarebonuslap")) + break; + case player_lastmarebonuslap: lua_pushinteger(L, plr->lastmarebonuslap); - else if (fastcmp(field,"totalmarelap")) + break; + case player_totalmarelap: lua_pushinteger(L, plr->totalmarelap); - else if (fastcmp(field,"totalmarebonuslap")) + break; + case player_totalmarebonuslap: lua_pushinteger(L, plr->totalmarebonuslap); - else if (fastcmp(field,"maxlink")) + break; + case player_maxlink: lua_pushinteger(L, plr->maxlink); - else if (fastcmp(field,"texttimer")) + break; + case player_texttimer: lua_pushinteger(L, plr->texttimer); - else if (fastcmp(field,"textvar")) + break; + case player_textvar: lua_pushinteger(L, plr->textvar); - else if (fastcmp(field,"lastsidehit")) + break; + case player_lastsidehit: lua_pushinteger(L, plr->lastsidehit); - else if (fastcmp(field,"lastlinehit")) + break; + case player_lastlinehit: lua_pushinteger(L, plr->lastlinehit); - else if (fastcmp(field,"losstime")) + break; + case player_losstime: lua_pushinteger(L, plr->losstime); - else if (fastcmp(field,"timeshit")) + break; + case player_timeshit: lua_pushinteger(L, plr->timeshit); - else if (fastcmp(field,"onconveyor")) + break; + case player_onconveyor: lua_pushinteger(L, plr->onconveyor); - else if (fastcmp(field,"awayviewmobj")) + break; + case player_awayviewmobj: LUA_PushUserdata(L, plr->awayviewmobj, META_MOBJ); - else if (fastcmp(field,"awayviewtics")) + break; + case player_awayviewtics: lua_pushinteger(L, plr->awayviewtics); - else if (fastcmp(field,"awayviewaiming")) + break; + case player_awayviewaiming: lua_pushangle(L, plr->awayviewaiming); - else if (fastcmp(field,"spectator")) + break; + case player_spectator: lua_pushboolean(L, plr->spectator); - else if (fastcmp(field,"outofcoop")) + break; + case player_outofcoop: lua_pushboolean(L, plr->outofcoop); - else if (fastcmp(field,"bot")) + break; + case player_bot: lua_pushinteger(L, plr->bot); - else if (fastcmp(field,"botleader")) + break; + case player_botleader: LUA_PushUserdata(L, plr->botleader, META_PLAYER); - else if (fastcmp(field,"lastbuttons")) + break; + case player_lastbuttons: lua_pushinteger(L, plr->lastbuttons); - else if (fastcmp(field,"blocked")) + break; + case player_blocked: lua_pushboolean(L, plr->blocked); - else if (fastcmp(field,"jointime")) + break; + case player_jointime: lua_pushinteger(L, plr->jointime); - else if (fastcmp(field,"quittime")) + break; + case player_quittime: lua_pushinteger(L, plr->quittime); + break; #ifdef HWRENDER - else if (fastcmp(field,"fovadd")) + case player_fovadd: lua_pushfixed(L, plr->fovadd); + break; #endif - else { + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, plr); lua_rawget(L, -2); if (!lua_istable(L, -1)) { // no extra values table - CONS_Debug(DBG_LUA, M_GetText("'%s' has no extvars table or field named '%s'; returning nil.\n"), "player_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no extvars table or field named '%s'; returning nil.\n"), "player_t", lua_tostring(L, 2)); return 0; } - lua_getfield(L, -1, field); + lua_pushvalue(L, 2); // field name + lua_gettable(L, -2); if (lua_isnil(L, -1)) // no value for this field - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "player_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "player_t", lua_tostring(L, 2)); + break; } return 1; @@ -405,7 +847,7 @@ static int player_get(lua_State *L) static int player_set(lua_State *L) { player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - const char *field = luaL_checkstring(L, 2); + enum player_e field = Lua_optoption(L, 2, player_cmd, player_fields_ref); if (!plr) return LUA_ErrInvalid(L, "player_t"); @@ -414,337 +856,473 @@ static int player_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter player_t in CMD building code!"); - if (fastcmp(field,"mo") || fastcmp(field,"realmo")) { + switch (field) + { + case player_mo: + case player_realmo: + { mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); plr->mo->player = NULL; // remove player pointer from old mobj (newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj + break; } - else if (fastcmp(field,"cmd")) + case player_cmd: return NOSET; - else if (fastcmp(field,"playerstate")) + case player_playerstate: plr->playerstate = luaL_checkinteger(L, 3); - else if (fastcmp(field,"camerascale")) + break; + case player_camerascale: plr->camerascale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"shieldscale")) + break; + case player_shieldscale: plr->shieldscale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"viewz")) + break; + case player_viewz: plr->viewz = luaL_checkfixed(L, 3); - else if (fastcmp(field,"viewheight")) + break; + case player_viewheight: plr->viewheight = luaL_checkfixed(L, 3); - else if (fastcmp(field,"deltaviewheight")) + break; + case player_deltaviewheight: plr->deltaviewheight = luaL_checkfixed(L, 3); - else if (fastcmp(field,"bob")) + break; + case player_bob: plr->bob = luaL_checkfixed(L, 3); - else if (fastcmp(field,"viewrollangle")) + break; + case player_viewrollangle: plr->viewrollangle = luaL_checkangle(L, 3); - else if (fastcmp(field,"aiming")) { + break; + case player_aiming: + { plr->aiming = luaL_checkangle(L, 3); if (plr == &players[consoleplayer]) localaiming = plr->aiming; else if (plr == &players[secondarydisplayplayer]) localaiming2 = plr->aiming; + break; } - else if (fastcmp(field,"drawangle")) + case player_drawangle: plr->drawangle = luaL_checkangle(L, 3); - else if (fastcmp(field,"rings")) + break; + case player_rings: plr->rings = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"spheres")) + break; + case player_spheres: plr->spheres = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"pity")) + break; + case player_pity: plr->pity = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"currentweapon")) + break; + case player_currentweapon: plr->currentweapon = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ringweapons")) + break; + case player_ringweapons: plr->ringweapons = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ammoremoval")) + break; + case player_ammoremoval: plr->ammoremoval = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ammoremovaltimer")) + break; + case player_ammoremovaltimer: plr->ammoremovaltimer = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ammoremovalweapon")) + break; + case player_ammoremovalweapon: plr->ammoremovalweapon = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"powers")) + break; + case player_powers: return NOSET; - else if (fastcmp(field,"pflags")) + case player_pflags: plr->pflags = luaL_checkinteger(L, 3); - else if (fastcmp(field,"panim")) + break; + case player_panim: plr->panim = luaL_checkinteger(L, 3); - else if (fastcmp(field,"flashcount")) + break; + case player_flashcount: plr->flashcount = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"flashpal")) + break; + case player_flashpal: plr->flashpal = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"skincolor")) + break; + case player_skincolor: { UINT16 newcolor = (UINT16)luaL_checkinteger(L,3); if (newcolor >= numskincolors) return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1); plr->skincolor = newcolor; + break; } - else if (fastcmp(field,"skin")) + case player_skin: return NOSET; - else if (fastcmp(field,"availabilities")) + case player_availabilities: return NOSET; - else if (fastcmp(field,"score")) + case player_score: plr->score = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"dashspeed")) + break; + case player_dashspeed: plr->dashspeed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"normalspeed")) + break; + case player_normalspeed: plr->normalspeed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"runspeed")) + break; + case player_runspeed: plr->runspeed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"thrustfactor")) + break; + case player_thrustfactor: plr->thrustfactor = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"accelstart")) + break; + case player_accelstart: plr->accelstart = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"acceleration")) + break; + case player_acceleration: plr->acceleration = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"charability")) + break; + case player_charability: plr->charability = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"charability2")) + break; + case player_charability2: plr->charability2 = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"charflags")) + break; + case player_charflags: plr->charflags = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"thokitem")) + break; + case player_thokitem: plr->thokitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"spinitem")) + break; + case player_spinitem: plr->spinitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"revitem")) + break; + case player_revitem: plr->revitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"followitem")) + break; + case player_followitem: plr->followitem = luaL_checkinteger(L, 3); - else if (fastcmp(field,"followmobj")) + break; + case player_followmobj: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->followmobj, mo); + break; } - else if (fastcmp(field,"actionspd")) + case player_actionspd: plr->actionspd = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"mindash")) + break; + case player_mindash: plr->mindash = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"maxdash")) + break; + case player_maxdash: plr->maxdash = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"jumpfactor")) + break; + case player_jumpfactor: plr->jumpfactor = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"height")) + break; + case player_height: plr->height = luaL_checkfixed(L, 3); - else if (fastcmp(field,"spinheight")) + break; + case player_spinheight: plr->spinheight = luaL_checkfixed(L, 3); - else if (fastcmp(field,"lives")) + break; + case player_lives: plr->lives = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"continues")) + break; + case player_continues: plr->continues = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"xtralife")) + break; + case player_xtralife: plr->xtralife = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"gotcontinue")) + break; + case player_gotcontinue: plr->gotcontinue = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"speed")) + break; + case player_speed: plr->speed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"secondjump")) + break; + case player_secondjump: plr->secondjump = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"fly1")) + break; + case player_fly1: plr->fly1 = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"scoreadd")) + break; + case player_scoreadd: plr->scoreadd = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"glidetime")) + break; + case player_glidetime: plr->glidetime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"climbing")) + break; + case player_climbing: plr->climbing = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"deadtimer")) + break; + case player_deadtimer: plr->deadtimer = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"exiting")) + break; + case player_exiting: plr->exiting = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"homing")) + break; + case player_homing: plr->homing = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"dashmode")) + break; + case player_dashmode: plr->dashmode = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"skidtime")) + break; + case player_skidtime: plr->skidtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"cmomx")) + break; + case player_cmomx: plr->cmomx = luaL_checkfixed(L, 3); - else if (fastcmp(field,"cmomy")) + break; + case player_cmomy: plr->cmomy = luaL_checkfixed(L, 3); - else if (fastcmp(field,"rmomx")) + break; + case player_rmomx: plr->rmomx = luaL_checkfixed(L, 3); - else if (fastcmp(field,"rmomy")) + break; + case player_rmomy: plr->rmomy = luaL_checkfixed(L, 3); - else if (fastcmp(field,"numboxes")) + break; + case player_numboxes: plr->numboxes = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalring")) + break; + case player_totalring: plr->totalring = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"realtime")) + break; + case player_realtime: plr->realtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"laps")) + break; + case player_laps: plr->laps = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ctfteam")) + break; + case player_ctfteam: plr->ctfteam = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"gotflag")) + break; + case player_gotflag: plr->gotflag = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"weapondelay")) + break; + case player_weapondelay: plr->weapondelay = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"tossdelay")) + break; + case player_tossdelay: plr->tossdelay = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostx")) + break; + case player_starpostx: plr->starpostx = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starposty")) + break; + case player_starposty: plr->starposty = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostz")) + break; + case player_starpostz: plr->starpostz = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostnum")) + break; + case player_starpostnum: plr->starpostnum = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starposttime")) + break; + case player_starposttime: plr->starposttime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"starpostangle")) + break; + case player_starpostangle: plr->starpostangle = luaL_checkangle(L, 3); - else if (fastcmp(field,"starpostscale")) + break; + case player_starpostscale: plr->starpostscale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"angle_pos")) + break; + case player_angle_pos: plr->angle_pos = luaL_checkangle(L, 3); - else if (fastcmp(field,"old_angle_pos")) + break; + case player_old_angle_pos: plr->old_angle_pos = luaL_checkangle(L, 3); - else if (fastcmp(field,"axis1")) + break; + case player_axis1: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->axis1, mo); + break; } - else if (fastcmp(field,"axis2")) + case player_axis2: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->axis2, mo); + break; } - else if (fastcmp(field,"bumpertime")) + case player_bumpertime: plr->bumpertime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"flyangle")) + break; + case player_flyangle: plr->flyangle = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"drilltimer")) + break; + case player_drilltimer: plr->drilltimer = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"linkcount")) + break; + case player_linkcount: plr->linkcount = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"linktimer")) + break; + case player_linktimer: plr->linktimer = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"anotherflyangle")) + break; + case player_anotherflyangle: plr->anotherflyangle = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"nightstime")) + break; + case player_nightstime: plr->nightstime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"drillmeter")) + break; + case player_drillmeter: plr->drillmeter = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"drilldelay")) + break; + case player_drilldelay: plr->drilldelay = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"bonustime")) + break; + case player_bonustime: plr->bonustime = luaL_checkboolean(L, 3); - else if (fastcmp(field,"capsule")) + break; + case player_capsule: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->capsule, mo); + break; } - else if (fastcmp(field,"drone")) + case player_drone: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->drone, mo); + break; } - else if (fastcmp(field,"oldscale")) + case player_oldscale: plr->oldscale = luaL_checkfixed(L, 3); - else if (fastcmp(field,"mare")) + break; + case player_mare: plr->mare = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marelap")) + break; + case player_marelap: plr->marelap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marebonuslap")) + break; + case player_marebonuslap: plr->marebonuslap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marebegunat")) + break; + case player_marebegunat: plr->marebegunat = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"startedtime")) + break; + case player_startedtime: plr->startedtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"finishedtime")) + break; + case player_finishedtime: plr->finishedtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lapbegunat")) + break; + case player_lapbegunat: plr->lapbegunat = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lapstartedtime")) + break; + case player_lapstartedtime: plr->lapstartedtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"finishedspheres")) + break; + case player_finishedspheres: plr->finishedspheres = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"finishedrings")) + break; + case player_finishedrings: plr->finishedrings = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"marescore")) + break; + case player_marescore: plr->marescore = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmarescore")) + break; + case player_lastmarescore: plr->lastmarescore = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalmarescore")) + break; + case player_totalmarescore: plr->totalmarescore = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmare")) + break; + case player_lastmare: plr->lastmare = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmarelap")) + break; + case player_lastmarelap: plr->lastmarelap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastmarebonuslap")) + break; + case player_lastmarebonuslap: plr->lastmarebonuslap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalmarelap")) + break; + case player_totalmarelap: plr->totalmarelap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"totalmarebonuslap")) + break; + case player_totalmarebonuslap: plr->totalmarebonuslap = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"maxlink")) + break; + case player_maxlink: plr->maxlink = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"texttimer")) + break; + case player_texttimer: plr->texttimer = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"textvar")) + break; + case player_textvar: plr->textvar = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastsidehit")) + break; + case player_lastsidehit: plr->lastsidehit = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"lastlinehit")) + break; + case player_lastlinehit: plr->lastlinehit = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"losstime")) + break; + case player_losstime: plr->losstime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"timeshit")) + break; + case player_timeshit: plr->timeshit = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"onconveyor")) + break; + case player_onconveyor: plr->onconveyor = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"awayviewmobj")) + break; + case player_awayviewmobj: { mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->awayviewmobj, mo); + break; } - else if (fastcmp(field,"awayviewtics")) - { + case player_awayviewtics: plr->awayviewtics = (INT32)luaL_checkinteger(L, 3); if (plr->awayviewtics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!! P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now. - } - else if (fastcmp(field,"awayviewaiming")) + break; + case player_awayviewaiming: plr->awayviewaiming = luaL_checkangle(L, 3); - else if (fastcmp(field,"spectator")) + break; + case player_spectator: plr->spectator = lua_toboolean(L, 3); - else if (fastcmp(field,"outofcoop")) + break; + case player_outofcoop: plr->outofcoop = lua_toboolean(L, 3); - else if (fastcmp(field,"bot")) + break; + case player_bot: return NOSET; - else if (fastcmp(field,"botleader")) + case player_botleader: { player_t *player = NULL; if (!lua_isnil(L, 3)) player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); plr->botleader = player; + break; } - else if (fastcmp(field,"lastbuttons")) + case player_lastbuttons: plr->lastbuttons = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"blocked")) + break; + case player_blocked: plr->blocked = (UINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"jointime")) + break; + case player_jointime: plr->jointime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"quittime")) + break; + case player_quittime: plr->quittime = (tic_t)luaL_checkinteger(L, 3); + break; #ifdef HWRENDER - else if (fastcmp(field,"fovadd")) + case player_fovadd: plr->fovadd = luaL_checkfixed(L, 3); + break; #endif - else { + default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); lua_pushlightuserdata(L, plr); @@ -752,15 +1330,17 @@ static int player_set(lua_State *L) if (lua_isnil(L, -1)) { // This index doesn't have a table for extra values yet, let's make one. lua_pop(L, 1); - CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "player_t", field); + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; adding it as Lua data.\n"), "player_t", lua_tostring(L, 2)); lua_newtable(L); lua_pushlightuserdata(L, plr); lua_pushvalue(L, -2); // ext value table lua_rawset(L, -4); // LREG_EXTVARS table } + lua_pushvalue(L, 2); // key lua_pushvalue(L, 3); // value to store - lua_setfield(L, -2, field); + lua_settable(L, -3); lua_pop(L, 2); + break; } return 0; @@ -814,27 +1394,58 @@ static int power_len(lua_State *L) #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) #define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", field) +enum ticcmd_e +{ + ticcmd_forwardmove, + ticcmd_sidemove, + ticcmd_angleturn, + ticcmd_aiming, + ticcmd_buttons, + ticcmd_latency, +}; + +static const char *const ticcmd_opt[] = { + "forwardmove", + "sidemove", + "angleturn", + "aiming", + "buttons", + "latency", + NULL, +}; + +static int ticcmd_fields_ref = LUA_NOREF; + static int ticcmd_get(lua_State *L) { ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD)); - const char *field = luaL_checkstring(L, 2); + enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref); if (!cmd) return LUA_ErrInvalid(L, "player_t"); - if (fastcmp(field,"forwardmove")) + switch (field) + { + case ticcmd_forwardmove: lua_pushinteger(L, cmd->forwardmove); - else if (fastcmp(field,"sidemove")) + break; + case ticcmd_sidemove: lua_pushinteger(L, cmd->sidemove); - else if (fastcmp(field,"angleturn")) + break; + case ticcmd_angleturn: lua_pushinteger(L, cmd->angleturn); - else if (fastcmp(field,"aiming")) + break; + case ticcmd_aiming: lua_pushinteger(L, cmd->aiming); - else if (fastcmp(field,"buttons")) + break; + case ticcmd_buttons: lua_pushinteger(L, cmd->buttons); - else if (fastcmp(field,"latency")) + break; + case ticcmd_latency: lua_pushinteger(L, cmd->latency); - else + break; + default: return NOFIELD; + } return 1; } @@ -842,27 +1453,35 @@ static int ticcmd_get(lua_State *L) static int ticcmd_set(lua_State *L) { ticcmd_t *cmd = *((ticcmd_t **)luaL_checkudata(L, 1, META_TICCMD)); - const char *field = luaL_checkstring(L, 2); + enum ticcmd_e field = Lua_optoption(L, 2, -1, ticcmd_fields_ref); if (!cmd) return LUA_ErrInvalid(L, "ticcmd_t"); if (hud_running) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); - if (fastcmp(field,"forwardmove")) + switch (field) + { + case ticcmd_forwardmove: cmd->forwardmove = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"sidemove")) + break; + case ticcmd_sidemove: cmd->sidemove = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"angleturn")) + break; + case ticcmd_angleturn: cmd->angleturn = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"aiming")) + break; + case ticcmd_aiming: cmd->aiming = (INT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"buttons")) + break; + case ticcmd_buttons: cmd->buttons = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"latency")) + break; + case ticcmd_latency: return NOSET; - else + default: return NOFIELD; + } return 0; } @@ -883,6 +1502,8 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + player_fields_ref = Lua_CreateFieldTable(L, player_opt); + luaL_newmetatable(L, META_POWERS); lua_pushcfunction(L, power_get); lua_setfield(L, -2, "__index"); @@ -902,6 +1523,8 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + ticcmd_fields_ref = Lua_CreateFieldTable(L, ticcmd_opt); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getPlayer); diff --git a/src/lua_script.c b/src/lua_script.c index 9cb146c12..6893265d5 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1729,17 +1729,39 @@ void LUA_UnArchive(void) } // For mobj_t, player_t, etc. to take custom variables. -int Lua_optoption(lua_State *L, int narg, - const char *def, const char *const lst[]) +int Lua_optoption(lua_State *L, int narg, int def, int list_ref) { - const char *name = (def) ? luaL_optstring(L, narg, def) : luaL_checkstring(L, narg); - int i; - for (i=0; lst[i]; i++) - if (fastcmp(lst[i], name)) - return i; + if (lua_isnoneornil(L, narg)) + return def; + + I_Assert(lua_checkstack(L, 2)); + luaL_checkstring(L, narg); + + lua_rawgeti(L, LUA_REGISTRYINDEX, list_ref); + I_Assert(lua_istable(L, -1)); + lua_pushvalue(L, narg); + lua_rawget(L, -2); + + if (lua_isnumber(L, -1)) + return lua_tointeger(L, -1); return -1; } +int Lua_CreateFieldTable(lua_State *L, const char *const lst[]) +{ + int i; + + lua_newtable(L); + for (i = 0; lst[i] != NULL; i++) + { + lua_pushstring(L, lst[i]); + lua_pushinteger(L, i); + lua_settable(L, -3); + } + + return luaL_ref(L, LUA_REGISTRYINDEX); +} + void LUA_PushTaggableObjectArray ( lua_State *L, const char *field, diff --git a/src/lua_script.h b/src/lua_script.h index fe04e5e60..d0b06a719 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -57,8 +57,8 @@ int LUA_PushGlobals(lua_State *L, const char *word); int LUA_CheckGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(void *cvar); // lua_consolelib.c -int Lua_optoption(lua_State *L, int narg, - const char *def, const char *const lst[]); +int Lua_optoption(lua_State *L, int narg, int def, int list_ref); +int Lua_CreateFieldTable(lua_State *L, const char *const lst[]); void LUA_HookNetArchive(lua_CFunction archFunc); void LUA_PushTaggableObjectArray diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 5c21b04c3..b7890a6c7 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -55,6 +55,7 @@ enum skin { skin_soundsid, skin_sprites }; + static const char *const skin_opt[] = { "valid", "name", @@ -95,10 +96,12 @@ static const char *const skin_opt[] = { #define UNIMPLEMENTED luaL_error(L, LUA_QL("skin_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", skin_opt[field]) +static int skin_fields_ref = LUA_NOREF; + static int skin_get(lua_State *L) { skin_t *skin = *((skin_t **)luaL_checkudata(L, 1, META_SKIN)); - enum skin field = luaL_checkoption(L, 2, NULL, skin_opt); + enum skin field = Lua_optoption(L, 2, -1, skin_fields_ref); // skins are always valid, only added, never removed I_Assert(skin != NULL); @@ -376,6 +379,8 @@ int LUA_SkinLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + skin_fields_ref = Lua_CreateFieldTable(L, skin_opt); + luaL_newmetatable(L, META_SOUNDSID); lua_pushcfunction(L, soundsid_get); lua_setfield(L, -2, "__index"); From 17356f93bf1f77f582f68494d4ee2b1574ff36cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Mon, 19 Jun 2023 22:19:39 +0200 Subject: [PATCH 165/478] Fix segfault when ghost dies from a death pit --- src/p_mobj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index a04351ae7..3eab29c09 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3139,7 +3139,8 @@ boolean P_SceneryZMovement(mobj_t *mo) if (P_CheckDeathPitCollide(mo)) { - P_RemoveMobj(mo); + if (mo->type != MT_GHOST) // ghosts play death animations instead, so don't remove them + P_RemoveMobj(mo); return false; } From bbe6c12323703736722dc9b1813fe79f1be3eb0d Mon Sep 17 00:00:00 2001 From: Lach <54614944+lachablock@users.noreply.github.com> Date: Wed, 26 Oct 2022 22:44:25 +1100 Subject: [PATCH 166/478] Skincolor changes: - Tweaked Orange and Cobalt - Added Pepper, Jade, Headlight, Master, Mauve, and Taffy - Fixed Mario mode invincibility color cycle (Opposite color shades are placeholder for now) --- src/deh_tables.c | 6 ++++++ src/doomdef.h | 6 ++++++ src/info.c | 10 ++++++++-- src/p_user.c | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index c3b2cfccd..79e01ef75 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4623,6 +4623,7 @@ const char *COLOR_ENUMS[] = { // Viv's vivid colours (toast 21/07/17) "RUBY", // SKINCOLOR_RUBY, "SALMON", // SKINCOLOR_SALMON, + "PEPPER", // SKINCOLOR_PEPPER, "RED", // SKINCOLOR_RED, "CRIMSON", // SKINCOLOR_CRIMSON, "FLAME", // SKINCOLOR_FLAME, @@ -4644,7 +4645,10 @@ const char *COLOR_ENUMS[] = { "GREEN", // SKINCOLOR_GREEN, "FOREST", // SKINCOLOR_FOREST, "EMERALD", // SKINCOLOR_EMERALD, + "JADE", // SKINCOLOR_JADE, + "HEADLIGHT", // SKINCOLOR_HEADLIGHT, "MINT", // SKINCOLOR_MINT, + "MASTER", // SKINCOLOR_MASTER, "SEAFOAM", // SKINCOLOR_SEAFOAM, "AQUA", // SKINCOLOR_AQUA, "TEAL", // SKINCOLOR_TEAL, @@ -4666,8 +4670,10 @@ const char *COLOR_ENUMS[] = { "NEON", // SKINCOLOR_NEON, "VIOLET", // SKINCOLOR_VIOLET, "LILAC", // SKINCOLOR_LILAC, + "MAUVE", // SKINCOLOR_MAUVE, "PLUM", // SKINCOLOR_PLUM, "RASPBERRY", // SKINCOLOR_RASPBERRY, + "TAFFY", // SKINCOLOR_TAFFY, "ROSY", // SKINCOLOR_ROSY, // Super special awesome Super flashing colors! diff --git a/src/doomdef.h b/src/doomdef.h index d521d4fbb..a2243f5f3 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -275,6 +275,7 @@ typedef enum // Viv's vivid colours (toast 21/07/17) SKINCOLOR_RUBY, SKINCOLOR_SALMON, + SKINCOLOR_PEPPER, SKINCOLOR_RED, SKINCOLOR_CRIMSON, SKINCOLOR_FLAME, @@ -296,7 +297,10 @@ typedef enum SKINCOLOR_GREEN, SKINCOLOR_FOREST, SKINCOLOR_EMERALD, + SKINCOLOR_JADE, + SKINCOLOR_HEADLIGHT, SKINCOLOR_MINT, + SKINCOLOR_MASTER, SKINCOLOR_SEAFOAM, SKINCOLOR_AQUA, SKINCOLOR_TEAL, @@ -318,8 +322,10 @@ typedef enum SKINCOLOR_NEON, SKINCOLOR_VIOLET, SKINCOLOR_LILAC, + SKINCOLOR_MAUVE, SKINCOLOR_PLUM, SKINCOLOR_RASPBERRY, + SKINCOLOR_TAFFY, SKINCOLOR_ROSY, FIRSTSUPERCOLOR, diff --git a/src/info.c b/src/info.c index 09452a74f..fbcdcfc80 100644 --- a/src/info.c +++ b/src/info.c @@ -21600,6 +21600,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { // Viv's vivid colours (toast 21/07/17) {"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY {"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON + {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_PEPPER {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED {"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON {"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME @@ -21609,7 +21610,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET {"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER {"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT - {"Orange", {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE + {"Orange", { 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 42, 44, 45, 46, 46}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY @@ -21621,7 +21622,10 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN {"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST {"Emerald", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD + {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_TAFFY, 8, V_GREENMAP, true}, // SKINCOLOR_JADE + {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT {"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT + {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA {"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL @@ -21633,7 +21637,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Sapphire", {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE {"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER {"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE - {"Cobalt", {0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT + {"Cobalt", { 145, 147, 149, 150, 151, 153, 154, 155, 156, 157, 158, 159, 253, 253, 254, 254}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT {"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR {"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK {"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL @@ -21643,8 +21647,10 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC + {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY + {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 206, 207, 44, 44, 46, 47}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY // super diff --git a/src/p_user.c b/src/p_user.c index 0f3282da5..38af2843b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2984,7 +2984,7 @@ static void P_CheckInvincibilityTimer(player_t *player) return; if (mariomode && !player->powers[pw_super]) - player->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (numskincolors - SKINCOLOR_RUBY))); // Passes through all saturated colours + player->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (FIRSTSUPERCOLOR - SKINCOLOR_RUBY))); // Passes through all saturated colours else if (leveltime % (TICRATE/7) == 0) { mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); From 222e409cde6e212b2eec61268b78ac83a7cf1051 Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 27 Oct 2022 00:24:12 +0200 Subject: [PATCH 167/478] More skincolor changes: - Tweaked Bubblegum - Added 8 new colors by Alice - Added 22 new colors by sphere --- src/deh_tables.c | 31 +++++++++++++++++++++++++++++++ src/doomdef.h | 31 +++++++++++++++++++++++++++++++ src/info.c | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 79e01ef75..7ee78218b 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4609,19 +4609,28 @@ const char *COLOR_ENUMS[] = { // Desaturated "AETHER", // SKINCOLOR_AETHER, "SLATE", // SKINCOLOR_SLATE, + "MERCURY", // SKINCOLOR_MERCURY, "BLUEBELL", // SKINCOLOR_BLUEBELL, "PINK", // SKINCOLOR_PINK, + "ROSEWOOD", // SKINCOLOR_ROSEWOOD, "YOGURT", // SKINCOLOR_YOGURT, + "LATTE", // SKINCOLOR_LATTE, "BROWN", // SKINCOLOR_BROWN, "BRONZE", // SKINCOLOR_BRONZE, + "SEPIA", // SKINCOLOR_SEPIA, + "ECRU", // SKINCOLOR_ECRU, "TAN", // SKINCOLOR_TAN, "BEIGE", // SKINCOLOR_BEIGE, + "ROSEBUSH", // SKINCOLOR_ROSEBUSH, "MOSS", // SKINCOLOR_MOSS, "AZURE", // SKINCOLOR_AZURE, + "EGGPLANT", // SKINCOLOR_EGGPLANT, "LAVENDER", // SKINCOLOR_LAVENDER, // Viv's vivid colours (toast 21/07/17) + // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) "RUBY", // SKINCOLOR_RUBY, + "CHERRY", // SKINCOLOR_CHERRY, "SALMON", // SKINCOLOR_SALMON, "PEPPER", // SKINCOLOR_PEPPER, "RED", // SKINCOLOR_RED, @@ -4630,18 +4639,24 @@ const char *COLOR_ENUMS[] = { "KETCHUP", // SKINCOLOR_KETCHUP, "PEACHY", // SKINCOLOR_PEACHY, "QUAIL", // SKINCOLOR_QUAIL, + "FOUNDATION", // SKINCOLOR_FOUNDATION, "SUNSET", // SKINCOLOR_SUNSET, "COPPER", // SKINCOLOR_COPPER, "APRICOT", // SKINCOLOR_APRICOT, "ORANGE", // SKINCOLOR_ORANGE, + "PUMPKIN", // SKINCOLOR_PUMPKIN, "RUST", // SKINCOLOR_RUST, "GOLD", // SKINCOLOR_GOLD, "SANDY", // SKINCOLOR_SANDY, "YELLOW", // SKINCOLOR_YELLOW, "OLIVE", // SKINCOLOR_OLIVE, + "KIWI", // SKINCOLOR_KIWI, + "LEMON", // SKINCOLOR_LEMON, "LIME", // SKINCOLOR_LIME, + "MINDARO", // SKINCOLOR_MINDARO, "PERIDOT", // SKINCOLOR_PERIDOT, "APPLE", // SKINCOLOR_APPLE, + "CHARTREUSE", // SKINCOLOR_CHARTREUSE, "GREEN", // SKINCOLOR_GREEN, "FOREST", // SKINCOLOR_FOREST, "EMERALD", // SKINCOLOR_EMERALD, @@ -4649,32 +4664,48 @@ const char *COLOR_ENUMS[] = { "HEADLIGHT", // SKINCOLOR_HEADLIGHT, "MINT", // SKINCOLOR_MINT, "MASTER", // SKINCOLOR_MASTER, + "BOTTLE", // SKINCOLOR_BOTTLE, "SEAFOAM", // SKINCOLOR_SEAFOAM, + "ISLAND", // SKINCOLOR_ISLAND, "AQUA", // SKINCOLOR_AQUA, "TEAL", // SKINCOLOR_TEAL, "WAVE", // SKINCOLOR_WAVE, "CYAN", // SKINCOLOR_CYAN, + "TURQUOISE", // SKINCOLOR_TURQUOISE, "SKY", // SKINCOLOR_SKY, + "MARINE", // SKINCOLOR_MARINE, "CERULEAN", // SKINCOLOR_CERULEAN, + "DREAM", // SKINCOLOR_DREAM, "ICY", // SKINCOLOR_ICY, + "DAYBREAK", // SKINCOLOR_DAYBREAK, "SAPPHIRE", // SKINCOLOR_SAPPHIRE, + "ARCTIC", // SKINCOLOR_ARCTIC, "CORNFLOWER", // SKINCOLOR_CORNFLOWER, "BLUE", // SKINCOLOR_BLUE, "COBALT", // SKINCOLOR_COBALT, + "MIDNIGHT", // SKINCOLOR_MIDNIGHT, + "GALAXY", // SKINCOLOR_GALAXY, "VAPOR", // SKINCOLOR_VAPOR, "DUSK", // SKINCOLOR_DUSK, + "MAJESTY", // SKINCOLOR_MAJESTY, "PASTEL", // SKINCOLOR_PASTEL, "PURPLE", // SKINCOLOR_PURPLE, + "NOBLE", // SKINCOLOR_NOBLE, + "FUCHSIA", // SKINCOLOR_FUCHSIA, "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM, "MAGENTA", // SKINCOLOR_MAGENTA, "NEON", // SKINCOLOR_NEON, "VIOLET", // SKINCOLOR_VIOLET, + "ROYAL", // SKINCOLOR_ROYAL, "LILAC", // SKINCOLOR_LILAC, "MAUVE", // SKINCOLOR_MAUVE, + "EVENTIDE", // SKINCOLOR_EVENTIDE, "PLUM", // SKINCOLOR_PLUM, "RASPBERRY", // SKINCOLOR_RASPBERRY, "TAFFY", // SKINCOLOR_TAFFY, "ROSY", // SKINCOLOR_ROSY, + "FANCY", // SKINCOLOR_FANCY, + "SANGRIA", // SKINCOLOR_SANGRIA, // Super special awesome Super flashing colors! "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1 diff --git a/src/doomdef.h b/src/doomdef.h index a2243f5f3..f21000cda 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -261,19 +261,28 @@ typedef enum // Desaturated SKINCOLOR_AETHER, SKINCOLOR_SLATE, + SKINCOLOR_MERCURY, SKINCOLOR_BLUEBELL, SKINCOLOR_PINK, + SKINCOLOR_ROSEWOOD, SKINCOLOR_YOGURT, + SKINCOLOR_LATTE, SKINCOLOR_BROWN, SKINCOLOR_BRONZE, + SKINCOLOR_SEPIA, + SKINCOLOR_ECRU, SKINCOLOR_TAN, SKINCOLOR_BEIGE, + SKINCOLOR_ROSEBUSH, SKINCOLOR_MOSS, SKINCOLOR_AZURE, + SKINCOLOR_EGGPLANT, SKINCOLOR_LAVENDER, // Viv's vivid colours (toast 21/07/17) + // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) SKINCOLOR_RUBY, + SKINCOLOR_CHERRY, SKINCOLOR_SALMON, SKINCOLOR_PEPPER, SKINCOLOR_RED, @@ -282,18 +291,24 @@ typedef enum SKINCOLOR_KETCHUP, SKINCOLOR_PEACHY, SKINCOLOR_QUAIL, + SKINCOLOR_FOUNDATION, SKINCOLOR_SUNSET, SKINCOLOR_COPPER, SKINCOLOR_APRICOT, SKINCOLOR_ORANGE, + SKINCOLOR_PUMPKIN, SKINCOLOR_RUST, SKINCOLOR_GOLD, SKINCOLOR_SANDY, SKINCOLOR_YELLOW, SKINCOLOR_OLIVE, + SKINCOLOR_KIWI, + SKINCOLOR_LEMON, SKINCOLOR_LIME, + SKINCOLOR_MINDARO, SKINCOLOR_PERIDOT, SKINCOLOR_APPLE, + SKINCOLOR_CHARTREUSE, SKINCOLOR_GREEN, SKINCOLOR_FOREST, SKINCOLOR_EMERALD, @@ -301,32 +316,48 @@ typedef enum SKINCOLOR_HEADLIGHT, SKINCOLOR_MINT, SKINCOLOR_MASTER, + SKINCOLOR_BOTTLE, SKINCOLOR_SEAFOAM, + SKINCOLOR_ISLAND, SKINCOLOR_AQUA, SKINCOLOR_TEAL, SKINCOLOR_WAVE, SKINCOLOR_CYAN, + SKINCOLOR_TURQUOISE, SKINCOLOR_SKY, + SKINCOLOR_MARINE, SKINCOLOR_CERULEAN, + SKINCOLOR_DREAM, SKINCOLOR_ICY, + SKINCOLOR_DAYBREAK, SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl + SKINCOLOR_ARCTIC, SKINCOLOR_CORNFLOWER, SKINCOLOR_BLUE, SKINCOLOR_COBALT, + SKINCOLOR_MIDNIGHT, + SKINCOLOR_GALAXY, SKINCOLOR_VAPOR, SKINCOLOR_DUSK, + SKINCOLOR_MAJESTY, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, + SKINCOLOR_NOBLE, + SKINCOLOR_FUCHSIA, SKINCOLOR_BUBBLEGUM, SKINCOLOR_MAGENTA, SKINCOLOR_NEON, SKINCOLOR_VIOLET, + SKINCOLOR_ROYAL, SKINCOLOR_LILAC, SKINCOLOR_MAUVE, + SKINCOLOR_EVENTIDE, SKINCOLOR_PLUM, SKINCOLOR_RASPBERRY, SKINCOLOR_TAFFY, SKINCOLOR_ROSY, + SKINCOLOR_FANCY, + SKINCOLOR_SANGRIA, FIRSTSUPERCOLOR, diff --git a/src/info.c b/src/info.c index fbcdcfc80..10b05dee4 100644 --- a/src/info.c +++ b/src/info.c @@ -21586,19 +21586,28 @@ skincolor_t skincolors[MAXSKINCOLORS] = { // Desaturated {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE + {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK + {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT + {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 14, V_BROWNMAP, true}, // SKINCOLOR_LATTE {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN {"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE + {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD,5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA + {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE + {"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT,5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE + {"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH,5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER // Viv's vivid colours (toast 21/07/17) + // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) {"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY + {"Cherry", { 202, 203, 204, 205, 206, 40, 41, 42, 43, 44, 186, 187, 28, 29, 30, 31}, SKINCOLOR_MIDNIGHT, 10, V_REDMAP, true}, // SKINCOLOR_CHERRY {"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_PEPPER {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED @@ -21607,18 +21616,24 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BRONZE, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP {"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY {"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL + {"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 195, 196, 186, 187, 30}, SKINCOLOR_DREAM, 9, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION {"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET {"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER {"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT {"Orange", { 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 42, 44, 45, 46, 46}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE + {"Pumpkin", { 51, 52, 53, 54, 56, 58, 59, 59, 61, 61, 63, 45, 46, 47, 47, 31}, SKINCOLOR_ARCTIC, 10, V_ORANGEMAP, true}, // SKINCOLOR_PUMPKIN {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW {"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE + {"Kiwi", { 88, 64, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 7, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI + {"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 6, V_YELLOWMAP, true}, // SKINCOLOR_LEMON {"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME + {"Mindaro", { 0, 80, 81, 82, 83, 64, 188, 189, 189, 190, 115, 116, 117, 118, 119, 111}, SKINCOLOR_MAJESTY, 11, V_PERIDOTMAP, true}, // SKINCOLOR_MINDARO {"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT {"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE + {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 12, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN {"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST {"Emerald", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD @@ -21626,32 +21641,48 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT {"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER + {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM + {"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA {"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL {"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE {"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN + {"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 7, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE {"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY + {"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_KIWI, 10, V_SKYMAP, true}, // SKINCOLOR_MARINE {"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN + {"Dream", { 80, 208, 200, 200, 146, 146, 133, 134, 135, 136, 137, 138, 139, 139, 254, 254}, SKINCOLOR_FOUNDATION, 9, V_SKYMAP, true}, // SKINCOLOR_DREAM {"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY + {"Daybreak", { 80, 81, 82, 72, 64, 9, 11, 171, 149, 150, 151, 153, 156, 157, 159, 253}, SKINCOLOR_EVENTIDE, 12, V_BLUEMAP, true}, // SKINCOLOR_DAYBREAK {"Sapphire", {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE + {"Arctic", { 0, 1, 3, 4, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 10, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC {"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER {"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE {"Cobalt", { 145, 147, 149, 150, 151, 153, 154, 155, 156, 157, 158, 159, 253, 253, 254, 254}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT + {"Midnight", { 171, 171, 172, 173, 173, 174, 155, 156, 157, 159, 253, 253, 254, 254, 31, 31}, SKINCOLOR_CHERRY, 10, V_GRAYMAP, true}, // SKINCOLOR_MIDNIGHT + {"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 167, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY {"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR {"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK + {"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_MINDARO, 11, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY {"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL {"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE - {"Bubblegum", {0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM + {"Noble", { 144, 146, 147, 148, 148, 164, 164, 165, 165, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE + {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 6, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA + {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 183, 165, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM {"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA {"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET + {"Royal", { 208, 209, 192, 192, 192, 193, 193, 194, 194, 172, 173, 174, 175, 175, 139, 139}, SKINCOLOR_FANCY, 9, V_PURPLEMAP, true}, // SKINCOLOR_ROYAL {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE + {"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 12, V_REDMAP, true}, // SKINCOLOR_EVENTIDE {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 206, 207, 44, 44, 46, 47}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY + {"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY + {"Sangria", { 210, 32, 33, 34, 35, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 7, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA // super {"Super Silver 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, SKINCOLOR_BLACK, 15, 0, false}, // SKINCOLOR_SUPERSILVER1 From edbfb92b1128d628177a80c201ecde5a09df267f Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 27 Oct 2022 00:37:15 +0200 Subject: [PATCH 168/478] Correct tabs & spacing --- src/deh_tables.c | 24 ++++++++++++------------ src/doomdef.h | 8 ++++---- src/info.c | 38 +++++++++++++++++++------------------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 7ee78218b..d349e35d0 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4612,20 +4612,20 @@ const char *COLOR_ENUMS[] = { "MERCURY", // SKINCOLOR_MERCURY, "BLUEBELL", // SKINCOLOR_BLUEBELL, "PINK", // SKINCOLOR_PINK, - "ROSEWOOD", // SKINCOLOR_ROSEWOOD, + "ROSEWOOD", // SKINCOLOR_ROSEWOOD, "YOGURT", // SKINCOLOR_YOGURT, "LATTE", // SKINCOLOR_LATTE, "BROWN", // SKINCOLOR_BROWN, "BRONZE", // SKINCOLOR_BRONZE, "SEPIA", // SKINCOLOR_SEPIA, "ECRU", // SKINCOLOR_ECRU, - "TAN", // SKINCOLOR_TAN, + "TAN", // SKINCOLOR_TAN, "BEIGE", // SKINCOLOR_BEIGE, - "ROSEBUSH", // SKINCOLOR_ROSEBUSH, + "ROSEBUSH", // SKINCOLOR_ROSEBUSH, "MOSS", // SKINCOLOR_MOSS, "AZURE", // SKINCOLOR_AZURE, - "EGGPLANT", // SKINCOLOR_EGGPLANT, - "LAVENDER", // SKINCOLOR_LAVENDER, + "EGGPLANT", // SKINCOLOR_EGGPLANT, + "LAVENDER", // SKINCOLOR_LAVENDER, // Viv's vivid colours (toast 21/07/17) // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) @@ -4639,7 +4639,7 @@ const char *COLOR_ENUMS[] = { "KETCHUP", // SKINCOLOR_KETCHUP, "PEACHY", // SKINCOLOR_PEACHY, "QUAIL", // SKINCOLOR_QUAIL, - "FOUNDATION", // SKINCOLOR_FOUNDATION, + "FOUNDATION", // SKINCOLOR_FOUNDATION, "SUNSET", // SKINCOLOR_SUNSET, "COPPER", // SKINCOLOR_COPPER, "APRICOT", // SKINCOLOR_APRICOT, @@ -4656,7 +4656,7 @@ const char *COLOR_ENUMS[] = { "MINDARO", // SKINCOLOR_MINDARO, "PERIDOT", // SKINCOLOR_PERIDOT, "APPLE", // SKINCOLOR_APPLE, - "CHARTREUSE", // SKINCOLOR_CHARTREUSE, + "CHARTREUSE", // SKINCOLOR_CHARTREUSE, "GREEN", // SKINCOLOR_GREEN, "FOREST", // SKINCOLOR_FOREST, "EMERALD", // SKINCOLOR_EMERALD, @@ -4673,17 +4673,17 @@ const char *COLOR_ENUMS[] = { "CYAN", // SKINCOLOR_CYAN, "TURQUOISE", // SKINCOLOR_TURQUOISE, "SKY", // SKINCOLOR_SKY, - "MARINE", // SKINCOLOR_MARINE, + "MARINE", // SKINCOLOR_MARINE, "CERULEAN", // SKINCOLOR_CERULEAN, - "DREAM", // SKINCOLOR_DREAM, + "DREAM", // SKINCOLOR_DREAM, "ICY", // SKINCOLOR_ICY, - "DAYBREAK", // SKINCOLOR_DAYBREAK, + "DAYBREAK", // SKINCOLOR_DAYBREAK, "SAPPHIRE", // SKINCOLOR_SAPPHIRE, - "ARCTIC", // SKINCOLOR_ARCTIC, + "ARCTIC", // SKINCOLOR_ARCTIC, "CORNFLOWER", // SKINCOLOR_CORNFLOWER, "BLUE", // SKINCOLOR_BLUE, "COBALT", // SKINCOLOR_COBALT, - "MIDNIGHT", // SKINCOLOR_MIDNIGHT, + "MIDNIGHT", // SKINCOLOR_MIDNIGHT, "GALAXY", // SKINCOLOR_GALAXY, "VAPOR", // SKINCOLOR_VAPOR, "DUSK", // SKINCOLOR_DUSK, diff --git a/src/doomdef.h b/src/doomdef.h index f21000cda..171c4b69c 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -264,16 +264,16 @@ typedef enum SKINCOLOR_MERCURY, SKINCOLOR_BLUEBELL, SKINCOLOR_PINK, - SKINCOLOR_ROSEWOOD, + SKINCOLOR_ROSEWOOD, SKINCOLOR_YOGURT, - SKINCOLOR_LATTE, + SKINCOLOR_LATTE, SKINCOLOR_BROWN, SKINCOLOR_BRONZE, - SKINCOLOR_SEPIA, + SKINCOLOR_SEPIA, SKINCOLOR_ECRU, SKINCOLOR_TAN, SKINCOLOR_BEIGE, - SKINCOLOR_ROSEBUSH, + SKINCOLOR_ROSEBUSH, SKINCOLOR_MOSS, SKINCOLOR_AZURE, SKINCOLOR_EGGPLANT, diff --git a/src/info.c b/src/info.c index 10b05dee4..ab5a0e254 100644 --- a/src/info.c +++ b/src/info.c @@ -21584,25 +21584,25 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Black", {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, SKINCOLOR_WHITE, 7, V_GRAYMAP, true}, // SKINCOLOR_BLACK // Desaturated - {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER - {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE - {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY - {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL - {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK - {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD - {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT - {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 14, V_BROWNMAP, true}, // SKINCOLOR_LATTE - {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN - {"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE - {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD,5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA - {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU - {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN - {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE - {"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT,5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH - {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS - {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE - {"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH,5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT - {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER + {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER + {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE + {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY + {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL + {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK + {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD + {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT + {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 14, V_BROWNMAP, true}, // SKINCOLOR_LATTE + {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN + {"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE + {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD, 5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA + {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU + {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN + {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE + {"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT, 5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH + {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS + {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE + {"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH, 5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT + {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER // Viv's vivid colours (toast 21/07/17) // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) From 647e6aac12d215e2263543172dbae3619f1fb9ef Mon Sep 17 00:00:00 2001 From: Lach <54614944+lachablock@users.noreply.github.com> Date: Thu, 27 Oct 2022 20:06:26 +1100 Subject: [PATCH 169/478] Simplify the way skincolors' invshades are used --- src/m_menu.c | 2 +- src/p_enemy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f9f52335d..c09e12998 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8520,7 +8520,7 @@ static void M_DrawLoadGameData(void) if (charskin->prefoppositecolor) { col = charskin->prefoppositecolor; - col = skincolors[col].ramp[skincolors[skincolors[col].invcolor].invshade]; + col = skincolors[col].ramp[skincolors[charskin->prefcolor].invshade]; } else { diff --git a/src/p_enemy.c b/src/p_enemy.c index c7d87b88a..fe062cffc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5321,7 +5321,7 @@ void A_SignPlayer(mobj_t *actor) actor->tracer->color = signcolor; if (signcolor && signcolor < numskincolors) - signframe += (15 - skincolors[skincolors[signcolor].invcolor].invshade); + signframe += (15 - skincolors[facecolor].invshade); actor->tracer->frame = signframe; } From 458b47464577cd23b5d1f5c3a9f88599598b1531 Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 27 Oct 2022 11:22:33 +0200 Subject: [PATCH 170/478] Even more skincolor changes: - Changed Bronze - Added Boulder & Volcanic - Tweaked Galaxy --- src/deh_tables.c | 2 ++ src/doomdef.h | 2 ++ src/info.c | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index d349e35d0..ec60d7311 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4616,6 +4616,7 @@ const char *COLOR_ENUMS[] = { "YOGURT", // SKINCOLOR_YOGURT, "LATTE", // SKINCOLOR_LATTE, "BROWN", // SKINCOLOR_BROWN, + "BOULDER", // SKINCOLOR_BOULDER "BRONZE", // SKINCOLOR_BRONZE, "SEPIA", // SKINCOLOR_SEPIA, "ECRU", // SKINCOLOR_ECRU, @@ -4706,6 +4707,7 @@ const char *COLOR_ENUMS[] = { "ROSY", // SKINCOLOR_ROSY, "FANCY", // SKINCOLOR_FANCY, "SANGRIA", // SKINCOLOR_SANGRIA, + "VOLCANIC", // SKINCOLOR_VOLCANIC, // Super special awesome Super flashing colors! "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1 diff --git a/src/doomdef.h b/src/doomdef.h index 171c4b69c..aa200274a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -268,6 +268,7 @@ typedef enum SKINCOLOR_YOGURT, SKINCOLOR_LATTE, SKINCOLOR_BROWN, + SKINCOLOR_BOULDER, SKINCOLOR_BRONZE, SKINCOLOR_SEPIA, SKINCOLOR_ECRU, @@ -358,6 +359,7 @@ typedef enum SKINCOLOR_ROSY, SKINCOLOR_FANCY, SKINCOLOR_SANGRIA, + SKINCOLOR_VOLCANIC, FIRSTSUPERCOLOR, diff --git a/src/info.c b/src/info.c index ab5a0e254..ec5a6c72d 100644 --- a/src/info.c +++ b/src/info.c @@ -21593,7 +21593,8 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 14, V_BROWNMAP, true}, // SKINCOLOR_LATTE {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN - {"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE + {"Boulder", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BOULDER + {"Bronze", { 82, 84, 50, 51, 223, 228, 230, 232, 234, 236, 237, 238, 239, 239, 30, 31}, SKINCOLOR_VOLCANIC, 9, V_BROWNMAP, true}, // SKINCOLOR_BRONZE {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD, 5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN @@ -21613,7 +21614,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED {"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON {"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME - {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BRONZE, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP + {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BOULDER, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP {"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY {"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL {"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 195, 196, 186, 187, 30}, SKINCOLOR_DREAM, 9, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION @@ -21661,7 +21662,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE {"Cobalt", { 145, 147, 149, 150, 151, 153, 154, 155, 156, 157, 158, 159, 253, 253, 254, 254}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT {"Midnight", { 171, 171, 172, 173, 173, 174, 155, 156, 157, 159, 253, 253, 254, 254, 31, 31}, SKINCOLOR_CHERRY, 10, V_GRAYMAP, true}, // SKINCOLOR_MIDNIGHT - {"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 167, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY + {"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 166, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY {"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR {"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK {"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_MINDARO, 11, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY @@ -21683,6 +21684,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY {"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY {"Sangria", { 210, 32, 33, 34, 35, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 7, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA + {"Volcanic", { 35, 38, 41, 42, 44, 46, 46, 169, 169, 159, 253, 254, 30, 30, 31, 31}, SKINCOLOR_BRONZE, 9, V_REDMAP, true}, // SKINCOLOR_VOLCANIC // super {"Super Silver 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, SKINCOLOR_BLACK, 15, 0, false}, // SKINCOLOR_SUPERSILVER1 From 4cd85b522838403cf98e91ef1de988dcdf471144 Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 27 Oct 2022 13:22:43 +0200 Subject: [PATCH 171/478] Support PgUp/PgDn for color select, similar to sound test & addons menu --- src/m_menu.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index c09e12998..d07bf62e1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12268,6 +12268,23 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } break; + case KEY_PGUP: + case KEY_PGDN: + { + UINT8 i; + if (itemOn == 2) // player color + { + S_StartSound(NULL,sfx_menu1); + for (i = 0; i < 13; i++) // or (282-charw)/(2*indexwidth) + { + setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; + while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors + setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; + } + } + } + break; + case KEY_ESCAPE: exitmenu = true; break; From 766c346df59f6cc8383e159458db463a9bf42895 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 29 Oct 2022 00:07:40 +0200 Subject: [PATCH 172/478] Add grid view for skincolors --- src/m_menu.c | 215 ++++++++++++++++++++++++++++++++++++++++----------- src/m_menu.h | 2 + 2 files changed, 173 insertions(+), 44 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d07bf62e1..63b345692 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -389,6 +389,7 @@ static void M_DrawRoomMenu(void); #endif static void M_DrawJoystick(void); static void M_DrawSetupMultiPlayerMenu(void); +static void M_DrawColorRamp(INT32 x, INT32 y, INT32 w, INT32 h, skincolor_t color); // Handling functions static boolean M_ExitPandorasBox(void); @@ -12010,6 +12011,7 @@ static consvar_t *setupm_cvdefaultskin; static consvar_t *setupm_cvdefaultcolor; static INT32 setupm_fakeskin; static menucolor_t *setupm_fakecolor; +static boolean colorgrid; static void M_DrawSetupMultiPlayerMenu(void) { @@ -12059,7 +12061,7 @@ static void M_DrawSetupMultiPlayerMenu(void) '\x1D' | V_YELLOWMAP, false); } - x = BASEVIDWIDTH/2; + x = colorgrid ? 92 : BASEVIDWIDTH/2; y += 11; // anim the player in the box @@ -12116,61 +12118,121 @@ faildraw: #undef chary colordraw: - x = MP_PlayerSetupDef.x; - y += 75; - - M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Color", true, false); - if (itemOn == 2) - cursory = y; - - // draw color string - V_DrawRightAlignedString(BASEVIDWIDTH - x, y, - ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, - skincolors[setupm_fakecolor->color].name); - - if (itemOn == 2 && (MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE) - { - V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skincolors[setupm_fakecolor->color].name, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, - '\x1C' | V_YELLOWMAP, false); - V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, - '\x1D' | V_YELLOWMAP, false); - } - - y += 11; #define indexwidth 8 + + if (colorgrid) // Draw color grid & skip the later options + { + UINT16 pos; + INT16 cx = 96, cy = 66; + INT16 i, j; + INT32 w = indexwidth; // Width of a singular color block + boolean stoprow = false; + menucolor_t *mc; // Last accessed color + + x = 132; + y = 66; + pos = min(max(0, 16*((M_GetColorIndex(setupm_fakecolor->color)-1)/16) - 64), 16*(M_GetColorIndex(menucolortail->color)/16-1) - 128); + mc = M_GetColorFromIndex(pos); + + // Draw grid + V_DrawFill(x-2, y-2, 132, 132, 159); + for (j = 0; j < 8; j++) + { + for (i = 0; i < 16; i++) + { + if (skincolors[mc->color].accessible && !stoprow) + { + M_DrawColorRamp(x + i*w, y + j*16, w, 1, skincolors[mc->color]); + if (mc->color == setupm_fakecolor->color) // store current color position + { + cx = x + i*w; + cy = y + j*16; + } + } + mc = mc->next; + while (!skincolors[mc->color].accessible && !stoprow) // Find accessible color after this one + { + mc = mc->next; + if (mc == menucolortail) stoprow = true; + } + } + } + + // Draw arrows, if needed + if (pos > 0) + V_DrawCharacter(264, y - (skullAnimCounter/5), '\x1A' | V_YELLOWMAP, false); + if (!stoprow) + V_DrawCharacter(264, y+120 + (skullAnimCounter/5), '\x1B' | V_YELLOWMAP, false); + + // Draw cursor & current skincolor + V_DrawFill(cx - 2, cy - 2, 12, 20, 0); + V_DrawFill(cx - 1, cy - 1, 11, 19, 31); + V_DrawFill( cx, cy, 9, 17, 0); + M_DrawColorRamp(cx, cy, w, 1, skincolors[setupm_fakecolor->color]); + + // Draw color string (with background) + V_DrawFill(55, 148, 74, 1, 73); + V_DrawFill(55, 149, 74, 1, 26); + M_DrawColorRamp(55, 150, 74, 1, skincolors[setupm_fakecolor->color]); + V_DrawRightAlignedString(x-2,166, + ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, + skincolors[setupm_fakecolor->color].name); + + return; // Don't draw anything after this + } + else // Draw color strip & the rest of the menu options { const INT32 numcolors = (282-charw)/(2*indexwidth); // Number of colors per side INT32 w = indexwidth; // Width of a singular color block menucolor_t *mc = setupm_fakecolor->prev; // Last accessed color - UINT8 h; INT16 i; + x = MP_PlayerSetupDef.x; + y += 75; + + // Draw color header & string + M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), "Color...", true, false); + V_DrawRightAlignedString(BASEVIDWIDTH - x, y, + ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 2 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, + skincolors[setupm_fakecolor->color].name); + + // Draw horizontal arrows + if (itemOn == 2) + { + cursory = y; + if ((MP_PlayerSetupMenu[2].status & IT_TYPE) != IT_SPACE) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skincolors[setupm_fakecolor->color].name, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, + '\x1C' | V_YELLOWMAP, false); + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | V_YELLOWMAP, false); + } + } + // Draw color in the middle x += numcolors*w; - for (h = 0; h < 16; h++) - V_DrawFill(x, y+h, charw, 1, skincolors[setupm_fakecolor->color].ramp[h]); + y += 11; + M_DrawColorRamp(x, y, charw, 1, skincolors[setupm_fakecolor->color]); - //Draw colors from middle to left - for (i=0; icolor].accessible) + while (!skincolors[mc->color].accessible) // Find accessible color before this one mc = mc->prev; - for (h = 0; h < 16; h++) - V_DrawFill(x, y+h, w, 1, skincolors[mc->color].ramp[h]); + M_DrawColorRamp(x, y, w, 1, skincolors[mc->color]); mc = mc->prev; } // Draw colors from middle to right mc = setupm_fakecolor->next; x += numcolors*w + charw; - for (i=0; icolor].accessible) + for (i = 0; i < numcolors; i++) + { + while (!skincolors[mc->color].accessible) // Find accessible color after this one mc = mc->next; - for (h = 0; h < 16; h++) - V_DrawFill(x, y+h, w, 1, skincolors[mc->color].ramp[h]); + M_DrawColorRamp(x, y, w, 1, skincolors[mc->color]); x += w; mc = mc->next; } @@ -12195,6 +12257,13 @@ colordraw: W_CachePatchName("M_CURSOR", PU_PATCH)); } +static void M_DrawColorRamp(INT32 x, INT32 y, INT32 w, INT32 h, skincolor_t color) +{ + UINT8 i; + for (i = 0; i < 16; i++) + V_DrawFill(x, y+(i*h), w, h, color.ramp[i]); +} + // Handle 1P/2P MP Setup static void M_HandleSetupMultiPlayer(INT32 choice) { @@ -12205,13 +12274,25 @@ static void M_HandleSetupMultiPlayer(INT32 choice) switch (choice) { case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL,sfx_menu1); // Tails - break; - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL,sfx_menu1); // Tails + { + UINT8 i; + if (itemOn == 2 && colorgrid) + { + for (i = 0; i < 16; i++) + { + setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; + while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors + setupm_fakecolor = (choice == KEY_UPARROW) ? setupm_fakecolor->prev : setupm_fakecolor->next; + } + } + else if (choice == KEY_UPARROW) + M_PrevOpt(); + else + M_NextOpt(); + + S_StartSound(NULL,sfx_menu1); + } break; case KEY_LEFTARROW: @@ -12246,6 +12327,13 @@ static void M_HandleSetupMultiPlayer(INT32 choice) COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor->color)); break; } + else if (itemOn == 2) + { + if (!colorgrid) + S_StartSound(NULL,sfx_menu1); + colorgrid = !colorgrid; + break; + } /* FALLTHRU */ case KEY_RIGHTARROW: if (itemOn == 1) //player skin @@ -12275,7 +12363,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) if (itemOn == 2) // player color { S_StartSound(NULL,sfx_menu1); - for (i = 0; i < 13; i++) // or (282-charw)/(2*indexwidth) + for (i = 0; i < (colorgrid ? 64 : 13); i++) // or (282-charw)/(2*indexwidth) { setupm_fakecolor = (choice == KEY_PGUP) ? setupm_fakecolor->prev : setupm_fakecolor->next; while (!skincolors[setupm_fakecolor->color].accessible) // skip inaccessible colors @@ -12286,7 +12374,10 @@ static void M_HandleSetupMultiPlayer(INT32 choice) break; case KEY_ESCAPE: - exitmenu = true; + if (itemOn == 2 && colorgrid) + colorgrid = false; + else + exitmenu = true; break; case KEY_BACKSPACE: @@ -12596,6 +12687,42 @@ UINT16 M_GetColorAfter(UINT16 color) { } } +UINT16 M_GetColorIndex(UINT16 color) { + menucolor_t *look; + UINT16 i = 0; + + if (color >= numskincolors) { + CONS_Printf("M_GetColorIndex: color %d does not exist.\n",color); + return 0; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + return i; + if (look==menucolortail) + return 0; + i++; + } +} + +menucolor_t* M_GetColorFromIndex(UINT16 index) { + menucolor_t *look = menucolorhead; + UINT16 i = 0; + + if (index >= numskincolors) { + CONS_Printf("M_GetColorIndex: index %d does not exist.\n",index); + return 0; + } + + for (i = 0; i <= index; i++) { + if (look==menucolortail) + return menucolorhead; + look=look->next; + } + + return look; +} + void M_InitPlayerSetupColors(void) { UINT8 i; numskincolors = SKINCOLOR_FIRSTFREESLOT; diff --git a/src/m_menu.h b/src/m_menu.h index 35c77cc43..c925c7f49 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -482,6 +482,8 @@ void M_MoveColorBefore(UINT16 color, UINT16 targ); void M_MoveColorAfter(UINT16 color, UINT16 targ); UINT16 M_GetColorBefore(UINT16 color); UINT16 M_GetColorAfter(UINT16 color); +UINT16 M_GetColorIndex(UINT16 color); +menucolor_t* M_GetColorFromIndex(UINT16 index); void M_InitPlayerSetupColors(void); void M_FreePlayerSetupColors(void); From c9b6693c765fcabf1523d58ca6e6197dd0609b5b Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 29 Oct 2022 00:08:32 +0200 Subject: [PATCH 173/478] Allow pausing & rotation of player sprites in player setup --- src/m_menu.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 63b345692..b4b5409b0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -11999,6 +11999,8 @@ static void M_HandleConnectIP(INT32 choice) static fixed_t multi_tics; static UINT8 multi_frame; static UINT8 multi_spr2; +static UINT8 multi_angle; +static boolean multi_paused; // this is set before entering the MultiPlayer setup menu, // for either player 1 or 2 @@ -12066,7 +12068,7 @@ static void M_DrawSetupMultiPlayerMenu(void) // anim the player in the box multi_tics -= renderdeltatics; - while (multi_tics <= 0) + while (!multi_paused && multi_tics <= 0) { multi_frame++; multi_tics += 4*FRACUNIT; @@ -12089,8 +12091,8 @@ static void M_DrawSetupMultiPlayerMenu(void) multi_frame = 0; sprframe = &sprdef->spriteframes[multi_frame]; - patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); - if (sprframe->flip & 1) // Only for first sprite + patch = W_CachePatchNum(sprframe->lumppat[multi_angle], PU_PATCH); + if (sprframe->flip & 1 || multi_angle >= 5) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! #define chary (y+64) @@ -12408,6 +12410,20 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } break; + case KEY_KEYPAD5: + multi_paused = !multi_paused; + break; + + case KEY_KEYPAD4: + if (multi_angle <= 0) multi_angle = 7; + else multi_angle--; + break; + + case KEY_KEYPAD6: + if (multi_angle >= 7) multi_angle = 0; + else multi_angle++; + break; + default: if (itemOn != 0 || choice < 32 || choice > 127) break; @@ -12447,6 +12463,7 @@ static void M_SetupMultiPlayer(INT32 choice) multi_frame = 0; multi_tics = 4*FRACUNIT; + multi_angle = 0; strcpy(setupm_name, cv_playername.string); // set for player 1 @@ -12491,6 +12508,7 @@ static void M_SetupMultiPlayer2(INT32 choice) multi_frame = 0; multi_tics = 4*FRACUNIT; + multi_angle = 0; strcpy (setupm_name, cv_playername2.string); // set for splitscreen secondary player From 853c9958d7c044629608d5316715333016c207b5 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 31 Dec 2022 02:40:44 +0100 Subject: [PATCH 174/478] Remove unfinished sprite rotation --- src/m_menu.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index b4b5409b0..a1c22bb3e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -11999,7 +11999,6 @@ static void M_HandleConnectIP(INT32 choice) static fixed_t multi_tics; static UINT8 multi_frame; static UINT8 multi_spr2; -static UINT8 multi_angle; static boolean multi_paused; // this is set before entering the MultiPlayer setup menu, @@ -12091,8 +12090,8 @@ static void M_DrawSetupMultiPlayerMenu(void) multi_frame = 0; sprframe = &sprdef->spriteframes[multi_frame]; - patch = W_CachePatchNum(sprframe->lumppat[multi_angle], PU_PATCH); - if (sprframe->flip & 1 || multi_angle >= 5) // Only for first sprite + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + if (sprframe->flip & 1) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! #define chary (y+64) @@ -12410,20 +12409,10 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } break; - case KEY_KEYPAD5: + case KEY_PAUSE: multi_paused = !multi_paused; break; - case KEY_KEYPAD4: - if (multi_angle <= 0) multi_angle = 7; - else multi_angle--; - break; - - case KEY_KEYPAD6: - if (multi_angle >= 7) multi_angle = 0; - else multi_angle++; - break; - default: if (itemOn != 0 || choice < 32 || choice > 127) break; @@ -12463,7 +12452,7 @@ static void M_SetupMultiPlayer(INT32 choice) multi_frame = 0; multi_tics = 4*FRACUNIT; - multi_angle = 0; + strcpy(setupm_name, cv_playername.string); // set for player 1 @@ -12508,7 +12497,7 @@ static void M_SetupMultiPlayer2(INT32 choice) multi_frame = 0; multi_tics = 4*FRACUNIT; - multi_angle = 0; + strcpy (setupm_name, cv_playername2.string); // set for splitscreen secondary player From 5e6850a7f78ddbef1414a82b9e0395ffddfd66b4 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 31 Dec 2022 03:18:26 +0100 Subject: [PATCH 175/478] Some more color tweaks: - Added 6 new colors to match Chaos Emeralds - Changed Taffy & Sapphire (3rd emerald) - Renamed old Emerald to Shamrock --- src/deh_tables.c | 10 ++++++++-- src/doomdef.h | 8 +++++++- src/info.c | 12 +++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index ec60d7311..1344fb400 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4609,6 +4609,7 @@ const char *COLOR_ENUMS[] = { // Desaturated "AETHER", // SKINCOLOR_AETHER, "SLATE", // SKINCOLOR_SLATE, + "STONE", // SKINCOLOR_STONE, "MERCURY", // SKINCOLOR_MERCURY, "BLUEBELL", // SKINCOLOR_BLUEBELL, "PINK", // SKINCOLOR_PINK, @@ -4637,6 +4638,7 @@ const char *COLOR_ENUMS[] = { "RED", // SKINCOLOR_RED, "CRIMSON", // SKINCOLOR_CRIMSON, "FLAME", // SKINCOLOR_FLAME, + "GARNET", // SKINCOLOR_GARNET, "KETCHUP", // SKINCOLOR_KETCHUP, "PEACHY", // SKINCOLOR_PEACHY, "QUAIL", // SKINCOLOR_QUAIL, @@ -4649,6 +4651,7 @@ const char *COLOR_ENUMS[] = { "RUST", // SKINCOLOR_RUST, "GOLD", // SKINCOLOR_GOLD, "SANDY", // SKINCOLOR_SANDY, + "TOPAZ", // SKINCOLOR_TOPAZ, "YELLOW", // SKINCOLOR_YELLOW, "OLIVE", // SKINCOLOR_OLIVE, "KIWI", // SKINCOLOR_KIWI, @@ -4660,11 +4663,12 @@ const char *COLOR_ENUMS[] = { "CHARTREUSE", // SKINCOLOR_CHARTREUSE, "GREEN", // SKINCOLOR_GREEN, "FOREST", // SKINCOLOR_FOREST, - "EMERALD", // SKINCOLOR_EMERALD, + "SHAMROCK", // SKINCOLOR_SHAMROCK, "JADE", // SKINCOLOR_JADE, "HEADLIGHT", // SKINCOLOR_HEADLIGHT, "MINT", // SKINCOLOR_MINT, "MASTER", // SKINCOLOR_MASTER, + "EMERALD", // SKINCOLOR_EMERALD, "BOTTLE", // SKINCOLOR_BOTTLE, "SEAFOAM", // SKINCOLOR_SEAFOAM, "ISLAND", // SKINCOLOR_ISLAND, @@ -4678,6 +4682,7 @@ const char *COLOR_ENUMS[] = { "CERULEAN", // SKINCOLOR_CERULEAN, "DREAM", // SKINCOLOR_DREAM, "ICY", // SKINCOLOR_ICY, + "AQUAMARINE", // SKINCOLOR_AQUAMARINE, "DAYBREAK", // SKINCOLOR_DAYBREAK, "SAPPHIRE", // SKINCOLOR_SAPPHIRE, "ARCTIC", // SKINCOLOR_ARCTIC, @@ -4693,7 +4698,8 @@ const char *COLOR_ENUMS[] = { "PURPLE", // SKINCOLOR_PURPLE, "NOBLE", // SKINCOLOR_NOBLE, "FUCHSIA", // SKINCOLOR_FUCHSIA, - "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM, + "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM, + "AMETHYST", // SKINCOLOR_AMETHYST, "MAGENTA", // SKINCOLOR_MAGENTA, "NEON", // SKINCOLOR_NEON, "VIOLET", // SKINCOLOR_VIOLET, diff --git a/src/doomdef.h b/src/doomdef.h index aa200274a..8bd311e6a 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -261,6 +261,7 @@ typedef enum // Desaturated SKINCOLOR_AETHER, SKINCOLOR_SLATE, + SKINCOLOR_STONE, SKINCOLOR_MERCURY, SKINCOLOR_BLUEBELL, SKINCOLOR_PINK, @@ -289,6 +290,7 @@ typedef enum SKINCOLOR_RED, SKINCOLOR_CRIMSON, SKINCOLOR_FLAME, + SKINCOLOR_GARNET, SKINCOLOR_KETCHUP, SKINCOLOR_PEACHY, SKINCOLOR_QUAIL, @@ -301,6 +303,7 @@ typedef enum SKINCOLOR_RUST, SKINCOLOR_GOLD, SKINCOLOR_SANDY, + SKINCOLOR_TOPAZ, SKINCOLOR_YELLOW, SKINCOLOR_OLIVE, SKINCOLOR_KIWI, @@ -312,11 +315,12 @@ typedef enum SKINCOLOR_CHARTREUSE, SKINCOLOR_GREEN, SKINCOLOR_FOREST, - SKINCOLOR_EMERALD, + SKINCOLOR_SHAMROCK, SKINCOLOR_JADE, SKINCOLOR_HEADLIGHT, SKINCOLOR_MINT, SKINCOLOR_MASTER, + SKINCOLOR_EMERALD, SKINCOLOR_BOTTLE, SKINCOLOR_SEAFOAM, SKINCOLOR_ISLAND, @@ -330,6 +334,7 @@ typedef enum SKINCOLOR_CERULEAN, SKINCOLOR_DREAM, SKINCOLOR_ICY, + SKINCOLOR_AQUAMARINE, SKINCOLOR_DAYBREAK, SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl SKINCOLOR_ARCTIC, @@ -346,6 +351,7 @@ typedef enum SKINCOLOR_NOBLE, SKINCOLOR_FUCHSIA, SKINCOLOR_BUBBLEGUM, + SKINCOLOR_AMETHYST, SKINCOLOR_MAGENTA, SKINCOLOR_NEON, SKINCOLOR_VIOLET, diff --git a/src/info.c b/src/info.c index ec5a6c72d..052be8c87 100644 --- a/src/info.c +++ b/src/info.c @@ -21586,6 +21586,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { // Desaturated {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE + {"Stone", { 0, 4, 8, 9, 11, 12, 14, 15, 171, 172, 173, 174, 175, 27, 29, 31}, SKINCOLOR_TOPAZ, 15, 0, true}, // SKINCOLOR_STONE {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK @@ -21614,6 +21615,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED {"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON {"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME + {"Garnet", { 0, 83, 50, 53, 34, 35, 37, 38, 39, 40, 42, 44, 45, 46, 47, 47}, SKINCOLOR_AQUAMARINE, 8, V_REDMAP, true}, // SKINCOLOR_GARNET {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BOULDER, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP {"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY {"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL @@ -21626,6 +21628,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY + {"Topaz", { 0, 81, 72, 73, 64, 65, 66, 66, 54, 55, 57, 59, 60, 42, 43, 45}, SKINCOLOR_STONE , 8, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW {"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE {"Kiwi", { 88, 64, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 7, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI @@ -21637,11 +21640,12 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 12, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN {"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST - {"Emerald", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD + {"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_AMETHYST, 4, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_TAFFY, 8, V_GREENMAP, true}, // SKINCOLOR_JADE {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT {"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER + {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM {"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND @@ -21655,8 +21659,9 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN {"Dream", { 80, 208, 200, 200, 146, 146, 133, 134, 135, 136, 137, 138, 139, 139, 254, 254}, SKINCOLOR_FOUNDATION, 9, V_SKYMAP, true}, // SKINCOLOR_DREAM {"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY + {"Aquamarine", { 0, 120, 121, 131, 132, 133, 134, 134, 135, 135, 149, 149, 172, 173, 174, 175}, SKINCOLOR_GARNET, 0, V_SKYMAP, true}, // SKINCOLOR_AQUAMARINE {"Daybreak", { 80, 81, 82, 72, 64, 9, 11, 171, 149, 150, 151, 153, 156, 157, 159, 253}, SKINCOLOR_EVENTIDE, 12, V_BLUEMAP, true}, // SKINCOLOR_DAYBREAK - {"Sapphire", {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE + {"Sapphire", {0x80, 0x82, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE {"Arctic", { 0, 1, 3, 4, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 10, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC {"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER {"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE @@ -21671,6 +21676,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Noble", { 144, 146, 147, 148, 148, 164, 164, 165, 165, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 6, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 183, 165, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM + {"Amethyst", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_AMETHYST {"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA {"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET @@ -21680,7 +21686,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 12, V_REDMAP, true}, // SKINCOLOR_EVENTIDE {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY - {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 206, 207, 44, 44, 46, 47}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY + {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY {"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY {"Sangria", { 210, 32, 33, 34, 35, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 7, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA From 70b69552f9f42ee1a94b29583f75ebc50ddb2f56 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 31 Dec 2022 14:30:47 +0100 Subject: [PATCH 176/478] Add toggle for invcolor background, plus: - Renamed Amethyst to Crystal - Moved some of the new colors - Tweaked a couple of invshades --- src/deh_tables.c | 6 +++--- src/doomdef.h | 6 +++--- src/info.c | 22 +++++++++++----------- src/m_menu.c | 8 +++++++- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 1344fb400..d174afb12 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4649,9 +4649,9 @@ const char *COLOR_ENUMS[] = { "ORANGE", // SKINCOLOR_ORANGE, "PUMPKIN", // SKINCOLOR_PUMPKIN, "RUST", // SKINCOLOR_RUST, + "TOPAZ", // SKINCOLOR_TOPAZ, "GOLD", // SKINCOLOR_GOLD, "SANDY", // SKINCOLOR_SANDY, - "TOPAZ", // SKINCOLOR_TOPAZ, "YELLOW", // SKINCOLOR_YELLOW, "OLIVE", // SKINCOLOR_OLIVE, "KIWI", // SKINCOLOR_KIWI, @@ -4677,12 +4677,12 @@ const char *COLOR_ENUMS[] = { "WAVE", // SKINCOLOR_WAVE, "CYAN", // SKINCOLOR_CYAN, "TURQUOISE", // SKINCOLOR_TURQUOISE, + "AQUAMARINE", // SKINCOLOR_AQUAMARINE, "SKY", // SKINCOLOR_SKY, "MARINE", // SKINCOLOR_MARINE, "CERULEAN", // SKINCOLOR_CERULEAN, "DREAM", // SKINCOLOR_DREAM, "ICY", // SKINCOLOR_ICY, - "AQUAMARINE", // SKINCOLOR_AQUAMARINE, "DAYBREAK", // SKINCOLOR_DAYBREAK, "SAPPHIRE", // SKINCOLOR_SAPPHIRE, "ARCTIC", // SKINCOLOR_ARCTIC, @@ -4699,7 +4699,7 @@ const char *COLOR_ENUMS[] = { "NOBLE", // SKINCOLOR_NOBLE, "FUCHSIA", // SKINCOLOR_FUCHSIA, "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM, - "AMETHYST", // SKINCOLOR_AMETHYST, + "CRYSTAL", // SKINCOLOR_CRYSTAL, "MAGENTA", // SKINCOLOR_MAGENTA, "NEON", // SKINCOLOR_NEON, "VIOLET", // SKINCOLOR_VIOLET, diff --git a/src/doomdef.h b/src/doomdef.h index 8bd311e6a..d19543e23 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -301,9 +301,9 @@ typedef enum SKINCOLOR_ORANGE, SKINCOLOR_PUMPKIN, SKINCOLOR_RUST, + SKINCOLOR_TOPAZ, SKINCOLOR_GOLD, SKINCOLOR_SANDY, - SKINCOLOR_TOPAZ, SKINCOLOR_YELLOW, SKINCOLOR_OLIVE, SKINCOLOR_KIWI, @@ -329,12 +329,12 @@ typedef enum SKINCOLOR_WAVE, SKINCOLOR_CYAN, SKINCOLOR_TURQUOISE, + SKINCOLOR_AQUAMARINE, SKINCOLOR_SKY, SKINCOLOR_MARINE, SKINCOLOR_CERULEAN, SKINCOLOR_DREAM, SKINCOLOR_ICY, - SKINCOLOR_AQUAMARINE, SKINCOLOR_DAYBREAK, SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl SKINCOLOR_ARCTIC, @@ -351,7 +351,7 @@ typedef enum SKINCOLOR_NOBLE, SKINCOLOR_FUCHSIA, SKINCOLOR_BUBBLEGUM, - SKINCOLOR_AMETHYST, + SKINCOLOR_CRYSTAL, SKINCOLOR_MAGENTA, SKINCOLOR_NEON, SKINCOLOR_VIOLET, diff --git a/src/info.c b/src/info.c index 052be8c87..2b6d6affb 100644 --- a/src/info.c +++ b/src/info.c @@ -21592,7 +21592,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT - {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 14, V_BROWNMAP, true}, // SKINCOLOR_LATTE + {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 12, V_BROWNMAP, true}, // SKINCOLOR_LATTE {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN {"Boulder", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BOULDER {"Bronze", { 82, 84, 50, 51, 223, 228, 230, 232, 234, 236, 237, 238, 239, 239, 30, 31}, SKINCOLOR_VOLCANIC, 9, V_BROWNMAP, true}, // SKINCOLOR_BRONZE @@ -21627,11 +21627,11 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Pumpkin", { 51, 52, 53, 54, 56, 58, 59, 59, 61, 61, 63, 45, 46, 47, 47, 31}, SKINCOLOR_ARCTIC, 10, V_ORANGEMAP, true}, // SKINCOLOR_PUMPKIN {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD + {"Topaz", { 0, 81, 72, 73, 64, 65, 66, 66, 54, 55, 57, 59, 60, 42, 43, 45}, SKINCOLOR_STONE , 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY - {"Topaz", { 0, 81, 72, 73, 64, 65, 66, 66, 54, 55, 57, 59, 60, 42, 43, 45}, SKINCOLOR_STONE , 8, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW {"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE - {"Kiwi", { 88, 64, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 7, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI + {"Kiwi", { 88, 64, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI {"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 6, V_YELLOWMAP, true}, // SKINCOLOR_LEMON {"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME {"Mindaro", { 0, 80, 81, 82, 83, 64, 188, 189, 189, 190, 115, 116, 117, 118, 119, 111}, SKINCOLOR_MAJESTY, 11, V_PERIDOTMAP, true}, // SKINCOLOR_MINDARO @@ -21640,13 +21640,13 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 12, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN {"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST - {"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_AMETHYST, 4, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK - {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_TAFFY, 8, V_GREENMAP, true}, // SKINCOLOR_JADE + {"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_CRYSTAL, 10, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK + {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_TAFFY, 10, V_GREENMAP, true}, // SKINCOLOR_JADE {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT {"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER - {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD - {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE + {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 7, V_GREENMAP, true}, // SKINCOLOR_EMERALD + {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 12, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM {"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA @@ -21654,12 +21654,12 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE {"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN {"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 7, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE + {"Aquamarine", { 0, 120, 121, 131, 132, 133, 134, 134, 135, 135, 149, 149, 172, 173, 174, 175}, SKINCOLOR_GARNET, 8, V_SKYMAP, true}, // SKINCOLOR_AQUAMARINE {"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY - {"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_KIWI, 10, V_SKYMAP, true}, // SKINCOLOR_MARINE + {"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_KIWI, 13, V_SKYMAP, true}, // SKINCOLOR_MARINE {"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN {"Dream", { 80, 208, 200, 200, 146, 146, 133, 134, 135, 136, 137, 138, 139, 139, 254, 254}, SKINCOLOR_FOUNDATION, 9, V_SKYMAP, true}, // SKINCOLOR_DREAM {"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY - {"Aquamarine", { 0, 120, 121, 131, 132, 133, 134, 134, 135, 135, 149, 149, 172, 173, 174, 175}, SKINCOLOR_GARNET, 0, V_SKYMAP, true}, // SKINCOLOR_AQUAMARINE {"Daybreak", { 80, 81, 82, 72, 64, 9, 11, 171, 149, 150, 151, 153, 156, 157, 159, 253}, SKINCOLOR_EVENTIDE, 12, V_BLUEMAP, true}, // SKINCOLOR_DAYBREAK {"Sapphire", {0x80, 0x82, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE {"Arctic", { 0, 1, 3, 4, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 10, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC @@ -21676,14 +21676,14 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Noble", { 144, 146, 147, 148, 148, 164, 164, 165, 165, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 6, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 183, 165, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM - {"Amethyst", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_AMETHYST + {"Crystal", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_CRYSTAL {"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA {"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET {"Royal", { 208, 209, 192, 192, 192, 193, 193, 194, 194, 172, 173, 174, 175, 175, 139, 139}, SKINCOLOR_FANCY, 9, V_PURPLEMAP, true}, // SKINCOLOR_ROYAL {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE - {"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 12, V_REDMAP, true}, // SKINCOLOR_EVENTIDE + {"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 13, V_MAGENTAMAP, true}, // SKINCOLOR_EVENTIDE {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY diff --git a/src/m_menu.c b/src/m_menu.c index a1c22bb3e..cf61e7fb1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12000,6 +12000,7 @@ static fixed_t multi_tics; static UINT8 multi_frame; static UINT8 multi_spr2; static boolean multi_paused; +static boolean multi_invcolor; // this is set before entering the MultiPlayer setup menu, // for either player 1 or 2 @@ -12076,7 +12077,8 @@ static void M_DrawSetupMultiPlayerMenu(void) #define charw 74 // draw box around character - V_DrawFill(x-(charw/2), y, charw, 84, 159); + V_DrawFill(x-(charw/2), y, charw, 84, + multi_invcolor ?skincolors[skincolors[setupm_fakecolor->color].invcolor].ramp[skincolors[setupm_fakecolor->color].invshade] : 159); sprdef = &skins[setupm_fakeskin].sprites[multi_spr2]; @@ -12413,6 +12415,10 @@ static void M_HandleSetupMultiPlayer(INT32 choice) multi_paused = !multi_paused; break; + case KEY_INS: + multi_invcolor = !multi_invcolor; + break; + default: if (itemOn != 0 || choice < 32 || choice > 127) break; From 1bd593d17337a2664c58c46c316613cde8e48781 Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 3 Jan 2023 23:08:39 +0100 Subject: [PATCH 177/478] Use extra colors for very high NiGHTS links, plus: - Replaced Mindaro with Goldenrod - Changed Topaz, and fixed inconsistency with its placement - Small tweaks to Kiwi, Seafoam, Noble and Sangria - Changed other NiGHTS link colors a little (& removed old iterations) --- src/deh_tables.c | 4 ++-- src/doomdef.h | 4 ++-- src/info.c | 14 +++++++------- src/st_stuff.c | 38 ++++++++------------------------------ 4 files changed, 19 insertions(+), 41 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index d174afb12..268a18ad4 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4649,15 +4649,15 @@ const char *COLOR_ENUMS[] = { "ORANGE", // SKINCOLOR_ORANGE, "PUMPKIN", // SKINCOLOR_PUMPKIN, "RUST", // SKINCOLOR_RUST, - "TOPAZ", // SKINCOLOR_TOPAZ, "GOLD", // SKINCOLOR_GOLD, + "TOPAZ", // SKINCOLOR_TOPAZ, "SANDY", // SKINCOLOR_SANDY, + "GOLDENROD", // SKINCOLOR_GOLDENROD, "YELLOW", // SKINCOLOR_YELLOW, "OLIVE", // SKINCOLOR_OLIVE, "KIWI", // SKINCOLOR_KIWI, "LEMON", // SKINCOLOR_LEMON, "LIME", // SKINCOLOR_LIME, - "MINDARO", // SKINCOLOR_MINDARO, "PERIDOT", // SKINCOLOR_PERIDOT, "APPLE", // SKINCOLOR_APPLE, "CHARTREUSE", // SKINCOLOR_CHARTREUSE, diff --git a/src/doomdef.h b/src/doomdef.h index d19543e23..31cdac9c4 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -301,15 +301,15 @@ typedef enum SKINCOLOR_ORANGE, SKINCOLOR_PUMPKIN, SKINCOLOR_RUST, - SKINCOLOR_TOPAZ, SKINCOLOR_GOLD, + SKINCOLOR_TOPAZ, SKINCOLOR_SANDY, + SKINCOLOR_GOLDENROD, SKINCOLOR_YELLOW, SKINCOLOR_OLIVE, SKINCOLOR_KIWI, SKINCOLOR_LEMON, SKINCOLOR_LIME, - SKINCOLOR_MINDARO, SKINCOLOR_PERIDOT, SKINCOLOR_APPLE, SKINCOLOR_CHARTREUSE, diff --git a/src/info.c b/src/info.c index 2b6d6affb..085966b9c 100644 --- a/src/info.c +++ b/src/info.c @@ -21627,14 +21627,14 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Pumpkin", { 51, 52, 53, 54, 56, 58, 59, 59, 61, 61, 63, 45, 46, 47, 47, 31}, SKINCOLOR_ARCTIC, 10, V_ORANGEMAP, true}, // SKINCOLOR_PUMPKIN {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD - {"Topaz", { 0, 81, 72, 73, 64, 65, 66, 66, 54, 55, 57, 59, 60, 42, 43, 45}, SKINCOLOR_STONE , 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ + {"Topaz", { 0, 81, 83, 73, 74, 74, 65, 52, 53, 54, 56, 58, 60, 42, 43, 45}, SKINCOLOR_STONE , 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY + {"Goldenrod", { 0, 80, 81, 81, 83, 73, 73, 64, 65, 66, 67, 68, 69, 62, 44, 45}, SKINCOLOR_MAJESTY, 11, V_YELLOWMAP, true}, // SKINCOLOR_GOLDENROD {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW {"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE - {"Kiwi", { 88, 64, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI + {"Kiwi", { 88, 89, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI {"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 6, V_YELLOWMAP, true}, // SKINCOLOR_LEMON {"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME - {"Mindaro", { 0, 80, 81, 82, 83, 64, 188, 189, 189, 190, 115, 116, 117, 118, 119, 111}, SKINCOLOR_MAJESTY, 11, V_PERIDOTMAP, true}, // SKINCOLOR_MINDARO {"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT {"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 12, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE @@ -21647,7 +21647,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 7, V_GREENMAP, true}, // SKINCOLOR_EMERALD {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 12, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE - {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM + {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8b, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM {"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA {"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL @@ -21670,10 +21670,10 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 166, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY {"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR {"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK - {"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_MINDARO, 11, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY + {"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_GOLDENROD, 11, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY {"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL {"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE - {"Noble", { 144, 146, 147, 148, 148, 164, 164, 165, 165, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE + {"Noble", { 144, 146, 147, 148, 149, 164, 164, 165, 166, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 6, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 183, 165, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM {"Crystal", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_CRYSTAL @@ -21689,7 +21689,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY {"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY - {"Sangria", { 210, 32, 33, 34, 35, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 7, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA + {"Sangria", { 210, 32, 33, 34, 34, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 7, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA {"Volcanic", { 35, 38, 41, 42, 44, 46, 46, 169, 169, 159, 253, 254, 30, 30, 31, 31}, SKINCOLOR_BRONZE, 9, V_REDMAP, true}, // SKINCOLOR_VOLCANIC // super diff --git a/src/st_stuff.c b/src/st_stuff.c index dcab2bb9c..484216e30 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1751,43 +1751,21 @@ static void ST_drawNightsRecords(void) } } -// 2.0-1: [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold -/*#define NUMLINKCOLORS 14 -static skincolornum_t linkColor[NUMLINKCOLORS] = -{SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_AZURE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE, - SKINCOLOR_MAGENTA, SKINCOLOR_SILVER, SKINCOLOR_SUPERGOLD4, SKINCOLOR_PINK, SKINCOLOR_RED, - SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD};*/ - -// 2.2 indev list: (unix time 1470866042) Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot -/*#define NUMLINKCOLORS 13 -static skincolornum_t linkColor[NUMLINKCOLORS] = -{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_BLUE, SKINCOLOR_PASTEL, - SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, - SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT};*/ - -// 2.2 indev list again: [19:59:52] Ruby > Red > Flame > Sunset > Orange > Gold > Yellow > Lime > Green > Aqua > cyan > Sky > Blue > Pastel > Purple > Bubblegum > Magenta > Rosy > repeat -// [20:00:25] Also Icy for the link freeze text color -// [20:04:03] I would start it on lime -/*#define NUMLINKCOLORS 18 -static skincolornum_t linkColor[NUMLINKCOLORS] = -{SKINCOLOR_LIME, SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_CYAN, SKINCOLOR_SKY, - SKINCOLOR_SAPPHIRE, SKINCOLOR_PASTEL, SKINCOLOR_PURPLE, SKINCOLOR_BUBBLEGUM, SKINCOLOR_MAGENTA, - SKINCOLOR_ROSY, SKINCOLOR_RUBY, SKINCOLOR_RED, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, - SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW};*/ - -// 2.2+ list for real this time: https://wiki.srb2.org/wiki/User:Rob/Sandbox (check history around 31/10/17, spoopy) +// NiGHTS link colors; 3 sets with increasingly fancy colors (1 to 299, 300 to 599, 600 and above) #define NUMLINKCOLORS 12 -static skincolornum_t linkColor[2][NUMLINKCOLORS] = { -{SKINCOLOR_EMERALD, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, +static skincolornum_t linkColor[3][NUMLINKCOLORS] = { +{SKINCOLOR_SHAMROCK, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}, -{SKINCOLOR_SEAFOAM, SKINCOLOR_CYAN, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_VAPOR, SKINCOLOR_BUBBLEGUM, - SKINCOLOR_VIOLET, SKINCOLOR_RUBY, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, SKINCOLOR_SANDY, SKINCOLOR_LIME}}; +{SKINCOLOR_EMERALD, SKINCOLOR_AQUAMARINE, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_GALAXY, SKINCOLOR_CRYSTAL, + SKINCOLOR_TAFFY, SKINCOLOR_RUBY, SKINCOLOR_GARNET, SKINCOLOR_TOPAZ, SKINCOLOR_LEMON, SKINCOLOR_LIME}, +{SKINCOLOR_ISLAND, SKINCOLOR_TURQUOISE, SKINCOLOR_DREAM, SKINCOLOR_DAYBREAK, SKINCOLOR_VAPOR, SKINCOLOR_FUCHSIA, + SKINCOLOR_VIOLET, SKINCOLOR_EVENTIDE, SKINCOLOR_KETCHUP, SKINCOLOR_FOUNDATION, SKINCOLOR_HEADLIGHT, SKINCOLOR_CHARTREUSE}}; static void ST_drawNiGHTSLink(void) { static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0}; const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0); - INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? 1 : 0); + INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? (stplyr->linkcount-1 >= 600) ? 2 : 1 : 0); skincolornum_t colornum; fixed_t x, y, scale; From 73eb8fc358bc0d474b28369d5d48b7953e1111d5 Mon Sep 17 00:00:00 2001 From: spherallic Date: Mon, 13 Mar 2023 19:52:41 +0100 Subject: [PATCH 178/478] A couple more changes: - Swapped invcolors of new character skincolors - Renamed Stone to Meteorite & changed text color to gray - Tweaked some colors' invshades --- src/deh_tables.c | 2 +- src/doomdef.h | 2 +- src/info.c | 92 ++++++++++++++++++++++++------------------------ 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 268a18ad4..d53680c19 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4609,7 +4609,7 @@ const char *COLOR_ENUMS[] = { // Desaturated "AETHER", // SKINCOLOR_AETHER, "SLATE", // SKINCOLOR_SLATE, - "STONE", // SKINCOLOR_STONE, + "METEORITE", // SKINCOLOR_METEORITE, "MERCURY", // SKINCOLOR_MERCURY, "BLUEBELL", // SKINCOLOR_BLUEBELL, "PINK", // SKINCOLOR_PINK, diff --git a/src/doomdef.h b/src/doomdef.h index 31cdac9c4..20b87f230 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -261,7 +261,7 @@ typedef enum // Desaturated SKINCOLOR_AETHER, SKINCOLOR_SLATE, - SKINCOLOR_STONE, + SKINCOLOR_METEORITE, SKINCOLOR_MERCURY, SKINCOLOR_BLUEBELL, SKINCOLOR_PINK, diff --git a/src/info.c b/src/info.c index 085966b9c..5a304240d 100644 --- a/src/info.c +++ b/src/info.c @@ -21584,76 +21584,76 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Black", {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, SKINCOLOR_WHITE, 7, V_GRAYMAP, true}, // SKINCOLOR_BLACK // Desaturated - {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER - {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE - {"Stone", { 0, 4, 8, 9, 11, 12, 14, 15, 171, 172, 173, 174, 175, 27, 29, 31}, SKINCOLOR_TOPAZ, 15, 0, true}, // SKINCOLOR_STONE - {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY - {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL - {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK - {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD - {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT - {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 12, V_BROWNMAP, true}, // SKINCOLOR_LATTE - {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN - {"Boulder", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BOULDER - {"Bronze", { 82, 84, 50, 51, 223, 228, 230, 232, 234, 236, 237, 238, 239, 239, 30, 31}, SKINCOLOR_VOLCANIC, 9, V_BROWNMAP, true}, // SKINCOLOR_BRONZE - {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD, 5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA - {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU - {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN - {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE - {"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT, 5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH - {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS - {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE - {"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH, 5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT - {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER + {"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER + {"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE + {"Meteorite", { 0, 4, 8, 9, 11, 12, 14, 15, 171, 172, 173, 174, 175, 27, 29, 31}, SKINCOLOR_TOPAZ, 15, V_GRAYMAP, true}, // SKINCOLOR_METEORITE + {"Mercury", { 0, 3, 4, 7, 11, 12, 14, 15, 171, 172, 173, 155, 157, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_AZUREMAP, true}, // SKINCOLOR_MERCURY + {"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL + {"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK + {"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD + {"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT + {"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 12, V_BROWNMAP, true}, // SKINCOLOR_LATTE + {"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN + {"Boulder", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BOULDER + {"Bronze", { 82, 84, 50, 51, 223, 228, 230, 232, 234, 236, 237, 238, 239, 239, 30, 31}, SKINCOLOR_VOLCANIC, 9, V_BROWNMAP, true}, // SKINCOLOR_BRONZE + {"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD, 5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA + {"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_MERCURY, 15, V_BROWNMAP, true}, // SKINCOLOR_ECRU + {"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN + {"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE + {"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT, 5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH + {"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS + {"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE + {"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH, 5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT + {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER // Viv's vivid colours (toast 21/07/17) // Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22) {"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY {"Cherry", { 202, 203, 204, 205, 206, 40, 41, 42, 43, 44, 186, 187, 28, 29, 30, 31}, SKINCOLOR_MIDNIGHT, 10, V_REDMAP, true}, // SKINCOLOR_CHERRY {"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON - {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_PEPPER - {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED + {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_PEPPER + {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_RED {"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON {"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME - {"Garnet", { 0, 83, 50, 53, 34, 35, 37, 38, 39, 40, 42, 44, 45, 46, 47, 47}, SKINCOLOR_AQUAMARINE, 8, V_REDMAP, true}, // SKINCOLOR_GARNET + {"Garnet", { 0, 83, 50, 53, 34, 35, 37, 38, 39, 40, 42, 44, 45, 46, 47, 47}, SKINCOLOR_AQUAMARINE, 6, V_REDMAP, true}, // SKINCOLOR_GARNET {"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BOULDER, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP {"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY {"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL - {"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 195, 196, 186, 187, 30}, SKINCOLOR_DREAM, 9, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION + {"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 195, 196, 186, 187, 30}, SKINCOLOR_DREAM, 6, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION {"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET {"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER {"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT {"Orange", { 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 42, 44, 45, 46, 46}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE - {"Pumpkin", { 51, 52, 53, 54, 56, 58, 59, 59, 61, 61, 63, 45, 46, 47, 47, 31}, SKINCOLOR_ARCTIC, 10, V_ORANGEMAP, true}, // SKINCOLOR_PUMPKIN + {"Pumpkin", { 51, 52, 53, 54, 56, 58, 59, 59, 61, 61, 63, 45, 46, 47, 47, 31}, SKINCOLOR_ARCTIC, 12, V_ORANGEMAP, true}, // SKINCOLOR_PUMPKIN {"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST - {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD - {"Topaz", { 0, 81, 83, 73, 74, 74, 65, 52, 53, 54, 56, 58, 60, 42, 43, 45}, SKINCOLOR_STONE , 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ + {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLD + {"Topaz", { 0, 81, 83, 73, 74, 74, 65, 52, 53, 54, 56, 58, 60, 42, 43, 45}, SKINCOLOR_METEORITE, 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ {"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY - {"Goldenrod", { 0, 80, 81, 81, 83, 73, 73, 64, 65, 66, 67, 68, 69, 62, 44, 45}, SKINCOLOR_MAJESTY, 11, V_YELLOWMAP, true}, // SKINCOLOR_GOLDENROD + {"Goldenrod", { 0, 80, 81, 81, 83, 73, 73, 64, 65, 66, 67, 68, 69, 62, 44, 45}, SKINCOLOR_MAJESTY, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLDENROD {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW {"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE {"Kiwi", { 88, 89, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI - {"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 6, V_YELLOWMAP, true}, // SKINCOLOR_LEMON + {"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 8, V_YELLOWMAP, true}, // SKINCOLOR_LEMON {"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME {"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT {"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE - {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 12, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE - {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN + {"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE + {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_GREEN {"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST {"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_CRYSTAL, 10, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK - {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_TAFFY, 10, V_GREENMAP, true}, // SKINCOLOR_JADE - {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT + {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_ROSY, 7, V_GREENMAP, true}, // SKINCOLOR_JADE + {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT {"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT - {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER - {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 7, V_GREENMAP, true}, // SKINCOLOR_EMERALD - {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 12, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE + {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_MASTER + {"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 9, V_GREENMAP, true}, // SKINCOLOR_EMERALD + {"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE {"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8b, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM {"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND - {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA + {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_TAFFY, 10, V_AQUAMAP, true}, // SKINCOLOR_AQUA {"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL {"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE {"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN - {"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 7, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE + {"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 12, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE {"Aquamarine", { 0, 120, 121, 131, 132, 133, 134, 134, 135, 135, 149, 149, 172, 173, 174, 175}, SKINCOLOR_GARNET, 8, V_SKYMAP, true}, // SKINCOLOR_AQUAMARINE {"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY {"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_KIWI, 13, V_SKYMAP, true}, // SKINCOLOR_MARINE @@ -21662,7 +21662,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY {"Daybreak", { 80, 81, 82, 72, 64, 9, 11, 171, 149, 150, 151, 153, 156, 157, 159, 253}, SKINCOLOR_EVENTIDE, 12, V_BLUEMAP, true}, // SKINCOLOR_DAYBREAK {"Sapphire", {0x80, 0x82, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE - {"Arctic", { 0, 1, 3, 4, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 10, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC + {"Arctic", { 0, 1, 3, 4, 146, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_PUMPKIN, 6, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC {"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER {"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE {"Cobalt", { 145, 147, 149, 150, 151, 153, 154, 155, 156, 157, 158, 159, 253, 253, 254, 254}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT @@ -21670,11 +21670,11 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 166, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY {"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR {"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK - {"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_GOLDENROD, 11, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY + {"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_GOLDENROD, 9, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY {"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL {"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE {"Noble", { 144, 146, 147, 148, 149, 164, 164, 165, 166, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE - {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 6, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA + {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 10, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 183, 165, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM {"Crystal", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_CRYSTAL {"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA @@ -21682,14 +21682,14 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET {"Royal", { 208, 209, 192, 192, 192, 193, 193, 194, 194, 172, 173, 174, 175, 175, 139, 139}, SKINCOLOR_FANCY, 9, V_PURPLEMAP, true}, // SKINCOLOR_ROYAL {"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC - {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE + {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE {"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 13, V_MAGENTAMAP, true}, // SKINCOLOR_EVENTIDE {"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY - {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY - {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY + {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_TAFFY + {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_ROSY {"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY - {"Sangria", { 210, 32, 33, 34, 34, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 7, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA + {"Sangria", { 210, 32, 33, 34, 34, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 12, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA {"Volcanic", { 35, 38, 41, 42, 44, 46, 46, 169, 169, 159, 253, 254, 30, 30, 31, 31}, SKINCOLOR_BRONZE, 9, V_REDMAP, true}, // SKINCOLOR_VOLCANIC // super From b97f0a8643dc59e9ffd78d73c848138d8882c06d Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 28 Mar 2023 20:10:53 +0200 Subject: [PATCH 179/478] Fix MT_NIGHTSCORE color cycling, using link colors --- src/p_inter.c | 39 ++++++++------------------------------- src/p_mobj.c | 2 +- src/st_stuff.c | 16 ++++++++-------- src/st_stuff.h | 3 +++ 4 files changed, 20 insertions(+), 40 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 046a0a198..c66c4e10e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -255,42 +255,19 @@ void P_DoNightsScore(player_t *player) player->linktimer = nightslinktics; } - if (player->linkcount < 10) - { - if (player->bonustime) - { - P_AddPlayerScore(player, player->linkcount*20); - P_SetMobjState(dummymo, dummymo->info->xdeathstate+player->linkcount-1); - } - else - { - P_AddPlayerScore(player, player->linkcount*10); - P_SetMobjState(dummymo, dummymo->info->spawnstate+player->linkcount-1); - } - } - else - { - if (player->bonustime) - { - P_AddPlayerScore(player, 200); - P_SetMobjState(dummymo, dummymo->info->xdeathstate+9); - } - else - { - P_AddPlayerScore(player, 100); - P_SetMobjState(dummymo, dummymo->info->spawnstate+9); - } - } + // Award 10-100 score, doubled if bonus time is active + P_AddPlayerScore(player, min(player->linkcount,10)*(player->bonustime ? 20 : 10)); + P_SetMobjState(dummymo, (player->bonustime ? dummymo->info->xdeathstate : dummymo->info->spawnstate) + min(player->linkcount,10)-1); - // Hoops are the only things that should add to your drill meter - //player->drillmeter += TICRATE; + // Make objects slowly rise & scale up dummymo->momz = FRACUNIT; dummymo->fuse = 3*TICRATE; - - // What?! NO, don't use the camera! Scale up instead! - //P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera.x, camera.y), 3*FRACUNIT); dummymo->scalespeed = FRACUNIT/25; dummymo->destscale = 2*FRACUNIT; + + // Add extra values used for color variety + dummymo->extravalue1 = player->linkcount-1; + dummymo->extravalue2 = ((player->linkcount-1 >= 300) ? (player->linkcount-1 >= 600) ? 2 : 1 : 0); } // diff --git a/src/p_mobj.c b/src/p_mobj.c index 3eab29c09..a43afc9b1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9603,7 +9603,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) case MT_BOSSFLYPOINT: return false; case MT_NIGHTSCORE: - mobj->color = (UINT16)(leveltime % SKINCOLOR_WHITE); + mobj->color = linkColor[mobj->extravalue2][(leveltime + mobj->extravalue1) % NUMLINKCOLORS]; break; case MT_JETFUME1: if (!P_JetFume1Think(mobj)) diff --git a/src/st_stuff.c b/src/st_stuff.c index 484216e30..3ce1cbfd8 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -170,6 +170,14 @@ hudinfo_t hudinfo[NUMHUDITEMS] = static huddrawlist_h luahuddrawlist_game[2]; static huddrawlist_h luahuddrawlist_titlecard; +skincolornum_t linkColor[3][NUMLINKCOLORS] = { +{SKINCOLOR_SHAMROCK, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, + SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}, +{SKINCOLOR_EMERALD, SKINCOLOR_AQUAMARINE, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_GALAXY, SKINCOLOR_CRYSTAL, + SKINCOLOR_TAFFY, SKINCOLOR_RUBY, SKINCOLOR_GARNET, SKINCOLOR_TOPAZ, SKINCOLOR_LEMON, SKINCOLOR_LIME}, +{SKINCOLOR_ISLAND, SKINCOLOR_TURQUOISE, SKINCOLOR_DREAM, SKINCOLOR_DAYBREAK, SKINCOLOR_VAPOR, SKINCOLOR_FUCHSIA, + SKINCOLOR_VIOLET, SKINCOLOR_EVENTIDE, SKINCOLOR_KETCHUP, SKINCOLOR_FOUNDATION, SKINCOLOR_HEADLIGHT, SKINCOLOR_CHARTREUSE}}; + // // STATUS BAR CODE // @@ -1752,14 +1760,6 @@ static void ST_drawNightsRecords(void) } // NiGHTS link colors; 3 sets with increasingly fancy colors (1 to 299, 300 to 599, 600 and above) -#define NUMLINKCOLORS 12 -static skincolornum_t linkColor[3][NUMLINKCOLORS] = { -{SKINCOLOR_SHAMROCK, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, - SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}, -{SKINCOLOR_EMERALD, SKINCOLOR_AQUAMARINE, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_GALAXY, SKINCOLOR_CRYSTAL, - SKINCOLOR_TAFFY, SKINCOLOR_RUBY, SKINCOLOR_GARNET, SKINCOLOR_TOPAZ, SKINCOLOR_LEMON, SKINCOLOR_LIME}, -{SKINCOLOR_ISLAND, SKINCOLOR_TURQUOISE, SKINCOLOR_DREAM, SKINCOLOR_DAYBREAK, SKINCOLOR_VAPOR, SKINCOLOR_FUCHSIA, - SKINCOLOR_VIOLET, SKINCOLOR_EVENTIDE, SKINCOLOR_KETCHUP, SKINCOLOR_FOUNDATION, SKINCOLOR_HEADLIGHT, SKINCOLOR_CHARTREUSE}}; static void ST_drawNiGHTSLink(void) { diff --git a/src/st_stuff.h b/src/st_stuff.h index 68ac900f7..603be3c30 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -124,4 +124,7 @@ extern hudinfo_t hudinfo[NUMHUDITEMS]; extern UINT16 objectsdrawn; +#define NUMLINKCOLORS 12 +extern skincolornum_t linkColor[3][NUMLINKCOLORS]; + #endif From 1a956667a74c8619333076d68c94f177b5f5082f Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 29 Mar 2023 15:50:03 +0200 Subject: [PATCH 180/478] Small tweak to Bubblegum --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 5a304240d..32b21b702 100644 --- a/src/info.c +++ b/src/info.c @@ -21675,7 +21675,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE {"Noble", { 144, 146, 147, 148, 149, 164, 164, 165, 166, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE {"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 10, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA - {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 183, 165, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM + {"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 182, 164, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM {"Crystal", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_CRYSTAL {"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA {"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON From 867a5e0d47180c068a5819e0b3e6d054e999d000 Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 20 Jun 2023 21:48:26 +0200 Subject: [PATCH 181/478] Correct misplaced comment on NiGHTS link colors --- src/st_stuff.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 3ce1cbfd8..9cac145a7 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -170,6 +170,7 @@ hudinfo_t hudinfo[NUMHUDITEMS] = static huddrawlist_h luahuddrawlist_game[2]; static huddrawlist_h luahuddrawlist_titlecard; +// NiGHTS link colors; 3 sets with increasingly fancy colors (1 to 299, 300 to 599, 600 and above) skincolornum_t linkColor[3][NUMLINKCOLORS] = { {SKINCOLOR_SHAMROCK, SKINCOLOR_AQUA, SKINCOLOR_SKY, SKINCOLOR_BLUE, SKINCOLOR_PURPLE, SKINCOLOR_MAGENTA, SKINCOLOR_ROSY, SKINCOLOR_RED, SKINCOLOR_ORANGE, SKINCOLOR_GOLD, SKINCOLOR_YELLOW, SKINCOLOR_PERIDOT}, @@ -1759,8 +1760,6 @@ static void ST_drawNightsRecords(void) } } -// NiGHTS link colors; 3 sets with increasingly fancy colors (1 to 299, 300 to 599, 600 and above) - static void ST_drawNiGHTSLink(void) { static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0}; From e88b3542c72516c94d9257c4c79852dca58e8791 Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 22 Jun 2023 14:02:31 +0200 Subject: [PATCH 182/478] Update UZB/UDMF configuration files --- extras/conf/udb/Includes/SRB222_common.cfg | 152 +- extras/conf/udb/Includes/SRB222_linedefs.cfg | 1810 +------- extras/conf/udb/Includes/SRB222_misc.cfg | 356 +- extras/conf/udb/Includes/SRB222_sectors.cfg | 107 - extras/conf/udb/Includes/SRB222_things.cfg | 3927 +++--------------- extras/conf/udb/SRB2_22Doom.cfg | 32 - 6 files changed, 751 insertions(+), 5633 deletions(-) delete mode 100644 extras/conf/udb/Includes/SRB222_sectors.cfg delete mode 100644 extras/conf/udb/SRB2_22Doom.cfg diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index 0ff044a6d..9a574d6f2 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -15,7 +15,7 @@ common ignoredextensions = "wad pk3 pk7 bak backup1 backup2 backup3 zip rar 7z"; // Default testing parameters - testparameters = "-file \"%AP\" \"%F\" -warp %L"; + testparameters = "-folder \"%AF\" -file \"%AA\" \"%F\" -warp %L"; testshortpaths = true; // Action special help @@ -26,7 +26,7 @@ common generalizedsectors = true; // Maximum safe map size check (0 means skip check) - safeboundary = 1; + safeboundary = 0; // Map boundaries. Map objects can only be placed within these boundaries leftboundary = -32768; @@ -40,6 +40,8 @@ common defaultflatscale = 1.0f; scaledtextureoffsets = true; + maxcolormapalpha = 25; + // Thing number for start position in 3D Mode start3dmode = 3328; @@ -68,137 +70,6 @@ common } } -mapformat_doom -{ - // The format interface handles the map data format - formatinterface = "DoomMapSetIO"; - - // Default nodebuilder configurations - defaultsavecompiler = "zennode_normal"; - defaulttestcompiler = "zennode_fast"; - - /* - GAME DETECT PATTERN - Used to guess the game for which a WAD file is made. - - 1 = One of these lumps must exist - 2 = None of these lumps must exist - 3 = All of these lumps must exist - */ - - gamedetect - { - EXTENDED = 2; - - - BEHAVIOR = 2; - - E#M# = 2; - - MAP?? = 1; - } - - /* - MAP LUMP NAMES - Map lumps are loaded with the map as long as they are right after each other. When the editor - meets a lump which is not defined in this list it will ignore the map if not satisfied. - The order of items defines the order in which lumps will be written to WAD file on save. - To indicate the map header lump, use ~MAP - - Legenda: - required = Lump is required to exist. - blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) - nodebuild = The nodebuilder generates this lump. - allowempty = The nodebuilder is allowed to leave this lump empty. - script = This lump is a text-based script. Specify the filename of the script configuration to use. - */ - - maplumpnames - { - include("SRB222_misc.cfg", "doommaplumpnames"); - } - - // When this is set to true, sectors with the same tag will light up when a line is highlighted - linetagindicatesectors = true; - - // Special linedefs - include("SRB222_misc.cfg", "speciallinedefs"); - - // Default flags for first new thing - defaultthingflags - { - } - - // DEFAULT SECTOR BRIGHTNESS LEVELS - sectorbrightness - { - include("SRB222_misc.cfg", "sectorbrightness"); - } - - // SECTOR TYPES - sectortypes - { - include("SRB222_sectors.cfg", "sectortypes"); - } - - // GENERALISED SECTOR TYPES - gen_sectortypes - { - include("SRB222_sectors.cfg", "gen_sectortypes"); - } - - // LINEDEF FLAGS - linedefflags - { - include("SRB222_misc.cfg", "linedefflags"); - } - - // Linedef flags UDMF translation table - // This is needed for copy/paste and prefabs to work properly - // When the UDMF field name is prefixed with ! it is inverted - linedefflagstranslation - { - include("SRB222_misc.cfg", "linedefflagstranslation"); - } - - // LINEDEF ACTIVATIONS - linedefactivations - { - } - - // LINEDEF TYPES - linedeftypes - { - include("SRB222_linedefs.cfg", "doom"); - } - - // THING FLAGS - thingflags - { - include("SRB222_misc.cfg", "thingflags"); - } - - // Thing flags UDMF translation table - // This is needed for copy/paste and prefabs to work properly - // When the UDMF field name is prefixed with ! it is inverted - thingflagstranslation - { - include("SRB222_misc.cfg", "thingflagstranslation"); - } - - // THING FLAGS ERROR MASK - // Mask for the thing flags which indicates the options - // that make the same thing appear in the same modes - thingflagsmask1 = 7; // 1 + 2 + 4 - thingflagsmask2 = 0; - - // THING TYPES - thingtypes - { - include("SRB222_things.cfg", "doom"); - } -} - mapformat_udmf { // The format interface handles the map data format @@ -222,9 +93,17 @@ mapformat_udmf { include("SRB222_misc.cfg", "universalfields"); } + + // Disable Doom-related modes that don't make sense for SRB2 + soundsupport = false; + automapsupport = false; // When this is set to true, sectors with the same tag will light up when a line is highlighted linetagindicatesectors = false; + localsidedeftextureoffsets = false; + distinctfloorandceilingbrightness = true; + + planeequationsupport = true; // Special linedefs include("SRB222_misc.cfg", "speciallinedefs_udmf"); @@ -240,6 +119,11 @@ mapformat_udmf include("SRB222_misc.cfg", "sectorflags"); } + sectorflagscategories + { + include("SRB222_misc.cfg", "sectorflagscategories"); + } + // DEFAULT SECTOR BRIGHTNESS LEVELS sectorbrightness { @@ -247,6 +131,7 @@ mapformat_udmf } damagetypes = "Generic Water Fire Lava Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage"; + triggerertypes = "Player AllPlayers Mobj"; // LINEDEF FLAGS linedefflags @@ -282,7 +167,6 @@ mapformat_udmf // How to compare thing flags (for the stuck things error checker) thingflagscompare { - include("UDMF_misc.cfg", "thingflagscompare"); } // THING TYPES diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index b526e84e7..621b4abd5 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1,1793 +1,3 @@ -doom -{ - misc - { - title = "Miscellaneous"; - - 0 - { - title = "None"; - prefix = "(0)"; - } - 1 - { - title = "Per-Sector Gravity"; - prefix = "(1)"; - } - 5 - { - title = "Camera Scanner "; - prefix = "(5)"; - } - 7 - { - title = "Sector Flat Alignment"; - prefix = "(7)"; - } - 10 - { - title = "Culling Plane"; - prefix = "(10)"; - } - 13 - { - title = "Heat Wave Effect"; - prefix = "(13)"; - } - 40 - { - title = "Visual Portal Between Tagged Linedefs"; - prefix = "(40)"; - } - 41 - { - title = "Horizon Effect"; - prefix = "(41)"; - } - 50 - { - title = "Instantly Lower Floor on Level Load"; - prefix = "(50)"; - } - 51 - { - title = "Instantly Raise Ceiling on Level Load"; - prefix = "(51)"; - } - 63 - { - title = "Fake Floor/Ceiling Planes"; - prefix = "(63)"; - } - 540 - { - title = "Floor Friction"; - prefix = "(540)"; - } - } - - parameters - { - title = "Parameters"; - - 2 - { - title = "Custom Exit"; - prefix = "(2)"; - } - 3 - { - title = "Zoom Tube Parameters"; - prefix = "(3)"; - } - 4 - { - title = "Speed Pad Parameters"; - prefix = "(4)"; - } - 8 - { - title = "Special Sector Properties"; - prefix = "(8)"; - } - 9 - { - title = "Chain Parameters"; - prefix = "(9)"; - } - 11 - { - title = "Rope Hang Parameters"; - prefix = "(11)"; - } - 12 - { - title = "Rock Spawner Parameters"; - prefix = "(12)"; - } - 14 - { - title = "Bustable Block Parameters"; - prefix = "(14)"; - } - 15 - { - title = "Fan Particle Spawner Parameters"; - prefix = "(15)"; - } - 16 - { - title = "Minecart Parameters"; - prefix = "(16)"; - } - 64 - { - title = "Continuously Appearing/Disappearing FOF"; - prefix = "(64)"; - } - 76 - { - title = "Make FOF Bouncy"; - prefix = "(76)"; - } - } - - polyobject - { - title = "PolyObject"; - - 20 - { - title = "First Line"; - prefix = "(20)"; - } - 21 - { - title = "Explicitly Include Line "; - prefix = "(21)"; - } - 22 - { - title = "Parameters"; - prefix = "(22)"; - } - 30 - { - title = "Waving Flag"; - prefix = "(30)"; - } - 31 - { - title = "Displacement by Front Sector"; - prefix = "(31)"; - } - 32 - { - title = "Angular Displacement by Front Sector"; - prefix = "(32)"; - } - } - - planemove - { - title = "Plane Movement"; - - 52 - { - title = "Continuously Falling Sector"; - prefix = "(52)"; - } - 53 - { - title = "Continuous Floor/Ceiling Mover"; - prefix = "(53)"; - } - 54 - { - title = "Continuous Floor Mover"; - prefix = "(54)"; - } - 55 - { - title = "Continuous Ceiling Mover"; - prefix = "(55)"; - } - 56 - { - title = "Continuous Two-Speed Floor/Ceiling Mover"; - prefix = "(56)"; - } - 57 - { - title = "Continuous Two-Speed Floor Mover"; - prefix = "(57)"; - } - 58 - { - title = "Continuous Two-Speed Ceiling Mover"; - prefix = "(58)"; - } - 59 - { - title = "Activate Moving Platform"; - prefix = "(59)"; - } - 60 - { - title = "Activate Moving Platform (Adjustable Speed)"; - prefix = "(60)"; - } - 61 - { - title = "Crusher (Ceiling to Floor)"; - prefix = "(61)"; - } - 62 - { - title = "Crusher (Floor to Ceiling)"; - prefix = "(62)"; - } - 66 - { - title = "Move Floor by Displacement"; - prefix = "(66)"; - } - 67 - { - title = "Move Ceiling by Displacement"; - prefix = "(67)"; - } - 68 - { - title = "Move Floor and Ceiling by Displacement"; - prefix = "(68)"; - } - } - - fofsolid - { - title = "FOF (solid)"; - - 100 - { - title = "Solid, Opaque"; - prefix = "(100)"; - } - 101 - { - title = "Solid, Opaque, No Shadow"; - prefix = "(101)"; - } - 102 - { - title = "Solid, Translucent"; - prefix = "(102)"; - } - 103 - { - title = "Solid, Sides Only"; - prefix = "(103)"; - } - 104 - { - title = "Solid, No Sides"; - prefix = "(104)"; - } - 105 - { - title = "Solid, Invisible"; - prefix = "(105)"; - } - 140 - { - title = "Intangible from Bottom, Opaque"; - prefix = "(140)"; - } - 141 - { - title = "Intangible from Bottom, Translucent"; - prefix = "(141)"; - } - 142 - { - title = "Intangible from Bottom, Translucent, No Sides"; - prefix = "(142)"; - } - 143 - { - title = "Intangible from Top, Opaque"; - prefix = "(143)"; - } - 144 - { - title = "Intangible from Top, Translucent"; - prefix = "(144)"; - } - 145 - { - title = "Intangible from Top, Translucent, No Sides"; - prefix = "(145)"; - } - 146 - { - title = "Only Tangible from Sides"; - prefix = "(146)"; - } - } - - fofintangible - { - title = "FOF (intangible)"; - - 120 - { - title = "Water, Opaque"; - prefix = "(120)"; - } - 121 - { - title = "Water, Translucent"; - prefix = "(121)"; - } - 122 - { - title = "Water, Opaque, No Sides"; - prefix = "(122)"; - } - 123 - { - title = "Water, Translucent, No Sides"; - prefix = "(123)"; - } - 124 - { - title = "Goo Water, Translucent"; - prefix = "(124)"; - } - 125 - { - title = "Goo Water, Translucent, No Sides"; - prefix = "(125)"; - } - 220 - { - title = "Intangible, Opaque"; - prefix = "(220)"; - } - 221 - { - title = "Intangible, Translucent"; - prefix = "(221)"; - } - 222 - { - title = "Intangible, Sides Only"; - prefix = "(222)"; - } - 223 - { - title = "Intangible, Invisible"; - prefix = "(223)"; - } - } - - fofmoving - { - title = "FOF (moving)"; - - 150 - { - title = "Air Bobbing"; - prefix = "(150)"; - } - 151 - { - title = "Air Bobbing (Adjustable)"; - prefix = "(151)"; - } - 152 - { - title = "Reverse Air Bobbing (Adjustable)"; - prefix = "(152)"; - } - 153 - { - title = "Dynamically Sinking Platform"; - prefix = "(153)"; - } - 160 - { - title = "Water Bobbing"; - prefix = "(160)"; - } - 190 - { - title = "Rising Platform, Solid, Opaque"; - prefix = "(190)"; - } - 191 - { - title = "Rising Platform, Solid, Opaque, No Shadow"; - prefix = "(191)"; - } - 192 - { - title = "Rising Platform, Solid, Translucent"; - prefix = "(192)"; - } - 193 - { - title = "Rising Platform, Solid, Invisible"; - prefix = "(193)"; - } - 194 - { - title = "Rising Platform, Intangible from Bottom, Opaque"; - prefix = "(194)"; - } - 195 - { - title = "Rising Platform, Intangible from Bottom, Translucent"; - prefix = "(195)"; - } - } - - fofcrumbling - { - title = "FOF (crumbling)"; - - 170 - { - title = "Crumbling, Respawn"; - prefix = "(170)"; - } - 171 - { - title = "Crumbling, No Respawn"; - prefix = "(171)"; - } - 172 - { - title = "Crumbling, Respawn, Intangible from Bottom"; - prefix = "(172)"; - } - 173 - { - title = "Crumbling, No Respawn, Intangible from Bottom"; - prefix = "(173)"; - } - 174 - { - title = "Crumbling, Respawn, Int. from Bottom, Translucent"; - prefix = "(174)"; - } - 175 - { - title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; - prefix = "(175)"; - } - 176 - { - title = "Crumbling, Respawn, Floating, Bobbing"; - prefix = "(176)"; - } - 177 - { - title = "Crumbling, No Respawn, Floating, Bobbing"; - prefix = "(177)"; - } - 178 - { - title = "Crumbling, Respawn, Floating"; - prefix = "(178)"; - } - 179 - { - title = "Crumbling, No Respawn, Floating"; - prefix = "(179)"; - } - 180 - { - title = "Crumbling, Respawn, Air Bobbing"; - prefix = "(180)"; - } - } - - fofspecial - { - title = "FOF (special)"; - - 200 - { - title = "Light Block"; - prefix = "(200)"; - } - 201 - { - title = "Half Light Block"; - prefix = "(201)"; - } - 202 - { - title = "Fog Block"; - prefix = "(202)"; - } - 250 - { - title = "Mario Block"; - prefix = "(250)"; - } - 251 - { - title = "Thwomp Block"; - prefix = "(251)"; - } - 252 - { - title = "Shatter Block"; - prefix = "(252)"; - } - 253 - { - title = "Shatter Block, Translucent"; - prefix = "(253)"; - } - 254 - { - title = "Bustable Block"; - prefix = "(254)"; - } - 255 - { - title = "Spin-Bustable Block"; - prefix = "(255)"; - } - 256 - { - title = "Spin-Bustable Block, Translucent"; - prefix = "(256)"; - } - 257 - { - title = "Quicksand"; - prefix = "(257)"; - } - 258 - { - title = "Laser"; - prefix = "(258)"; - } - 259 - { - title = "Custom FOF"; - prefix = "(259)"; - } - } - - linedeftrigger - { - title = "Linedef Executor Trigger"; - - 300 - { - title = "Continuous"; - prefix = "(300)"; - } - 301 - { - title = "Each Time"; - prefix = "(301)"; - } - 302 - { - title = "Once"; - prefix = "(302)"; - } - 303 - { - title = "Ring Count - Continuous"; - prefix = "(303)"; - } - 304 - { - title = "Ring Count - Once"; - prefix = "(304)"; - } - 305 - { - title = "Character Ability - Continuous"; - prefix = "(305)"; - } - 306 - { - title = "Character Ability - Each Time"; - prefix = "(306)"; - } - 307 - { - title = "Character Ability - Once"; - prefix = "(307)"; - } - 308 - { - title = "Race Only - Once"; - prefix = "(308)"; - } - 309 - { - title = "CTF Red Team - Continuous"; - prefix = "(309)"; - } - 310 - { - title = "CTF Red Team - Each Time"; - prefix = "(310)"; - } - 311 - { - title = "CTF Blue Team - Continuous"; - prefix = "(311)"; - } - 312 - { - title = "CTF Blue Team - Each Time"; - prefix = "(312)"; - } - 313 - { - title = "No More Enemies - Once"; - prefix = "(313)"; - } - 314 - { - title = "Number of Pushables - Continuous"; - prefix = "(314)"; - } - 315 - { - title = "Number of Pushables - Once"; - prefix = "(315)"; - } - 317 - { - title = "Condition Set Trigger - Continuous"; - prefix = "(317)"; - } - 318 - { - title = "Condition Set Trigger - Once"; - prefix = "(318)"; - } - 319 - { - title = "Unlockable - Continuous"; - prefix = "(319)"; - } - 320 - { - title = "Unlockable - Once"; - prefix = "(320)"; - } - 321 - { - title = "Trigger After X Calls - Continuous"; - prefix = "(321)"; - } - 322 - { - title = "Trigger After X Calls - Each Time"; - prefix = "(322)"; - } - 323 - { - title = "NiGHTSerize - Each Time"; - prefix = "(323)"; - } - 324 - { - title = "NiGHTSerize - Once"; - prefix = "(324)"; - } - 325 - { - title = "De-NiGHTSerize - Each Time"; - prefix = "(325)"; - } - 326 - { - title = "De-NiGHTSerize - Once"; - prefix = "(326)"; - } - 327 - { - title = "NiGHTS Lap - Each Time"; - prefix = "(327)"; - } - 328 - { - title = "NiGHTS Lap - Once"; - prefix = "(328)"; - } - 329 - { - title = "Ideya Capture Touch - Each Time"; - prefix = "(329)"; - } - 330 - { - title = "Ideya Capture Touch - Once"; - prefix = "(330)"; - } - 331 - { - title = "Player Skin - Continuous"; - flags64text = "[6] Disable for this skin"; - prefix = "(331)"; - } - 332 - { - title = "Player Skin - Each Time"; - prefix = "(332)"; - } - 333 - { - title = "Player Skin - Once"; - prefix = "(333)"; - } - 334 - { - title = "Object Dye - Continuous"; - prefix = "(334)"; - } - 335 - { - title = "Object Dye - Each Time"; - prefix = "(335)"; - } - 336 - { - title = "Object Dye - Once"; - prefix = "(336)"; - } - 337 - { - title = "Emerald Check - Continuous"; - prefix = "(337)"; - } - 338 - { - title = "Emerald Check - Each Time"; - prefix = "(338)"; - } - 339 - { - title = "Emerald Check - Once"; - prefix = "(339)"; - } - 340 - { - title = "NiGHTS Mare - Continuous"; - prefix = "(340)"; - } - 341 - { - title = "NiGHTS Mare - Each Time"; - prefix = "(341)"; - } - 342 - { - title = "NiGHTS Mare - Once"; - prefix = "(342)"; - } - 343 - { - title = "Gravity Check - Continuous"; - prefix = "(343)"; - } - 344 - { - title = "Gravity Check - Each Time"; - prefix = "(344)"; - } - 345 - { - title = "Gravity Check - Once"; - prefix = "(345)"; - } - 399 - { - title = "Level Load"; - prefix = "(399)"; - } - } - - linedefexecsector - { - title = "Linedef Executor (sector)"; - - 400 - { - title = "Set Tagged Sector's Floor Height/Texture"; - prefix = "(400)"; - } - 401 - { - title = "Set Tagged Sector's Ceiling Height/Texture"; - prefix = "(401)"; - } - 402 - { - title = "Copy Light Level to Tagged Sectors"; - prefix = "(402)"; - } - 408 - { - title = "Set Tagged Sector's Flats"; - prefix = "(408)"; - } - 409 - { - title = "Change Tagged Sector's Tag"; - prefix = "(409)"; - } - 410 - { - title = "Change Front Sector's Tag"; - prefix = "(410)"; - } - 416 - { - title = "Start Adjustable Flickering Light"; - prefix = "(416)"; - } - 417 - { - title = "Start Adjustable Pulsating Light"; - prefix = "(417)"; - } - 418 - { - title = "Start Adjustable Blinking Light (unsynchronized)"; - prefix = "(418)"; - } - 419 - { - title = "Start Adjustable Blinking Light (synchronized)"; - prefix = "(419)"; - } - 420 - { - title = "Fade Light Level"; - prefix = "(420)"; - } - 421 - { - title = "Stop Lighting Effect"; - prefix = "(421)"; - } - 435 - { - title = "Change Plane Scroller Direction"; - prefix = "(435)"; - } - 467 - { - title = "Set Tagged Sector's Light Level"; - prefix = "(467)"; - } - } - - linedefexecplane - { - title = "Linedef Executor (plane movement)"; - - 403 - { - title = "Move Tagged Sector's Floor"; - prefix = "(403)"; - } - 404 - { - title = "Move Tagged Sector's Ceiling"; - prefix = "(404)"; - } - 405 - { - title = "Move Floor According to Front Texture Offsets"; - prefix = "(405)"; - } - 407 - { - title = "Move Ceiling According to Front Texture Offsets"; - prefix = "(407)"; - } - 411 - { - title = "Stop Plane Movement"; - prefix = "(411)"; - } - 428 - { - title = "Start Platform Movement"; - prefix = "(428)"; - } - 429 - { - title = "Crush Ceiling Once"; - prefix = "(429)"; - } - 430 - { - title = "Crush Floor Once"; - prefix = "(430)"; - } - 431 - { - title = "Crush Floor and Ceiling Once"; - prefix = "(431)"; - } - } - - linedefexecplayer - { - title = "Linedef Executor (player/object)"; - - 412 - { - title = "Teleporter"; - prefix = "(412)"; - } - 425 - { - title = "Change Object State"; - prefix = "(425)"; - } - 426 - { - title = "Stop Object"; - prefix = "(426)"; - } - 427 - { - title = "Award Score"; - prefix = "(427)"; - } - 432 - { - title = "Enable/Disable 2D Mode"; - prefix = "(432)"; - } - 433 - { - title = "Enable/Disable Gravity Flip"; - prefix = "(433)"; - } - 434 - { - title = "Award Power-Up"; - prefix = "(434)"; - } - 437 - { - title = "Disable Player Control"; - prefix = "(437)"; - } - 438 - { - title = "Change Object Size"; - prefix = "(438)"; - } - 442 - { - title = "Change Object Type State"; - prefix = "(442)"; - } - 457 - { - title = "Track Object's Angle"; - prefix = "(457)"; - } - 458 - { - title = "Stop Tracking Object's Angle"; - prefix = "(458)"; - } - 460 - { - title = "Award Rings"; - prefix = "(460)"; - } - 461 - { - title = "Spawn Object"; - prefix = "(461)"; - } - 462 - { - title = "Stop Timer/Exit Stage in Record Attack"; - prefix = "(462)"; - } - 463 - { - title = "Dye Object"; - prefix = "(463)"; - } - 464 - { - title = "Trigger Egg Capsule"; - prefix = "(464)"; - } - 466 - { - title = "Set Level Failure State"; - prefix = "(466)"; - } - } - - linedefexecmisc - { - title = "Linedef Executor (misc.)"; - - 413 - { - title = "Change Music"; - prefix = "(413)"; - } - 414 - { - title = "Play Sound Effect"; - prefix = "(414)"; - } - 415 - { - title = "Run Script"; - prefix = "(415)"; - } - 422 - { - title = "Switch to Cut-Away View"; - prefix = "(422)"; - } - 423 - { - title = "Change Sky"; - prefix = "(423)"; - } - 424 - { - title = "Change Weather"; - prefix = "(424)"; - } - 436 - { - title = "Shatter FOF"; - prefix = "(436)"; - } - 439 - { - title = "Change Tagged Linedef's Textures"; - prefix = "(439)"; - } - 440 - { - title = "Start Metal Sonic Race"; - prefix = "(440)"; - } - 441 - { - title = "Condition Set Trigger"; - prefix = "(441)"; - } - 443 - { - title = "Call Lua Function"; - prefix = "(443)"; - } - 444 - { - title = "Earthquake"; - prefix = "(444)"; - } - 445 - { - title = "Make FOF Disappear/Reappear"; - prefix = "(445)"; - } - 446 - { - title = "Make FOF Crumble"; - prefix = "(446)"; - } - 447 - { - title = "Change Tagged Sector's Colormap"; - prefix = "(447)"; - } - 448 - { - title = "Change Skybox"; - prefix = "(448)"; - } - 449 - { - title = "Enable Bosses with Parameter"; - prefix = "(449)"; - } - 450 - { - title = "Execute Linedef Executor (specific tag)"; - prefix = "(450)"; - } - 451 - { - title = "Execute Linedef Executor (random tag in range)"; - prefix = "(451)"; - } - 452 - { - title = "Set FOF Translucency"; - prefix = "(452)"; - } - 453 - { - title = "Fade FOF"; - prefix = "(453)"; - } - 454 - { - title = "Stop Fading FOF"; - prefix = "(454)"; - } - 455 - { - title = "Fade Tagged Sector's Colormap"; - prefix = "(455)"; - } - 456 - { - title = "Stop Fading Tagged Sector's Colormap"; - prefix = "(456)"; - } - 459 - { - title = "Control Text Prompt"; - prefix = "(459)"; - } - } - - linedefexecpoly - { - title = "Linedef Executor (polyobject)"; - - 480 - { - title = "Door Slide"; - prefix = "(480)"; - } - 481 - { - title = "Door Swing"; - prefix = "(481)"; - } - 482 - { - title = "Move"; - prefix = "(482)"; - } - 483 - { - title = "Move, Override"; - prefix = "(483)"; - } - 484 - { - title = "Rotate Right"; - prefix = "(484)"; - } - 485 - { - title = "Rotate Right, Override"; - prefix = "(485)"; - } - 486 - { - title = "Rotate Left"; - prefix = "(486)"; - } - 487 - { - title = "Rotate Left, Override"; - prefix = "(487)"; - } - 488 - { - title = "Move by Waypoints"; - prefix = "(488)"; - } - 489 - { - title = "Turn Invisible, Intangible"; - prefix = "(489)"; - } - 490 - { - title = "Turn Visible, Tangible"; - prefix = "(490)"; - } - 491 - { - title = "Set Translucency"; - prefix = "(491)"; - } - 492 - { - title = "Fade Translucency"; - prefix = "(492)"; - } - } - - wallscroll - { - title = "Wall Scrolling"; - - 500 - { - title = "Scroll Wall Front Side Left"; - prefix = "(500)"; - } - 501 - { - title = "Scroll Wall Front Side Right"; - prefix = "(501)"; - } - 502 - { - title = "Scroll Wall According to Linedef"; - prefix = "(502)"; - } - 503 - { - title = "Scroll Wall According to Linedef (Accelerative)"; - prefix = "(503)"; - } - 504 - { - title = "Scroll Wall According to Linedef (Displacement)"; - prefix = "(504)"; - } - 505 - { - title = "Scroll Texture by Front Side Offsets"; - prefix = "(505)"; - } - 506 - { - title = "Scroll Texture by Back Side Offsets"; - prefix = "(506)"; - } - } - - planescroll - { - title = "Plane Scrolling"; - - 510 - { - title = "Scroll Floor Texture"; - prefix = "(510)"; - } - 511 - { - title = "Scroll Floor Texture (Accelerative)"; - prefix = "(511)"; - } - 512 - { - title = "Scroll Floor Texture (Displacement)"; - prefix = "(512)"; - } - 513 - { - title = "Scroll Ceiling Texture"; - prefix = "(513)"; - } - 514 - { - title = "Scroll Ceiling Texture (Accelerative)"; - prefix = "(514)"; - } - 515 - { - title = "Scroll Ceiling Texture (Displacement)"; - prefix = "(515)"; - } - 516 - { - title = "Scroll Floor and Ceiling Texture"; - prefix = "(516)"; - } - 517 - { - title = "Scroll Floor and Ceiling Texture (Accelerative)"; - prefix = "(517)"; - } - 518 - { - title = "Scroll Floor and Ceiling Texture (Displacement)"; - prefix = "(518)"; - } - 520 - { - title = "Carry Objects on Floor"; - prefix = "(520)"; - } - 521 - { - title = "Carry Objects on Floor (Accelerative)"; - prefix = "(521)"; - } - 522 - { - title = "Carry Objects on Floor (Displacement)"; - prefix = "(522)"; - } - 523 - { - title = "Carry Objects on Ceiling"; - prefix = "(523)"; - } - 524 - { - title = "Carry Objects on Ceiling (Accelerative)"; - prefix = "(524)"; - } - 525 - { - title = "Carry Objects on Ceiling (Displacement)"; - prefix = "(525)"; - } - 526 - { - title = "Carry Objects on Floor and Ceiling"; - prefix = "(526)"; - } - 527 - { - title = "Carry Objects on Floor and Ceiling (Accelerative)"; - prefix = "(527)"; - } - 528 - { - title = "Carry Objects on Floor and Ceiling (Displacement)"; - prefix = "(528)"; - } - 530 - { - title = "Scroll Floor Texture and Carry Objects"; - prefix = "(530)"; - } - 531 - { - title = "Scroll Floor Texture and Carry Objects (Accelerative)"; - prefix = "(531)"; - } - 532 - { - title = "Scroll Floor Texture and Carry Objects (Displacement)"; - prefix = "(532)"; - } - 533 - { - title = "Scroll Ceiling Texture and Carry Objects"; - prefix = "(533)"; - } - 534 - { - title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; - prefix = "(534)"; - } - 535 - { - title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; - prefix = "(535)"; - } - 536 - { - title = "Scroll Floor and Ceiling Texture and Carry Objects"; - prefix = "(536)"; - } - 537 - { - title = "Scroll Floor and Ceiling Texture and Carry Objects (Accelerative)"; - prefix = "(537)"; - } - 538 - { - title = "Scroll Floor and Ceiling Texture and Carry Objects (Displacement)"; - prefix = "(538)"; - } - } - - pusher - { - title = "Pusher"; - - 541 - { - title = "Wind"; - prefix = "(541)"; - } - 542 - { - title = "Upwards Wind"; - prefix = "(542)"; - } - 543 - { - title = "Downwards Wind"; - prefix = "(543)"; - } - 544 - { - title = "Current"; - prefix = "(544)"; - } - 545 - { - title = "Upwards Current"; - prefix = "(545)"; - } - 546 - { - title = "Downwards Current"; - prefix = "(546)"; - } - 547 - { - title = "Push/Pull"; - prefix = "(547)"; - } - } - - light - { - title = "Lighting"; - - 600 - { - title = "Floor Lighting"; - prefix = "(600)"; - } - 601 - { - title = "Ceiling Lighting"; - prefix = "(601)"; - } - 602 - { - title = "Adjustable Pulsating Light"; - prefix = "(602)"; - } - 603 - { - title = "Adjustable Flickering Light"; - prefix = "(603)"; - } - 604 - { - title = "Adjustable Blinking Light (unsynchronized)"; - prefix = "(604)"; - } - 605 - { - title = "Adjustable Blinking Light (synchronized)"; - prefix = "(605)"; - } - 606 - { - title = "Colormap"; - prefix = "(606)"; - } - } - - slope - { - title = "Slope"; - - 700 - { - title = "Slope Frontside Floor"; - prefix = "(700)"; - } - 701 - { - title = "Slope Frontside Ceiling"; - prefix = "(701)"; - } - 702 - { - title = "Slope Frontside Floor and Ceiling"; - prefix = "(702)"; - } - 703 - { - title = "Slope Frontside Floor and Backside Ceiling"; - prefix = "(703)"; -´ } - 704 - { - title = "Slope Frontside Floor by 3 Tagged Vertex Things"; - prefix = "(704)"; - } - 705 - { - title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; - prefix = "(705)"; - } - 710 - { - title = "Slope Backside Floor"; - prefix = "(710)"; - } - 711 - { - title = "Slope Backside Ceiling"; - prefix = "(711)"; - } - 712 - { - title = "Slope Backside Floor and Ceiling"; - prefix = "(712)"; - } - 713 - { - title = "Slope Backside Floor and Frontside Ceiling"; - prefix = "(713)"; - } - 714 - { - title = "Slope Backside Floor by 3 Tagged Vertex Things"; - prefix = "(714)"; - } - 715 - { - title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; - prefix = "(715)"; - } - 720 - { - title = "Copy Frontside Floor Slope from Line Tag"; - prefix = "(720)"; - } - 721 - { - title = "Copy Frontside Ceiling Slope from Line Tag"; - prefix = "(721)"; - } - 722 - { - title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; - prefix = "(722)"; - } - 799 - { - title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; - prefix = "(799)"; - } - } - - transwall - { - title = "Translucent Wall"; - - 900 - { - title = "90% Opaque"; - prefix = "(900)"; - } - 901 - { - title = "80% Opaque"; - prefix = "(901)"; - } - 902 - { - title = "70% Opaque"; - prefix = "(902)"; - } - 903 - { - title = "60% Opaque"; - prefix = "(903)"; - } - 904 - { - title = "50% Opaque"; - prefix = "(904)"; - } - 905 - { - title = "40% Opaque"; - prefix = "(905)"; - } - 906 - { - title = "30% Opaque"; - prefix = "(906)"; - } - 907 - { - title = "20% Opaque"; - prefix = "(907)"; - } - 908 - { - title = "10% Opaque"; - prefix = "(908)"; - } - 909 - { - title = "Fog Wall"; - prefix = "(909)"; - } - 910 - { - title = "100% Additive"; - prefix = "(910)"; - } - 911 - { - title = "90% Additive"; - prefix = "(911)"; - } - 912 - { - title = "80% Additive"; - prefix = "(912)"; - } - 913 - { - title = "70% Additive"; - prefix = "(913)"; - } - 914 - { - title = "60% Additive"; - prefix = "(914)"; - } - 915 - { - title = "50% Additive"; - prefix = "(915)"; - } - 916 - { - title = "40% Additive"; - prefix = "(916)"; - } - 917 - { - title = "30% Additive"; - prefix = "(917)"; - } - 918 - { - title = "20% Additive"; - prefix = "(918)"; - } - 919 - { - title = "10% Additive"; - prefix = "(919)"; - } - 920 - { - title = "100% Subtractive"; - prefix = "(920)"; - } - 921 - { - title = "90% Subtractive"; - prefix = "(921)"; - } - 922 - { - title = "80% Subtractive"; - prefix = "(922)"; - } - 923 - { - title = "70% Subtractive"; - prefix = "(923)"; - } - 924 - { - title = "60% Subtractive"; - prefix = "(924)"; - } - 925 - { - title = "50% Subtractive"; - prefix = "(925)"; - } - 926 - { - title = "40% Subtractive"; - prefix = "(926)"; - } - 927 - { - title = "30% Subtractive"; - prefix = "(927)"; - } - 928 - { - title = "20% Subtractive"; - prefix = "(928)"; - } - 929 - { - title = "10% Subtractive"; - prefix = "(929)"; - } - 930 - { - title = "100% Reverse Subtractive"; - prefix = "(930)"; - } - 931 - { - title = "90% Reverse Subtractive"; - prefix = "(931)"; - } - 932 - { - title = "80% Reverse Subtractive"; - prefix = "(932)"; - } - 933 - { - title = "70% Reverse Subtractive"; - prefix = "(933)"; - } - 934 - { - title = "60% Reverse Subtractive"; - prefix = "(934)"; - } - 935 - { - title = "50% Reverse Subtractive"; - prefix = "(935)"; - } - 936 - { - title = "40% Reverse Subtractive"; - prefix = "(936)"; - } - 937 - { - title = "30% Reverse Subtractive"; - prefix = "(937)"; - } - 938 - { - title = "20% Reverse Subtractive"; - prefix = "(938)"; - } - 939 - { - title = "10% Reverse Subtractive"; - prefix = "(939)"; - } - 940 - { - title = "Modulate"; - prefix = "(940)"; - } - } -} - udmf { misc @@ -2502,6 +712,7 @@ udmf { title = "Solid"; prefix = "(100)"; + id = "srb2_fofsolid"; arg0 { title = "Target sector tag"; @@ -2544,6 +755,7 @@ udmf { title = "Water"; prefix = "(120)"; + id = "srb2_fofwater"; arg0 { title = "Target sector tag"; @@ -2580,6 +792,7 @@ udmf { title = "Air Bobbing"; prefix = "(150)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2606,6 +819,7 @@ udmf { title = "Water Bobbing"; prefix = "(160)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2617,6 +831,7 @@ udmf { title = "Crumbling"; prefix = "(170)"; + id = "srb2_fofcrumbling"; arg0 { title = "Target sector tag"; @@ -2653,11 +868,12 @@ udmf } } } - + 190 { title = "Rising"; prefix = "(190)"; + id = "srb2_fofsolid"; arg0 { title = "Target sector tag"; @@ -2714,6 +930,7 @@ udmf { title = "Light Block"; prefix = "(200)"; + id = "srb2_foflight"; arg0 { title = "Target sector tag"; @@ -2731,6 +948,7 @@ udmf { title = "Fog Block"; prefix = "(202)"; + id = "srb2_foffog"; arg0 { title = "Target sector tag"; @@ -2742,6 +960,7 @@ udmf { title = "Intangible"; prefix = "(220)"; + id = "srb2_fofintangible"; arg0 { title = "Target sector tag"; @@ -2778,6 +997,7 @@ udmf { title = "Intangible, Invisible"; prefix = "(223)"; + id = "srb2_fofintangibleinvisible"; arg0 { title = "Target sector tag"; @@ -2789,6 +1009,7 @@ udmf { title = "Mario Block"; prefix = "(250)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2810,6 +1031,7 @@ udmf { title = "Thwomp Block"; prefix = "(251)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2834,6 +1056,7 @@ udmf { title = "Bustable Block"; prefix = "(254)"; + id = "srb2_fofbustable"; arg0 { title = "Target sector tag"; @@ -2885,6 +1108,7 @@ udmf { title = "Quicksand"; prefix = "(257)"; + id = "srb2_fofsolidopaque"; arg0 { title = "Target sector tag"; @@ -2910,6 +1134,7 @@ udmf { title = "Laser"; prefix = "(258)"; + id = "srb2_foflaser"; arg0 { title = "Target sector tag"; @@ -2942,6 +1167,7 @@ udmf { title = "Custom"; prefix = "(259)"; + id = "srb2_fofcustom"; arg0 { title = "Target sector tag"; @@ -5686,6 +3912,7 @@ udmf { title = "Create Vertex-Based Slope"; prefix = "(704)"; + id = "srb2_vertexslope"; arg0 { title = "Plane"; @@ -5729,6 +3956,7 @@ udmf { title = "Copy Slope"; prefix = "(720)"; + id = "plane_copy"; arg0 { title = "Front floor tag"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index ed0488a3f..e274fece6 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -1,24 +1,3 @@ -linedefflags -{ - 1 = "[0] Impassable"; - 2 = "[1] Block Enemies"; - 4 = "[2] Double-Sided"; - 8 = "[3] Upper Unpegged"; - 16 = "[4] Lower Unpegged"; - 32 = "[5] Slope Skew (E1)"; - 64 = "[6] Not Climbable"; - 128 = "[7] No Midtexture Skew (E2)"; - 256 = "[8] Peg Midtexture (E3)"; - 512 = "[9] Solid Midtexture (E4)"; - 1024 = "[10] Repeat Midtexture (E5)"; - 2048 = "[11] Netgame Only"; - 4096 = "[12] No Netgame"; - 8192 = "[13] Effect 6"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - - // Linedef flags UDMF translation table // This is needed for copy/paste and prefabs to work properly // When the UDMF field name is prefixed with ! it is inverted @@ -42,7 +21,6 @@ linedefflagstranslation 32768 = "transfer"; } - linedefflags_udmf { blocking = "Impassable"; @@ -74,19 +52,13 @@ linedefrenderstyles sectorflags { - colormapfog = "Fog Planes in Colormap"; - colormapfadesprites = "Fade Fullbright in Colormap"; - colormapprotected = "Protected Colormap"; - flipspecial_nofloor = "No Trigger on Floor Touch"; - flipspecial_ceiling = "Trigger on Ceiling Touch"; - triggerspecial_touch = "Trigger on Edge Touch"; - triggerspecial_headbump = "Trigger on Headbump"; - triggerline_plane = "Linedef Trigger Requires Plane Touch"; - triggerline_mobj = "Non-Pushables Can Trigger Linedef"; invertprecip = "Invert Precipitation"; gravityflip = "Flip Objects in Reverse Gravity"; heatwave = "Heat Wave"; noclipcamera = "Intangible to the Camera"; + colormapfog = "Fog Planes"; + colormapfadesprites = "Fade Fullbright"; + colormapprotected = "Protected from Tagging"; outerspace = "Space Countdown"; doublestepup = "Ramp Sector (double step-up/down)"; nostepdown = "Non-Ramp Sector (No step-down)"; @@ -104,23 +76,59 @@ sectorflags zoomtubeend = "Zoom Tube End"; finishline = "Circuit Finish Line"; ropehang = "Rope Hang"; + jumpflip = "Flip Gravity on Jump"; + gravityoverride = "Make Reverse Gravity Temporary"; + flipspecial_nofloor = "No Trigger on Floor Touch"; + flipspecial_ceiling = "Trigger on Ceiling Touch"; + triggerspecial_touch = "Trigger on Edge Touch"; + triggerspecial_headbump = "Trigger on Headbump"; + triggerline_plane = "Linedef Trigger Requires Plane Touch"; + triggerline_mobj = "Non-Pushables Can Trigger Linedef"; } -thingflags +sectorflagscategories { - 1 = "[1] Extra"; - 2 = "[2] Flip"; - 4 = "[4] Special"; - 8 = "[8] Ambush"; + invertprecip = "regular"; + gravityflip = "regular"; + heatwave = "regular"; + noclipcamera = "regular"; + colormapfog = "colormap"; + colormapfadesprites = "colormap"; + colormapprotected = "colormap"; + outerspace = "special"; + doublestepup = "special"; + nostepdown = "special"; + speedpad = "special"; + starpostactivator = "special"; + exit = "special"; + specialstagepit = "special"; + returnflag = "special"; + redteambase = "special"; + blueteambase = "special"; + fan = "special"; + supertransform = "special"; + forcespin = "special"; + zoomtubestart = "special"; + zoomtubeend = "special"; + finishline = "special"; + ropehang = "special"; + jumpflip = "special"; + gravityoverride = "special"; + flipspecial_nofloor = "trigger"; + flipspecial_ceiling = "trigger"; + triggerspecial_touch = "trigger"; + triggerspecial_headbump = "trigger"; + triggerline_plane = "trigger"; + triggerline_mobj = "trigger"; } // THING FLAGS thingflags_udmf { flip = "Flip"; + absolutez = "Absolute Z height"; } - // Thing flags UDMF translation table // This is needed for copy/paste and prefabs to work properly // When the UDMF field name is prefixed with ! it is inverted @@ -130,9 +138,9 @@ thingflagstranslation 2 = "flip"; 4 = "special"; 8 = "ambush"; + 16 = "absolutez"; } - // DEFAULT SECTOR BRIGHTNESS LEVELS sectorbrightness { @@ -171,6 +179,8 @@ sectorbrightness 0; } +numbrightnesslevels = 32; + /* TEXTURES AND FLAT SOURCES This tells Doom Builder where to find the information for textures @@ -221,145 +231,18 @@ universalfields { sector { - lightalpha - { - type = 0; - default = 25; - } - - fadealpha - { - type = 0; - default = 25; - } - - fadestart - { - type = 0; - default = 0; - } - - fadeend - { - type = 0; - default = 33; - } - - foglighting - { - type = 3; - default = false; - } - - friction - { - type = 1; - default = 0.90625; - } - - triggertag - { - type = 15; - default = 0; - } - - triggerer - { - type = 2; - default = "Player"; - } } linedef { - arg5 - { - type = 0; - default = 0; - } - arg6 - { - type = 0; - default = 0; - } - arg7 - { - type = 0; - default = 0; - } - arg8 - { - type = 0; - default = 0; - } - arg9 - { - type = 0; - default = 0; - } - stringarg0 - { - type = 2; - default = ""; - } - stringarg1 - { - type = 2; - default = ""; - } - executordelay - { - type = 0; - default = 0; - } } sidedef { - repeatcnt - { - type = 0; - default = 0; - } } thing { - arg5 - { - type = 0; - default = 0; - } - arg6 - { - type = 0; - default = 0; - } - arg7 - { - type = 0; - default = 0; - } - arg8 - { - type = 0; - default = 0; - } - arg9 - { - type = 0; - default = 0; - } - stringarg0 - { - type = 2; - default = ""; - } - stringarg1 - { - type = 2; - default = ""; - } } } @@ -378,87 +261,6 @@ allowempty = The nodebuilder is allowed to leave this lump empty. scriptbuild = This lump is a text-based script, which should be compiled using current script compiler; script = This lump is a text-based script. Specify the filename of the script configuration to use. */ - -doommaplumpnames -{ - ~MAP - { - required = true; - blindcopy = true; - nodebuild = false; - } - - THINGS - { - required = true; - nodebuild = true; - allowempty = true; - } - - LINEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - SIDEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - VERTEXES - { - required = true; - nodebuild = true; - allowempty = false; - } - - SEGS - { - required = false; - nodebuild = true; - allowempty = false; - } - - SSECTORS - { - required = false; - nodebuild = true; - allowempty = false; - } - - NODES - { - required = false; - nodebuild = true; - allowempty = false; - } - - SECTORS - { - required = true; - nodebuild = true; - allowempty = false; - } - - REJECT - { - required = false; - nodebuild = true; - allowempty = false; - } - - BLOCKMAP - { - required = false; - nodebuild = true; - allowempty = true; - } -} - udmfmaplumpnames { ZNODES @@ -682,48 +484,32 @@ thingsfilters } + //filter3 + //{ + // name = "Normal Gravity"; + // category = ""; + // type = -1; + // + // fields + // { + // 2 = false; + // } + //} - filter3 - { - name = "Normal Gravity"; - category = ""; - type = -1; - - fields - { - 2 = false; - } - - } - - - filter4 - { - name = "Reverse Gravity"; - category = ""; - type = -1; - - fields - { - 2 = true; - } - - } + //filter4 + //{ + // name = "Reverse Gravity"; + // category = ""; + // type = -1; + // + // fields + // { + // 2 = true; + // } + //} } // Special linedefs -speciallinedefs -{ - soundlinedefflag = 64; // See linedefflags - singlesidedflag = 1; // See linedefflags - doublesidedflag = 4; // See linedefflags - impassableflag = 1; - upperunpeggedflag = 8; - lowerunpeggedflag = 16; - repeatmidtextureflag = 1024; - pegmidtextureflag = 256; -} - speciallinedefs_udmf { soundlinedefflag = "noclimb"; @@ -734,6 +520,8 @@ speciallinedefs_udmf lowerunpeggedflag = "dontpegbottom"; repeatmidtextureflag = "wrapmidtex"; pegmidtextureflag = "midpeg"; + slopeskewflag = "skewtd"; + nomidtextureskewflag = "noskew"; } scriptlumpnames diff --git a/extras/conf/udb/Includes/SRB222_sectors.cfg b/extras/conf/udb/Includes/SRB222_sectors.cfg deleted file mode 100644 index 5b3ad4155..000000000 --- a/extras/conf/udb/Includes/SRB222_sectors.cfg +++ /dev/null @@ -1,107 +0,0 @@ -sectortypes -{ - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF "; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check) "; - 112 = "Trigger Line Ex. (NiGHTS Mare) "; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters "; - 176 = "Custom Global Gravity "; - 1280 = "Speed Pad"; - 1536 = "Flip Gravity on Jump"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; -} - -gen_sectortypes -{ - first - { - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF "; - } - - second - { - 0 = "Normal"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check) "; - 112 = "Trigger Line Ex. (NiGHTS Mare) "; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Spheres Parameters "; - 176 = "Custom Global Gravity "; - } - - third - { - 0 = "Normal"; - 1280 = "Speed Pad"; - 1536 = "Flip Gravity on Jump"; - } - - fourth - { - 0 = "Normal"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; - } -} diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index b4508c91e..df08e3ac5 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3,3175 +3,8 @@ // 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta // 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream -doom -{ - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 3328 = "3D Mode Start"; - } - - starts - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 16; - height = 48; - sprite = "PLAYA0"; - - 1 - { - title = "Player 01 Start"; - sprite = "PLAYA0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "PLAYA0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "PLAYA0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "PLAYA0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "PLAYA0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "PLAYA0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "PLAYA0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "PLAYA0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "PLAYA0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "PLAYA0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "PLAYA0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "PLAYA0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "PLAYA0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "PLAYA0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "PLAYA0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "PLAYA0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "PLAYA0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "PLAYA0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "PLAYA0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "PLAYA0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "PLAYA0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "PLAYA0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "PLAYA0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "PLAYA0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "PLAYA0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "PLAYA0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "PLAYA0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "PLAYA0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "PLAYA0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "PLAYA0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "PLAYA0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "PLAYA0"; - } - 33 - { - title = "Match Start"; - sprite = "NDRNA2A8"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - - enemies - { - color = 9; // Light_Blue - arrow = 1; - title = "Enemies"; - - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - width = 24; - height = 32; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - width = 24; - height = 32; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 28; - height = 40; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 28; - height = 40; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - height = 32; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Pop-up Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - } - 122 - { - title = "Spring Shell (Green)"; - sprite = "SSHLA1"; - width = 24; - height = 40; - } - 125 - { - title = "Spring Shell (Yellow)"; - sprite = "SSHLI1"; - width = 24; - height = 40; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 126 - { - title = "Crushstacean"; - sprite = "CRABA0"; - width = 24; - height = 32; - } - 138 - { - title = "Banpyura"; - sprite = "CR2BA0"; - width = 24; - height = 32; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - width = 24; - height = 32; - } - 118 - { - title = "Lance-a-Bot"; - sprite = "CBFSA1"; - width = 32; - height = 72; - } - 1113 - { - title = "Suspicious Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - width = 24; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA0"; - width = 24; - height = 32; - } - 134 - { - title = "Canarivore"; - sprite = "CANAA0"; - width = 12; - height = 80; - hangs = 1; - } - 123 - { - title = "Unidus"; - sprite = "UNIDA1"; - width = 18; - height = 36; - } - 135 - { - title = "Pterabyte Spawner"; - sprite = "PTERA2A8"; - width = 16; - height = 16; - } - 136 - { - title = "Pyre Fly"; - sprite = "PYREA0"; - width = 24; - height = 34; - } - 137 - { - title = "Dragonbomber"; - sprite = "DRABA1"; - width = 28; - height = 48; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 50; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - } - 112 - { - title = "Spincushion"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - width = 24; - height = 48; - } - 129 - { - title = "Penguinator"; - sprite = "PENGA1"; - width = 24; - height = 32; - } - 130 - { - title = "Pophat"; - sprite = "POPHA1"; - width = 24; - height = 32; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - height = 32; - } - 131 - { - title = "Spinbobert"; - sprite = "SBOBB0"; - width = 32; - height = 32; - } - 132 - { - title = "Cacolantern"; - sprite = "CACOA0"; - width = 32; - height = 32; - } - 133 - { - title = "Hangster"; - sprite = "HBATC1"; - width = 24; - height = 24; - hangs = 1; - } - 127 - { - title = "Hive Elemental"; - sprite = "HIVEA0"; - width = 32; - height = 80; - } - 128 - { - title = "Bumblebore"; - sprite = "BUMBA1"; - width = 16; - height = 32; - } - 124 - { - title = "Buggle"; - sprite = "BBUZA1"; - width = 20; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - } - - bosses - { - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; - - 200 - { - title = "Egg Mobile"; - sprite = "EGGMA1"; - width = 24; - height = 76; - } - 201 - { - title = "Egg Slimer"; - sprite = "EGGNA1"; - width = 24; - height = 76; - } - 202 - { - title = "Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 116; - } - 203 - { - title = "Egg Colosseum"; - sprite = "EGGPA1"; - width = 24; - height = 76; - } - 204 - { - title = "Fang"; - sprite = "FANGA1"; - width = 24; - height = 60; - } - 206 - { - title = "Brak Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - } - 207 - { - title = "Metal Sonic (Race)"; - sprite = "METLI1"; - width = 16; - height = 48; - } - 208 - { - title = "Metal Sonic (Battle)"; - sprite = "METLC1"; - width = 16; - height = 48; - } - 209 - { - title = "Brak Eggman"; - sprite = "BRAK01"; - width = 48; - height = 160; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - sprite = "internal:eggmanend"; - } - 291 - { - arrow = 0; - title = "Egg Capsule Center"; - width = 8; - height = 16; - sprite = "internal:capsule"; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - sprite = "internal:eggmanway"; - } - 293 - { - title = "Metal Sonic Gather Point"; - sprite = "internal:metal"; - width = 8; - height = 16; - } - 294 - { - title = "Fang Waypoint"; - sprite = "internal:eggmanway"; - width = 8; - height = 16; - } - } - - rings - { - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - sprite = "RINGA0"; - - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "internal:RNGBA0"; - } - 302 - { - title = "Rail Ring"; - sprite = "internal:RNGRA0"; - } - 303 - { - title = "Infinity Ring"; - sprite = "internal:RNGIA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "internal:RNGAA0"; - } - 305 - { - title = "Explosion Ring"; - sprite = "internal:RNGEA0"; - } - 306 - { - title = "Scatter Ring"; - sprite = "internal:RNGSA0"; - } - 307 - { - title = "Grenade Ring"; - sprite = "internal:RNGGA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; - } - } - - collectibles - { - color = 10; // Light_Green - title = "Other Collectibles"; - width = 16; - height = 32; - sort = 1; - sprite = "CEMGA0"; - - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Emerald Token"; - sprite = "TOKEA0"; - width = 16; - height = 32; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "CEMGA0"; - } - 314 - { - title = "Chaos Emerald 2 (Purple)"; - sprite = "CEMGB0"; - } - 315 - { - title = "Chaos Emerald 3 (Blue)"; - sprite = "CEMGC0"; - } - 316 - { - title = "Chaos Emerald 4 (Cyan)"; - sprite = "CEMGD0"; - } - 317 - { - title = "Chaos Emerald 5 (Orange)"; - sprite = "CEMGE0"; - } - 318 - { - title = "Chaos Emerald 6 (Red)"; - sprite = "CEMGF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "CEMGG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "SHRDA0"; - } - 321 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - } - 322 - { - title = "Emblem"; - sprite = "EMBMA0"; - width = 16; - height = 30; - } - } - - boxes - { - color = 7; // Gray - blocking = 2; - title = "Monitors"; - width = 18; - height = 40; - - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "TVRIA0"; - } - 401 - { - title = "Pity Shield"; - sprite = "TVPIA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "TVATA0"; - } - 403 - { - title = "Force Shield"; - sprite = "TVFOA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "TVARA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "TVWWA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "TVELA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "TVSSA0"; - } - 408 - { - title = "Invincibility"; - sprite = "TVIVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "TV1UA0"; - } - 410 - { - title = "Eggman"; - sprite = "TVEGA0"; - } - 411 - { - title = "Teleporter"; - sprite = "TVMXA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "TVGVA0"; - } - 414 - { - title = "CTF Team Ring Monitor (Red)"; - sprite = "TRRIA0"; - } - 415 - { - title = "CTF Team Ring Monitor (Blue)"; - sprite = "TBRIA0"; - } - 416 - { - title = "Recycler"; - sprite = "TVRCA0"; - } - 418 - { - title = "Score (1,000 Points)"; - sprite = "TV1KA0"; - } - 419 - { - title = "Score (10,000 Points)"; - sprite = "TVTKA0"; - } - 420 - { - title = "Flame Shield"; - sprite = "TVFLA0"; - } - 421 - { - title = "Water Shield"; - sprite = "TVBBA0"; - } - 422 - { - title = "Lightning Shield"; - sprite = "TVZPA0"; - } - } - - boxes2 - { - color = 18; // Gold - blocking = 2; - title = "Monitors (Respawning)"; - width = 20; - height = 44; - - 431 - { - title = "Pity Shield (Respawn)"; - sprite = "TVPIB0"; - } - 432 - { - title = "Attraction Shield (Respawn)"; - sprite = "TVATB0"; - } - 433 - { - title = "Force Shield (Respawn)"; - sprite = "TVFOB0"; - } - 434 - { - title = "Armageddon Shield (Respawn)"; - sprite = "TVARB0"; - } - 435 - { - title = "Whirlwind Shield (Respawn)"; - sprite = "TVWWB0"; - } - 436 - { - title = "Elemental Shield (Respawn)"; - sprite = "TVELB0"; - } - 437 - { - title = "Super Sneakers (Respawn)"; - sprite = "TVSSB0"; - } - 438 - { - title = "Invincibility (Respawn)"; - sprite = "TVIVB0"; - } - 440 - { - title = "Eggman (Respawn)"; - sprite = "TVEGB0"; - } - 443 - { - title = "Gravity Boots (Respawn)"; - sprite = "TVGVB0"; - } - 450 - { - title = "Flame Shield (Respawn)"; - sprite = "TVFLB0"; - } - 451 - { - title = "Water Shield (Respawn)"; - sprite = "TVBBB0"; - } - 452 - { - title = "Lightning Shield (Respawn)"; - sprite = "TVZPB0"; - } - } - - generic - { - color = 11; // Light_Cyan - title = "Generic Items & Hazards"; - - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLE0"; - width = 8; - height = 16; - } - 501 - { - title = "Signpost"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0M0"; - width = 64; - height = 128; - } - 520 - { - title = "Bomb Sphere"; - sprite = "SPHRD0"; - width = 16; - height = 24; - } - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 8; - } - 522 - { - title = "Wall Spike"; - sprite = "WSPKALAR"; - width = 16; - height = 14; - arrow = 1; - } - 523 - { - title = "Spike"; - sprite = "USPKA0"; - width = 8; - height = 32; - } - 1130 - { - title = "Small Mace"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1131 - { - title = "Big Mace"; - sprite = "BMCEA0"; - width = 34; - height = 68; - } - 1136 - { - title = "Small Fireball"; - sprite = "SFBRA0"; - width = 17; - height = 34; - } - 1137 - { - title = "Large Fireball"; - sprite = "BFBRA0"; - width = 34; - height = 68; - } - } - - springs - { - color = 12; // Light_Red - title = "Springs and Fans"; - width = 20; - height = 16; - sprite = "RSPRD2"; - - 540 - { - title = "Fan"; - sprite = "FANSA0D0"; - width = 16; - height = 8; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 542 - { - title = "Bumper"; - sprite = "BUMPA0"; - width = 32; - height = 64; - } - 543 - { - title = "Balloon"; - sprite = "BLONA0"; - width = 32; - height = 64; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - } - 557 - { - arrow = 1; - title = "Diagonal Blue Spring"; - sprite = "BSPRD2"; - width = 16; - } - 558 - { - arrow = 1; - title = "Horizontal Yellow Spring"; - sprite = "SSWYD2D8"; - width = 16; - height = 32; - } - 559 - { - arrow = 1; - title = "Horizontal Red Spring"; - sprite = "SSWRD2D8"; - width = 16; - height = 32; - } - 560 - { - arrow = 1; - title = "Horizontal Blue Spring"; - sprite = "SSWBD2D8"; - width = 16; - height = 32; - } - 1134 - { - title = "Yellow Spring Ball"; - sprite = "YSPBA0"; - width = 17; - height = 34; - } - 1135 - { - title = "Red Spring Ball"; - sprite = "RSPBA0"; - width = 17; - height = 34; - } - 544 - { - arrow = 1; - title = "Yellow Boost Panel"; - sprite = "BSTYA0"; - width = 28; - height = 2; - } - 545 - { - arrow = 1; - title = "Red Boost Panel"; - sprite = "BSTRA0"; - width = 28; - height = 2; - } - } - - patterns - { - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - sprite = "RINGA0"; - - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - } - } - - invisible - { - color = 15; // White - title = "Misc. Invisible"; - width = 0; - height = 0; - sprite = "UNKNA0"; - sort = 1; - fixedsize = true; - blocking = 0; - - 700 - { - title = "Water Ambience A (Large)"; - sprite = "internal:ambiance"; - } - - 701 - { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; - } - - 702 - { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; - } - - 703 - { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; - } - - 704 - { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; - } - - 705 - { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; - } - - 706 - { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; - } - - 707 - { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; - } - - 708 - { - title = "Disco Ambience"; - sprite = "internal:ambiance"; - } - - 709 - { - title = "Volcano Ambience"; - sprite = "internal:ambiance"; - } - - 710 - { - title = "Machine Ambience"; - sprite = "internal:ambiance"; - } - - 750 - { - title = "Slope Vertex"; - sprite = "internal:vertexslope"; - } - - 751 - { - arrow = 1; - title = "Teleport Destination"; - sprite = "internal:tele"; - } - - 752 - { - arrow = 1; - title = "Alternate View Point"; - sprite = "internal:view"; - } - - 753 - { - title = "Zoom Tube Waypoint"; - sprite = "internal:zoom"; - } - - 754 - { - title = "Push Point"; - sprite = "GWLGA0"; - } - 755 - { - title = "Pull Point"; - sprite = "GWLRA0"; - } - 756 - { - title = "Blast Linedef Executor"; - sprite = "TOADA0"; - width = 32; - height = 16; - } - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 758 - { - title = "Object Angle Anchor"; - sprite = "internal:view"; - } - 760 - { - title = "PolyObject Anchor"; - sprite = "internal:polyanchor"; - } - 761 - { - title = "PolyObject Spawn Point"; - sprite = "internal:polycenter"; - } - 762 - { - title = "PolyObject Spawn Point (Crush)"; - sprite = "internal:polycentercrush"; - } - 780 - { - title = "Skybox View Point"; - sprite = "internal:skyb"; - } - } - - greenflower - { - color = 10; // Green - title = "Greenflower"; - - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - width = 16; - height = 40; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - width = 16; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 803 - { - title = "Blueberry Bush"; - sprite = "BUS3A0"; - width = 16; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - width = 16; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - width = 16; - height = 32; - } - 806 - { - title = "GFZ Tree"; - sprite = "TRE1A0"; - width = 20; - height = 128; - } - 807 - { - title = "GFZ Berry Tree"; - sprite = "TRE1B0"; - width = 20; - height = 128; - } - 808 - { - title = "GFZ Cherry Tree"; - sprite = "TRE1C0"; - width = 20; - height = 128; - } - 809 - { - title = "Checkered Tree"; - sprite = "TRE2A0"; - width = 20; - height = 200; - } - 810 - { - title = "Checkered Tree (Sunset)"; - sprite = "TRE2B0"; - width = 20; - height = 200; - } - 811 - { - title = "Polygon Tree"; - sprite = "TRE4A0"; - width = 20; - height = 200; - } - 812 - { - title = "Bush Tree"; - sprite = "TRE5A0"; - width = 20; - height = 200; - } - 813 - { - title = "Red Bush Tree"; - sprite = "TRE5B0"; - width = 20; - height = 200; - } - } - - technohill - { - color = 10; // Green - title = "Techno Hill"; - - 900 - { - title = "THZ Steam Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 902 - { - title = "THZ Spin Flower (Red)"; - sprite = "FWR5A0"; - width = 16; - height = 64; - } - 903 - { - title = "THZ Spin Flower (Yellow)"; - sprite = "FWR6A0"; - width = 16; - height = 64; - } - 904 - { - arrow = 1; - title = "Whistlebush"; - sprite = "THZTA0"; - width = 16; - height = 64; - } - } - - deepsea - { - color = 10; // Green - title = "Deep Sea"; - - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - width = 16; - height = 40; - } - 1009 - { - arrow = 1; - blocking = 2; - title = "Gargoyle (Big)"; - sprite = "GARGB1"; - width = 32; - height = 80; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CORLA0"; - width = 29; - height = 40; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CORLB0"; - width = 30; - height = 53; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CORLC0"; - width = 28; - height = 41; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1007 - { - title = "Kelp"; - sprite = "KELPA0"; - width = 16; - height = 292; - } - 1008 - { - title = "Stalagmite (DSZ1)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - } - 1010 - { - arrow = 1; - title = "Light Beam"; - sprite = "LIBEARAL"; - width = 16; - height = 16; - } - 1011 - { - title = "Stalagmite (DSZ2)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - } - 1012 - { - arrow = 1; - title = "Big Floating Mine"; - width = 28; - height = 56; - sprite = "BMNEA1"; - } - 1013 - { - title = "Animated Kelp"; - sprite = "ALGAA0"; - width = 48; - height = 120; - } - 1014 - { - title = "Large Coral (Brown)"; - sprite = "CORLD0"; - width = 56; - height = 112; - } - 1015 - { - title = "Large Coral (Beige)"; - sprite = "CORLE0"; - width = 56; - height = 112; - } - } - - castleeggman - { - color = 10; // Green - title = "Castle Eggman"; - - 1100 - { - title = "Chain (Decorative)"; - sprite = "CHANA0"; - width = 4; - height = 128; - hangs = 1; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0E0"; - width = 8; - height = 32; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - width = 16; - height = 40; - } - 1104 - { - title = "Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1105 - { - title = "Chain with Maces Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1106 - { - title = "Chained Spring Spawnpoint"; - sprite = "YSPBA0"; - width = 17; - height = 34; - } - 1107 - { - title = "Chain Spawnpoint"; - sprite = "BMCHA0"; - width = 17; - height = 34; - } - 1108 - { - arrow = 1; - title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; - width = 17; - height = 34; - } - 1109 - { - title = "Firebar Spawnpoint"; - sprite = "BFBRA0"; - width = 17; - height = 34; - } - 1110 - { - title = "Custom Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1111 - { - arrow = 1; - blocking = 2; - title = "Crawla Statue"; - sprite = "CSTAA1"; - width = 16; - height = 40; - } - 1112 - { - arrow = 1; - blocking = 2; - title = "Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - } - 1114 - { - title = "Pine Tree"; - sprite = "PINEA0"; - width = 16; - height = 628; - } - 1115 - { - title = "CEZ Shrub (Small)"; - sprite = "CEZBA0"; - width = 16; - height = 24; - } - 1116 - { - title = "CEZ Shrub (Large)"; - sprite = "CEZBB0"; - width = 32; - height = 48; - } - 1117 - { - arrow = 1; - title = "Pole Banner (Red)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1118 - { - arrow = 1; - title = "Pole Banner (Blue)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1119 - { - title = "Candle"; - sprite = "CNDLA0"; - width = 8; - height = 48; - } - 1120 - { - title = "Candle Pricket"; - sprite = "CNDLB0"; - width = 8; - height = 176; - } - 1121 - { - title = "Flame Holder"; - sprite = "FLMHA0"; - width = 24; - height = 80; - } - 1122 - { - title = "Fire Torch"; - sprite = "CTRCA0"; - width = 16; - height = 80; - } - 1123 - { - title = "Cannonball Launcher"; - sprite = "internal:cannonball"; - width = 8; - height = 16; - } - 1124 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - height = 40; - } - 1125 - { - title = "Brambles"; - sprite = "CABRALAR"; - width = 48; - height = 32; - } - 1126 - { - title = "Invisible Lockon Object"; - sprite = "LCKNC0"; - width = 16; - height = 32; - } - 1127 - { - title = "Spectator Eggrobo"; - sprite = "EGR1A1"; - width = 20; - height = 72; - } - 1128 - { - arrow = 1; - title = "Waving Flag (Red)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - 1129 - { - arrow = 1; - title = "Waving Flag (Blue)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - } - - aridcanyon - { - color = 10; // Green - title = "Arid Canyon"; - - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 48; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - width = 8; - height = 16; - } - 1203 - { - title = "Tiny Red Flower Cactus"; - sprite = "CACTA0"; - width = 13; - height = 24; - } - 1204 - { - title = "Small Red Flower Cactus"; - sprite = "CACTB0"; - width = 15; - height = 52; - } - 1205 - { - title = "Tiny Blue Flower Cactus"; - sprite = "CACTC0"; - width = 13; - height = 24; - } - 1206 - { - title = "Small Blue Flower Cactus"; - sprite = "CACTD0"; - width = 15; - height = 52; - } - 1207 - { - title = "Prickly Pear"; - sprite = "CACTE0"; - width = 32; - height = 96; - } - 1208 - { - title = "Barrel Cactus"; - sprite = "CACTF0"; - width = 20; - height = 128; - } - 1209 - { - title = "Tall Barrel Cactus"; - sprite = "CACTG0"; - width = 24; - height = 224; - } - 1210 - { - title = "Armed Cactus"; - sprite = "CACTH0"; - width = 24; - height = 256; - } - 1211 - { - title = "Ball Cactus"; - sprite = "CACTI0"; - width = 48; - height = 96; - } - 1212 - { - title = "Caution Sign"; - sprite = "WWSGAR"; - width = 22; - height = 64; - } - 1213 - { - title = "Cacti Sign"; - sprite = "WWS2AR"; - width = 22; - height = 64; - } - 1214 - { - title = "Sharp Turn Sign"; - sprite = "WWS3ALAR"; - width = 16; - height = 192; - } - 1215 - { - title = "Mine Oil Lamp"; - sprite = "OILLA0"; - width = 22; - height = 64; - hangs = 1; - } - 1216 - { - title = "TNT Barrel"; - sprite = "BARRA1"; - width = 24; - height = 63; - } - 1217 - { - title = "TNT Proximity Shell"; - sprite = "REMTA0"; - width = 64; - height = 40; - } - 1218 - { - title = "Dust Devil"; - sprite = "TAZDCR"; - width = 80; - height = 416; - } - 1219 - { - title = "Minecart Spawner"; - sprite = "MCRTCLFR"; - width = 22; - height = 32; - } - 1220 - { - title = "Minecart Stopper"; - sprite = "MCRTIR"; - width = 32; - height = 32; - } - 1221 - { - title = "Minecart Saloon Door"; - sprite = "SALDARAL"; - width = 96; - height = 160; - } - 1222 - { - title = "Train Cameo Spawner"; - sprite = "TRAEBRBL"; - width = 28; - height = 32; - } - 1223 - { - title = "Train Dust Spawner"; - sprite = "ADSTA0"; - width = 4; - height = 4; - } - 1224 - { - title = "Train Steam Spawner"; - sprite = "STEAA0"; - width = 4; - height = 4; - } - 1229 - { - title = "Minecart Switch Point"; - sprite = "internal:zoom"; - width = 8; - height = 16; - } - 1230 - { - title = "Tiny Cactus"; - sprite = "CACTJ0"; - width = 13; - height = 28; - } - 1231 - { - title = "Small Cactus"; - sprite = "CACTK0"; - width = 15; - height = 60; - } - } - - redvolcano - { - color = 10; // Green - title = "Red Volcano"; - - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "internal:flameh"; - width = 16; - height = 40; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "internal:flamev"; - width = 16; - height = 40; - } - 1302 - { - title = "Spinning Flame Jet (Counter-Clockwise)"; - sprite = "internal:flame2"; - width = 16; - height = 24; - } - 1303 - { - title = "Spinning Flame Jet (Clockwise)"; - sprite = "internal:flame1"; - width = 16; - height = 24; - } - 1304 - { - title = "Lavafall"; - sprite = "LFALF0"; - width = 30; - height = 32; - } - 1305 - { - title = "Rollout Rock"; - sprite = "PUMIA1A5"; - width = 30; - height = 60; - } - 1306 - { - title = "Big Fern"; - sprite = "JPLAB0"; - width = 32; - height = 48; - } - 1307 - { - title = "Jungle Palm"; - sprite = "JPLAC0"; - width = 32; - height = 48; - } - 1308 - { - title = "Torch Flower"; - sprite = "TFLOA0"; - width = 14; - height = 110; - } - 1309 - { - title = "RVZ1 Wall Vine (Long)"; - sprite = "WVINALAR"; - width = 1; - height = 288; - } - 1310 - { - title = "RVZ1 Wall Vine (Short)"; - sprite = "WVINBLBR"; - width = 1; - height = 288; - } - } - - botanicserenity - { - color = 10; // Green - title = "Botanic Serenity"; - width = 16; - height = 32; - sprite = "BSZ1A0"; - 1400 - { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; - } - 1401 - { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; - } - 1402 - { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; - } - 1403 - { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; - } - 1404 - { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; - } - 1405 - { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; - } - 1410 - { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; - } - 1411 - { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; - } - 1412 - { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; - } - 1413 - { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; - } - 1414 - { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; - } - 1415 - { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; - } - 1420 - { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; - } - 1421 - { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; - } - 1422 - { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; - } - 1423 - { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; - } - 1424 - { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; - } - 1425 - { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; - } - 1430 - { - title = "Tulip (Red)"; - sprite = "BST1A0"; - } - 1431 - { - title = "Tulip (Purple)"; - sprite = "BST2A0"; - } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BST3A0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BST4A0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BST5A0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BST6A0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1473 - { - title = "Palm Tree (Big)"; - width = 16; - height = 160; - sprite = "BSZ8D0"; - } - 1475 - { - title = "Palm Tree (Small)"; - width = 16; - height = 80; - sprite = "BSZ8F0"; - } - } - - azuretemple - { - color = 10; // Green - title = "Azure Temple"; - - 1500 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Up)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1502 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Down)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Long)"; - sprite = "BGARA1"; - width = 16; - height = 40; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - 1505 - { - title = "Green Flame"; - sprite = "CFLMA0E0"; - width = 8; - height = 32; - } - 1506 - { - arrow = 1; - blocking = 2; - title = "Blue Gargoyle"; - sprite = "BGARD1"; - width = 16; - height = 40; - } - } - - dreamhill - { - color = 10; // Green - title = "Dream Hill"; - - 1600 - { - title = "Spring Tree"; - sprite = "TRE6A0"; - width = 16; - height = 32; - } - 1601 - { - title = "Shleep"; - sprite = "SHLPA0"; - width = 24; - height = 32; - } - 1602 - { - title = "Nightopian"; - sprite = "NTPNA1"; - width = 16; - height = 40; - } - } - - nightstrk - { - color = 13; // Pink - title = "NiGHTS Track"; - width = 8; - height = 4096; - sprite = "UNKNA0"; - - 1700 - { - title = "Axis"; - sprite = "internal:axis1"; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - sprite = "internal:axis2"; - } - 1702 - { - title = "Axis Transfer Line"; - sprite = "internal:axis3"; - } - 1710 - { - title = "Ideya Capture"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nights - { - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - } - 1704 - { - arrow = 1; - title = "NiGHTS Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Blue Sphere"; - sprite = "SPHRA0"; - width = 16; - height = 24; - } - 1707 - { - title = "Super Paraloop"; - sprite = "NPRUA0"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - } - 1709 - { - title = "Nightopian Helper"; - sprite = "NPRUC0"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - } - 1713 - { - arrow = 1; - title = "Hoop (Customizable)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1714 - { - title = "Ideya Anchor Point"; - sprite = "internal:axis1"; - width = 8; - height = 16; - } - } - - mario - { - color = 6; // Brown - title = "Mario"; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - width = 16; - height = 24; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - height = 32; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - height = 32; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - width = 16; - height = 32; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA1"; - width = 16; - height = 20; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - width = 16; - height = 48; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - width = 16; - height = 32; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - width = 16; - height = 32; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - height = 32; - } - } - - christmasdisco - { - color = 10; // Green - title = "Christmas & Disco"; - - 1850 - { - title = "Christmas Pole"; - sprite = "XMS1A0"; - width = 16; - height = 40; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - width = 16; - height = 64; - } - 1853 - { - blocking = 2; - title = "Snowman (With Hat)"; - sprite = "XMS3B0"; - width = 16; - height = 80; - } - 1854 - { - title = "Lamp Post"; - sprite = "XMS4A0"; - width = 8; - height = 120; - } - 1855 - { - title = "Lamp Post (Snow)"; - sprite = "XMS4B0"; - width = 8; - height = 120; - } - 1856 - { - title = "Hanging Star"; - sprite = "XMS5A0"; - width = 4; - height = 80; - hangs = 1; - } - 1857 - { - title = "Berry Bush (Snow)"; - sprite = "BUS1B0"; - width = 16; - height = 32; - } - 1858 - { - title = "Bush (Snow)"; - sprite = "BUS2B0"; - width = 16; - height = 32; - } - 1859 - { - title = "Blueberry Bush (Snow)"; - sprite = "BUS3B0"; - width = 16; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - width = 16; - height = 54; - hangs = 1; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - } - } - - stalagmites - { - color = 10; // Green - title = "Stalagmites"; - width = 16; - height = 40; - - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; - width = 16; - height = 40; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - width = 16; - height = 40; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - width = 16; - height = 40; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STLGD0"; - width = 16; - height = 40; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STLGE0"; - width = 16; - height = 40; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STLGF0"; - width = 16; - height = 40; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STLGG0"; - width = 24; - height = 96; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STLGH0"; - width = 16; - height = 40; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STLGI0"; - width = 16; - height = 40; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; - width = 16; - height = 40; - } - } - - hauntedheights - { - color = 10; // Green - title = "Haunted Heights"; - - 2000 - { - title = "Smashing Spikeball"; - sprite = "FMCEA0"; - width = 18; - height = 28; - } - 2001 - { - title = "HHZ Grass"; - sprite = "HHZMA0"; - width = 16; - height = 40; - } - 2002 - { - title = "HHZ Tentacle 1"; - sprite = "HHZMB0"; - width = 16; - height = 40; - } - 2003 - { - title = "HHZ Tentacle 2"; - sprite = "HHZMC0"; - width = 16; - height = 40; - } - 2004 - { - title = "HHZ Stalagmite (Tall)"; - sprite = "HHZME0"; - width = 16; - height = 40; - } - 2005 - { - title = "HHZ Stalagmite (Short)"; - sprite = "HHZMF0"; - width = 16; - height = 40; - } - 2006 - { - title = "Jack-o'-lantern 1"; - sprite = "PUMKA0"; - width = 16; - height = 40; - } - 2007 - { - title = "Jack-o'-lantern 2"; - sprite = "PUMKB0"; - width = 16; - height = 40; - } - 2008 - { - title = "Jack-o'-lantern 3"; - sprite = "PUMKC0"; - width = 16; - height = 40; - } - 2009 - { - title = "Purple Mushroom"; - sprite = "SHRMD0"; - width = 16; - height = 48; - } - 2010 - { - title = "HHZ Tree"; - sprite = "HHPLC0"; - width = 12; - height = 40; - } - } - - frozenhillside - { - color = 10; // Green - title = "Frozen Hillside"; - - 2100 - { - title = "Ice Shard (Small)"; - sprite = "FHZIA0"; - width = 8; - height = 32; - } - 2101 - { - title = "Ice Shard (Large)"; - sprite = "FHZIB0"; - width = 8; - height = 32; - } - 2102 - { - title = "Crystal Tree (Aqua)"; - sprite = "TRE3A0"; - width = 20; - height = 200; - } - 2103 - { - title = "Crystal Tree (Pink)"; - sprite = "TRE3B0"; - width = 20; - height = 200; - } - 2104 - { - title = "Amy Cameo"; - sprite = "ROSYA1"; - width = 16; - height = 48; - } - 2105 - { - title = "Mistletoe"; - sprite = "XMS6A0"; - width = 52; - height = 106; - } - } - - tutorial - { - color = 10; // Green - title = "Tutorial"; - - 799 - { - title = "Tutorial Plant"; - sprite = "TUPFH0"; - width = 40; - height = 144; - } - } - - flickies - { - color = 10; // Green - title = "Flickies"; - width = 8; - height = 20; - - 2200 - { - title = "Bluebird"; - sprite = "FL01A1"; - } - 2201 - { - title = "Rabbit"; - sprite = "FL02A1"; - } - 2202 - { - title = "Chicken"; - sprite = "FL03A1"; - } - 2203 - { - title = "Seal"; - sprite = "FL04A1"; - } - 2204 - { - title = "Pig"; - sprite = "FL05A1"; - } - 2205 - { - title = "Chipmunk"; - sprite = "FL06A1"; - } - 2206 - { - title = "Penguin"; - sprite = "FL07A1"; - } - 2207 - { - title = "Fish"; - sprite = "FL08A1"; - } - 2208 - { - title = "Ram"; - sprite = "FL09A1"; - } - 2209 - { - title = "Puffin"; - sprite = "FL10A1"; - } - 2210 - { - title = "Cow"; - sprite = "FL11A1"; - } - 2211 - { - title = "Rat"; - sprite = "FL12A1"; - } - 2212 - { - title = "Bear"; - sprite = "FL13A1"; - } - 2213 - { - title = "Dove"; - sprite = "FL14A1"; - } - 2214 - { - title = "Cat"; - sprite = "FL15A1"; - } - 2215 - { - title = "Canary"; - sprite = "FL16A1"; - } - 2216 - { - title = "Spider"; - sprite = "FS01A1"; - } - 2217 - { - title = "Bat"; - sprite = "FS02A0"; - } - } -} - udmf { - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 3328 = "3D Mode Start"; - } starts { @@ -3974,7 +807,7 @@ udmf bosses { - color = 8; // Dark_Gray + color = 4; // Dark Red arrow = 1; title = "Bosses"; @@ -4355,95 +1188,185 @@ udmf width = 24; height = 24; sprite = "RINGA0"; - arg0 - { - title = "Float?"; - type = 11; - enum = "yesno"; - } 300 { title = "Ring"; sprite = "RINGA0"; width = 16; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 301 { title = "Bounce Ring"; - sprite = "internal:RNGBA0"; + sprite = "RNGBA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 302 { title = "Rail Ring"; - sprite = "internal:RNGRA0"; + sprite = "RNGRA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 303 { title = "Infinity Ring"; - sprite = "internal:RNGIA0"; + sprite = "RNGIA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 304 { title = "Automatic Ring"; - sprite = "internal:RNGAA0"; + sprite = "RNGAA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 305 { title = "Explosion Ring"; - sprite = "internal:RNGEA0"; + sprite = "RNGEA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 306 { title = "Scatter Ring"; - sprite = "internal:RNGSA0"; + sprite = "RNGSA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 307 { title = "Grenade Ring"; - sprite = "internal:RNGGA0"; + sprite = "RNGGA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 308 { title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; + sprite = "internal:TRNGA0R"; width = 16; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 309 { title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; + sprite = "internal:TRNGA0B"; width = 16; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 330 { title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; + sprite = "PIKBA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 331 { title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; + sprite = "PIKRA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 332 { title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; + sprite = "PIKAA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 333 { title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; + sprite = "PIKEA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 334 { title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; + sprite = "PIKSA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } 335 { title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; + sprite = "PIKGA0"; + arg0 + { + title = "Float?"; + type = 11; + enum = "yesno"; + } } } @@ -4562,16 +1485,16 @@ udmf title = "Monitors"; width = 18; height = 40; - arg0 - { - title = "Death trigger tag"; - type = 15; - } 400 { title = "Super Ring (10 Rings)"; sprite = "TVRIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4583,6 +1506,11 @@ udmf { title = "Pity Shield"; sprite = "TVPIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4594,6 +1522,11 @@ udmf { title = "Attraction Shield"; sprite = "TVATA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4605,6 +1538,11 @@ udmf { title = "Force Shield"; sprite = "TVFOA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4616,6 +1554,11 @@ udmf { title = "Armageddon Shield"; sprite = "TVARA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4627,6 +1570,11 @@ udmf { title = "Whirlwind Shield"; sprite = "TVWWA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4638,6 +1586,11 @@ udmf { title = "Elemental Shield"; sprite = "TVELA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4649,6 +1602,11 @@ udmf { title = "Super Sneakers"; sprite = "TVSSA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4660,6 +1618,11 @@ udmf { title = "Invincibility"; sprite = "TVIVA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4671,6 +1634,11 @@ udmf { title = "Extra Life"; sprite = "TV1UA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4692,11 +1660,21 @@ udmf { title = "Eggman"; sprite = "TVEGA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 411 { title = "Teleporter"; sprite = "TVMXA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4708,21 +1686,41 @@ udmf { title = "Gravity Boots"; sprite = "TVGVA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 414 { title = "CTF Team Ring Monitor (Red)"; sprite = "TRRIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 415 { title = "CTF Team Ring Monitor (Blue)"; sprite = "TBRIA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 416 { title = "Recycler"; sprite = "TVRCA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4734,16 +1732,31 @@ udmf { title = "Score (1,000 Points)"; sprite = "TV1KA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 419 { title = "Score (10,000 Points)"; sprite = "TVTKA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 420 { title = "Flame Shield"; sprite = "TVFLA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4755,6 +1768,11 @@ udmf { title = "Water Shield"; sprite = "TVBBA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4766,6 +1784,11 @@ udmf { title = "Lightning Shield"; sprite = "TVZPA0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } arg1 { title = "Respawn behavior"; @@ -4782,76 +1805,136 @@ udmf title = "Monitors (Respawning)"; width = 20; height = 44; - arg0 - { - title = "Death trigger tag"; - type = 15; - } 431 { title = "Pity Shield (Respawn)"; sprite = "TVPIB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 432 { title = "Attraction Shield (Respawn)"; sprite = "TVATB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 433 { title = "Force Shield (Respawn)"; sprite = "TVFOB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 434 { title = "Armageddon Shield (Respawn)"; sprite = "TVARB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 435 { title = "Whirlwind Shield (Respawn)"; sprite = "TVWWB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 436 { title = "Elemental Shield (Respawn)"; sprite = "TVELB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 437 { title = "Super Sneakers (Respawn)"; sprite = "TVSSB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 438 { title = "Invincibility (Respawn)"; sprite = "TVIVB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 440 { title = "Eggman (Respawn)"; sprite = "TVEGB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 443 { title = "Gravity Boots (Respawn)"; sprite = "TVGVB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 450 { title = "Flame Shield (Respawn)"; sprite = "TVFLB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 451 { title = "Water Shield (Respawn)"; sprite = "TVBBB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } 452 { title = "Lightning Shield (Respawn)"; sprite = "TVZPB0"; + arg0 + { + title = "Death trigger tag"; + type = 15; + } } } @@ -5235,13 +2318,13 @@ udmf { arrow = 0; title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalyellow"; } 601 { arrow = 0; title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; + sprite = "internal:ringverticalred"; height = 1024; } 602 @@ -5259,41 +2342,47 @@ udmf 604 { title = "Circle of Rings"; - sprite = "RINGA0"; + sprite = "internal:circlering"; width = 96; height = 192; + centerhitbox = true; } 605 { title = "Circle of Rings (Big)"; - sprite = "RINGA0"; + sprite = "internal:circlebigring"; width = 192; + centerhitbox = true; } 606 { title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circlesphere"; width = 96; height = 192; + centerhitbox = true; } 607 { title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigsphere"; width = 192; + centerhitbox = true; } 608 { title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; + sprite = "internal:circleringsphere"; width = 96; height = 192; + centerhitbox = true; } 609 { title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; + sprite = "internal:circlebigringsphere"; width = 192; + centerhitbox = true; } 610 { @@ -5322,6 +2411,7 @@ udmf sprite = "RINGA0"; width = 96; height = 192; + centerhitbox = true; arg0 { title = "Number of items"; @@ -5429,7 +2519,7 @@ udmf 756 { title = "Blast Linedef Executor"; - sprite = "TOADA0"; + sprite = "internal:blastexec"; width = 32; height = 16; arg0 @@ -5441,7 +2531,7 @@ udmf 757 { title = "Fan Particle Generator"; - sprite = "PRTLA0"; + sprite = "internal:fanparticles"; width = 8; height = 16; arg0 @@ -5490,11 +2580,6 @@ udmf title = "PolyObject Spawn Point"; sprite = "internal:polycenter"; } - 762 - { - title = "PolyObject Spawn Point (Crush)"; - sprite = "internal:polycentercrush"; - } 780 { title = "Skybox View Point"; @@ -5514,7 +2599,7 @@ udmf greenflower { - color = 10; // Green + color = 2; // Green title = "Greenflower"; 800 @@ -5619,7 +2704,7 @@ udmf technohill { - color = 10; // Green + color = 2; // Green title = "Techno Hill"; 900 @@ -5663,7 +2748,7 @@ udmf deepsea { - color = 10; // Green + color = 2; // Green title = "Deep Sea"; 1000 @@ -5823,7 +2908,7 @@ udmf castleeggman { - color = 10; // Green + color = 2; // Green title = "Castle Eggman"; 1100 @@ -6386,7 +3471,7 @@ udmf aridcanyon { - color = 10; // Green + color = 2; // Green title = "Arid Canyon"; 1200 @@ -6511,6 +3596,7 @@ udmf sprite = "WWSGAR"; width = 22; height = 64; + wallsprite = true; } 1213 { @@ -6518,6 +3604,7 @@ udmf sprite = "WWS2AR"; width = 22; height = 64; + wallsprite = true; } 1214 { @@ -6525,6 +3612,7 @@ udmf sprite = "WWS3ALAR"; width = 16; height = 192; + wallsprite = true; } 1215 { @@ -6644,7 +3732,7 @@ udmf redvolcano { - color = 10; // Green + color = 2; // Green title = "Red Volcano"; 1300 @@ -6789,7 +3877,7 @@ udmf botanicserenity { - color = 10; // Green + color = 2; // Green title = "Botanic Serenity"; width = 16; height = 32; @@ -7032,7 +4120,7 @@ udmf azuretemple { - color = 10; // Green + color = 2; // Green title = "Azure Temple"; 1500 @@ -7144,7 +4232,7 @@ udmf dreamhill { - color = 10; // Green + color = 2; // Green title = "Dream Hill"; 1600 @@ -7178,8 +4266,8 @@ udmf nightstrk { - color = 13; // Pink - title = "NiGHTS Track"; + color = 16; // Light Pink + title = "NiGHTS Track & Misc."; width = 8; height = 4096; sprite = "UNKNA0"; @@ -7207,8 +4295,8 @@ udmf type = 11; enum { - 0 = "Clockwise"; - 1 = "Counterclockwise"; + 0 = "Counterclockwise"; + 1 = "Clockwise"; } } } @@ -7238,30 +4326,6 @@ udmf title = "Order"; } } - 1710 - { - title = "Ideya Capture"; - sprite = "CAPSA0"; - width = 72; - height = 144; - arg0 - { - title = "Mare"; - } - arg1 - { - title = "Required spheres"; - } - } - } - - nights - { - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; - 1703 { title = "Ideya Drone"; @@ -7299,6 +4363,41 @@ udmf enum = "noyes"; } } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + arg0 + { + title = "Mare"; + } + arg1 + { + title = "Required spheres"; + } + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:ideya"; + width = 8; + height = 16; + arg0 + { + title = "Mare"; + } + } + } + + nights + { + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + 1704 { arrow = 1; @@ -7399,25 +4498,15 @@ udmf { arrow = 1; title = "Hoop"; - sprite = "HOOPA0"; + sprite = "internal:nightshoop"; width = 80; height = 160; + centerhitbox = true; arg0 { title = "Radius"; } } - 1714 - { - title = "Ideya Anchor Point"; - sprite = "internal:axis1"; - width = 8; - height = 16; - arg0 - { - title = "Mare"; - } - } } mario @@ -7528,7 +4617,7 @@ udmf christmasdisco { - color = 10; // Green + color = 2; // Green title = "Christmas & Disco"; 1850 @@ -7643,7 +4732,7 @@ udmf stalagmites { - color = 10; // Green + color = 2; // Green title = "Stalagmites"; width = 16; height = 40; @@ -7722,7 +4811,7 @@ udmf hauntedheights { - color = 10; // Green + color = 2; // Green title = "Haunted Heights"; 2000 @@ -7828,7 +4917,7 @@ udmf frozenhillside { - color = 10; // Green + color = 2; // Green title = "Frozen Hillside"; 2100 @@ -7883,7 +4972,7 @@ udmf tutorial { - color = 10; // Green + color = 2; // Green title = "Tutorial"; 799 @@ -7901,65 +4990,170 @@ udmf flickies { - color = 10; // Green + color = 2; // Green title = "Flickies"; width = 8; height = 20; - arg0 - { - title = "Radius"; - } - arg1 - { - title = "Flags"; - type = 12; - enum - { - 1 = "Move aimlessly"; - 2 = "No movement"; - 4 = "Hop"; - } - } 2200 { title = "Bluebird"; sprite = "FL01A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2201 { title = "Rabbit"; sprite = "FL02A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2202 { title = "Chicken"; sprite = "FL03A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2203 { title = "Seal"; sprite = "FL04A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2204 { title = "Pig"; sprite = "FL05A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2205 { title = "Chipmunk"; sprite = "FL06A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2206 { title = "Penguin"; sprite = "FL07A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2207 { title = "Fish"; sprite = "FL08A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } arg2 { title = "Color"; @@ -7989,51 +5183,214 @@ udmf { title = "Ram"; sprite = "FL09A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2209 { title = "Puffin"; sprite = "FL10A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2210 { title = "Cow"; sprite = "FL11A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2211 { title = "Rat"; sprite = "FL12A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2212 { title = "Bear"; sprite = "FL13A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2213 { title = "Dove"; sprite = "FL14A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2214 { title = "Cat"; sprite = "FL15A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2215 { title = "Canary"; sprite = "FL16A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2216 { title = "Spider"; sprite = "FS01A1"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } 2217 { title = "Bat"; sprite = "FS02A0"; + arg0 + { + title = "Radius"; + } + arg1 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Move aimlessly"; + 2 = "No movement"; + 4 = "Hop"; + } + } } } -} + + editor + { + color = 15; // White + arrow = 1; + title = "3D Mode Start"; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; + } +} \ No newline at end of file diff --git a/extras/conf/udb/SRB2_22Doom.cfg b/extras/conf/udb/SRB2_22Doom.cfg deleted file mode 100644 index 9e733aa39..000000000 --- a/extras/conf/udb/SRB2_22Doom.cfg +++ /dev/null @@ -1,32 +0,0 @@ -/************************************************************************\ - Ultimate Doom Builder Game Configuration for Sonic Robo Blast 2 Version 2.2 -\************************************************************************/ - -// This is required to prevent accidental use of a different configuration -type = "Doom Builder 2 Game Configuration"; - -// This is the title to show for this game -game = "Sonic Robo Blast 2 - 2.2 (Doom format)"; - -// This is the simplified game engine/sourceport name -engine = "zdoom"; - -// Settings common to all games and all map formats -include("Includes\\SRB222_common.cfg", "common"); - -// Settings common to Doom map format -include("Includes\\SRB222_common.cfg", "mapformat_doom"); - -include("Includes\\Game_SRB222.cfg"); - -// Script lumps detection -scriptlumpnames -{ - include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); -} - -//Default things filters -thingsfilters -{ - include("Includes\\SRB222_misc.cfg", "thingsfilters"); -} \ No newline at end of file From b405f50caaa93dc0cfeb9de821cba003bda0a8a6 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Sat, 24 Jun 2023 19:35:57 +0200 Subject: [PATCH 183/478] Fix A_ConnectToGround's handling of scaled mobjs --- src/p_enemy.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index c7d87b88a..87c2d7b9e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -12583,8 +12583,7 @@ void A_MineRange(mobj_t *actor) void A_ConnectToGround(mobj_t *actor) { mobj_t *work; - fixed_t workz; - fixed_t workh; + fixed_t endz; angle_t ang; INT32 locvar1 = var1; INT32 locvar2 = var2; @@ -12595,38 +12594,42 @@ void A_ConnectToGround(mobj_t *actor) if (actor->subsector->sector->ffloors) P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2); + endz = actor->z; if (actor->flags2 & MF2_OBJECTFLIP) - workz = (actor->z + actor->height) - actor->ceilingz; + actor->z = actor->ceilingz - actor->height; // Ensures perfect ceiling connection else - workz = actor->floorz - actor->z; + actor->z = actor->floorz; // Ensures perfect floor connection if (locvar2) { - workh = FixedMul(mobjinfo[locvar2].height, actor->scale); - if (actor->flags2 & MF2_OBJECTFLIP) - workz += workh; - work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar2); - workz += workh; + work = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar2); + if (work) + work->old_z = work->z; // Don't copy old_z from the actor + + actor->z += P_MobjFlip(actor) * FixedMul(mobjinfo[locvar2].height, actor->scale); } - if (!locvar1) - return; - - if (!(workh = FixedMul(mobjinfo[locvar1].height, actor->scale))) + if (!locvar1 || !mobjinfo[locvar1].height) // Can't tile the middle object? + { + actor->z = endz; return; + } ang = actor->angle + ANGLE_45; - while (workz < 0) + while ((actor->flags2 & MF2_OBJECTFLIP) ? (actor->z > endz) : (actor->z < endz)) { - work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1); + work = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1); if (work) - work->angle = ang; + { + work->angle = work->old_angle = ang; + work->old_z = work->z; // Don't copy old_z from the actor + } + ang += ANGLE_90; - workz += workh; + actor->z += P_MobjFlip(actor) * FixedMul(mobjinfo[locvar1].height, actor->scale); } - if (workz != 0) - actor->z += P_MobjFlip(actor)*workz; + actor->old_z = actor->z; // Reset Z interpolation - the spawned objects intentionally don't have any Z interpolation either, after all } // Function: A_SpawnParticleRelative From 8c31d279cffd1f750ee8d3c082e72cd5be29baf9 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sun, 11 Jun 2023 19:55:43 +0200 Subject: [PATCH 184/478] Implement per-texture offsets in UDMF --- extras/conf/udb/Includes/SRB222_common.cfg | 2 +- src/hardware/hw_main.c | 54 +++++++++++----------- src/lua_maplib.c | 48 +++++++++++++++++++ src/p_maputl.c | 16 +++---- src/p_setup.c | 29 ++++++++++++ src/r_defs.h | 4 ++ src/r_segs.c | 26 ++++++----- 7 files changed, 132 insertions(+), 47 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index 9a574d6f2..8f37aabaa 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -100,7 +100,7 @@ mapformat_udmf // When this is set to true, sectors with the same tag will light up when a line is highlighted linetagindicatesectors = false; - localsidedeftextureoffsets = false; + localsidedeftextureoffsets = true; distinctfloorandceilingbrightness = true; planeequationsupport = true; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 897288da2..c2390519e 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1153,7 +1153,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom else texturevpeg = gl_backsector->ceilingheight + textureheight[gl_toptexture] - gl_frontsector->ceilingheight; - texturevpeg += gl_sidedef->rowoffset; + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway texturevpeg %= textureheight[gl_toptexture]; @@ -1162,8 +1162,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_top) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_top) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1213,7 +1213,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom else texturevpeg = gl_frontsector->floorheight - gl_backsector->floorheight; - texturevpeg += gl_sidedef->rowoffset; + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bot; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway texturevpeg %= textureheight[gl_bottomtexture]; @@ -1222,8 +1222,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_backsector->floorheight - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_bot) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_bot) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1333,13 +1333,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Peg it to the floor if (gl_linedef->flags & ML_MIDPEG) { - polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset; + polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polytop = polybottom + midtexheight; } // Peg it to the ceiling else { - polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset; + polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polybottom = polytop - midtexheight; } @@ -1350,9 +1350,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Skew the texture, but peg it to the floor else if (gl_linedef->flags & ML_MIDPEG) { - polybottom = popenbottom + gl_sidedef->rowoffset; + polybottom = popenbottom + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polytop = polybottom + midtexheight; - polybottomslope = popenbottomslope + gl_sidedef->rowoffset; + polybottomslope = popenbottomslope + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; polytopslope = polybottomslope + midtexheight; } // Skew it according to the ceiling's slope @@ -1407,12 +1407,12 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Left side wallVerts[3].t = texturevpeg * grTex->scaleY; wallVerts[0].t = (h - l + texturevpeg) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; // Right side wallVerts[2].t = texturevpegslope * grTex->scaleY; wallVerts[1].t = (hS - lS + texturevpegslope) * grTex->scaleY; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; // set top/bottom coords // Take the texture peg into account, rather than changing the offsets past @@ -1474,19 +1474,19 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // PEGGING if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW)) - texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset; + texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; else if (gl_linedef->flags & ML_DONTPEGBOTTOM) - texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset; + texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset + gl_sidedef->offsety_mid; else // top of texture at top - texturevpeg = gl_sidedef->rowoffset; + texturevpeg = gl_sidedef->rowoffset + gl_sidedef->offsety_mid; grTex = HWR_GetTexture(gl_midtexture); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; // Texture correction for slopes if (gl_linedef->flags & ML_NOSKEW) { @@ -1634,13 +1634,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // -- Monster Iestyn 26/06/18 if (newline) { - texturevpeg = sides[newline->sidenum[0]].rowoffset; + texturevpeg = sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid; attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM); slopeskew = !!(newline->flags & ML_SKEWTD); } else { - texturevpeg = sides[rover->master->sidenum[0]].rowoffset; + texturevpeg = sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid; attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM); slopeskew = !!(rover->master->flags & ML_SKEWTD); } @@ -1672,8 +1672,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } } - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; } if (rover->fofflags & FOF_FOG) { @@ -1785,17 +1785,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (newline) { - wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY; + wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) + sides[newline->sidenum[0]].offsety_mid) * grTex->scaleY; } else { - wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY; + wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid)) * grTex->scaleY; } - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX; } if (rover->fofflags & FOF_FOG) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index dc477c81f..f73b3c7d2 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -166,6 +166,12 @@ enum side_e { side_valid = 0, side_textureoffset, side_rowoffset, + side_offsetx_top, + side_offsety_top, + side_offsetx_mid, + side_offsety_mid, + side_offsetx_bot, + side_offsety_bot, side_toptexture, side_bottomtexture, side_midtexture, @@ -180,6 +186,12 @@ static const char *const side_opt[] = { "valid", "textureoffset", "rowoffset", + "offsetx_top", + "offsety_top", + "offsetx_mid", + "offsety_mid", + "offsetx_bot", + "offsety_bot", "toptexture", "bottomtexture", "midtexture", @@ -1097,6 +1109,24 @@ static int side_get(lua_State *L) case side_rowoffset: lua_pushfixed(L, side->rowoffset); return 1; + case side_offsetx_top: + lua_pushfixed(L, side->offsetx_top); + return 1; + case side_offsety_top: + lua_pushfixed(L, side->offsety_top); + return 1; + case side_offsetx_mid: + lua_pushfixed(L, side->offsetx_mid); + return 1; + case side_offsety_mid: + lua_pushfixed(L, side->offsety_mid); + return 1; + case side_offsetx_bot: + lua_pushfixed(L, side->offsetx_bot); + return 1; + case side_offsety_bot: + lua_pushfixed(L, side->offsety_bot); + return 1; case side_toptexture: lua_pushinteger(L, side->toptexture); return 1; @@ -1154,6 +1184,24 @@ static int side_set(lua_State *L) case side_rowoffset: side->rowoffset = luaL_checkfixed(L, 3); break; + case side_offsetx_top: + side->offsetx_top = luaL_checkfixed(L, 3); + break; + case side_offsety_top: + side->offsety_top = luaL_checkfixed(L, 3); + break; + case side_offsetx_mid: + side->offsetx_mid = luaL_checkfixed(L, 3); + break; + case side_offsety_mid: + side->offsety_mid = luaL_checkfixed(L, 3); + break; + case side_offsetx_bot: + side->offsetx_bot = luaL_checkfixed(L, 3); + break; + case side_offsety_bot: + side->offsety_bot = luaL_checkfixed(L, 3); + break; case side_toptexture: side->toptexture = luaL_checkinteger(L, 3); break; diff --git a/src/p_maputl.c b/src/p_maputl.c index b6a320730..e36d5fd72 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -509,26 +509,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // on non-solid polyobjects should NEVER happen in the future if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat - texbottom = back->floorheight + side->rowoffset; - textop = back->ceilingheight + side->rowoffset; + texbottom = back->floorheight + side->rowoffset + side->offsety_mid; + textop = back->ceilingheight + side->rowoffset + side->offsety_mid; } else if (linedef->flags & ML_MIDTEX) { - texbottom = back->floorheight + side->rowoffset; + texbottom = back->floorheight + side->rowoffset + side->offsety_mid; textop = texbottom + texheight*(side->repeatcnt+1); } else { - textop = back->ceilingheight + side->rowoffset; + textop = back->ceilingheight + side->rowoffset + side->offsety_mid; texbottom = textop - texheight*(side->repeatcnt+1); } } else #endif { if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat - texbottom = openbottom + side->rowoffset; - textop = opentop + side->rowoffset; + texbottom = openbottom + side->rowoffset + side->offsety_mid; + textop = opentop + side->rowoffset + side->offsety_mid; } else if (linedef->flags & ML_MIDPEG) { - texbottom = openbottom + side->rowoffset; + texbottom = openbottom + side->rowoffset + side->offsety_mid; textop = texbottom + texheight*(side->repeatcnt+1); } else { - textop = opentop + side->rowoffset; + textop = opentop + side->rowoffset + side->offsety_mid; texbottom = textop - texheight*(side->repeatcnt+1); } } diff --git a/src/p_setup.c b/src/p_setup.c index 74645e877..a10326986 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1240,6 +1240,9 @@ static void P_LoadSidedefs(UINT8 *data) } sd->rowoffset = SHORT(msd->rowoffset)<offsetx_top = sd->offsetx_mid = sd->offsetx_bot = 0; + sd->offsety_top = sd->offsety_mid = sd->offsety_bot = 0; + P_SetSidedefSector(i, SHORT(msd->sector)); // Special info stored in texture fields! @@ -1777,6 +1780,18 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char sides[i].textureoffset = atol(val)<> FRACBITS); if (wsides[i].rowoffset != 0) fprintf(f, "offsety = %d;\n", wsides[i].rowoffset >> FRACBITS); + if (wsides[i].offsetx_top != 0) + fprintf(f, "offsetx_top = %d;\n", wsides[i].offsetx_top >> FRACBITS); + if (wsides[i].offsety_top != 0) + fprintf(f, "offsety_top = %d;\n", wsides[i].offsety_top >> FRACBITS); + if (wsides[i].offsetx_mid != 0) + fprintf(f, "offsetx_mid = %d;\n", wsides[i].offsetx_mid >> FRACBITS); + if (wsides[i].offsety_mid != 0) + fprintf(f, "offsety_mid = %d;\n", wsides[i].offsety_mid >> FRACBITS); + if (wsides[i].offsetx_bot != 0) + fprintf(f, "offsetx_bottom = %d;\n", wsides[i].offsetx_bot >> FRACBITS); + if (wsides[i].offsety_bot != 0) + fprintf(f, "offsety_bottom = %d;\n", wsides[i].offsety_bot >> FRACBITS); if (wsides[i].toptexture > 0 && wsides[i].toptexture < numtextures) fprintf(f, "texturetop = \"%.*s\";\n", 8, textures[wsides[i].toptexture]->name); if (wsides[i].bottomtexture > 0 && wsides[i].bottomtexture < numtextures) @@ -2828,6 +2855,8 @@ static void P_LoadTextmap(void) // Defaults. sd->textureoffset = 0; sd->rowoffset = 0; + sd->offsetx_top = sd->offsetx_mid = sd->offsetx_bot = 0; + sd->offsety_top = sd->offsety_mid = sd->offsety_bot = 0; sd->toptexture = R_TextureNumForName("-"); sd->midtexture = R_TextureNumForName("-"); sd->bottomtexture = R_TextureNumForName("-"); diff --git a/src/r_defs.h b/src/r_defs.h index 6d2b7d3d8..963d655b1 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -559,6 +559,10 @@ typedef struct // add this to the calculated texture top fixed_t rowoffset; + // per-texture offsets for UDMF + fixed_t offsetx_top, offsetx_mid, offsetx_bot; + fixed_t offsety_top, offsety_mid, offsety_bot; + // Texture indices. // We do not maintain names here. INT32 toptexture, bottomtexture, midtexture; diff --git a/src/r_segs.c b/src/r_segs.c index 71fc9f9b2..5acca9b17 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -49,6 +49,7 @@ fixed_t rw_distance; static INT32 rw_x, rw_stopx; static angle_t rw_centerangle; static fixed_t rw_offset; +static fixed_t rw_offset_top, rw_offset_mid, rw_offset_bot; static fixed_t rw_offset2; // for splats static fixed_t rw_scale, rw_scalestep; static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid; @@ -778,7 +779,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (newline) { - offsetvalue = sides[newline->sidenum[0]].rowoffset; + offsetvalue = sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid; if (newline->flags & ML_DONTPEGBOTTOM) { skewslope = *pfloor->b_slope; // skew using bottom slope @@ -790,7 +791,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } else { - offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset; + offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset + sides[pfloor->master->sidenum[0]].offsety_mid; if (curline->linedef->flags & ML_DONTPEGBOTTOM) { skewslope = *pfloor->b_slope; // skew using bottom slope @@ -1335,7 +1336,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn); + dc_source = R_GetColumn(midtexture,texturecolumn + (rw_offset_mid>>FRACBITS)); dc_texheight = textureheight[midtexture]>>FRACBITS; //profile stuff --------------------------------------------------------- @@ -1396,7 +1397,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn); + dc_source = R_GetColumn(toptexture,texturecolumn + (rw_offset_top>>FRACBITS)); dc_texheight = textureheight[toptexture]>>FRACBITS; colfunc(); ceilingclip[rw_x] = (INT16)mid; @@ -1433,7 +1434,7 @@ static void R_RenderSegLoop (void) dc_yh = yh; dc_texturemid = rw_bottomtexturemid; dc_source = R_GetColumn(bottomtexture, - texturecolumn); + texturecolumn + (rw_offset_bot>>FRACBITS)); dc_texheight = textureheight[bottomtexture]>>FRACBITS; colfunc(); floorclip[rw_x] = (INT16)mid; @@ -1452,7 +1453,7 @@ static void R_RenderSegLoop (void) { // save texturecol // for backdrawing of masked mid texture - maskedtexturecol[rw_x] = (INT16)texturecolumn; + maskedtexturecol[rw_x] = (INT16)(texturecolumn + (rw_offset_mid>>FRACBITS)); if (maskedtextureheight != NULL) { maskedtextureheight[rw_x] = (curline->linedef->flags & ML_MIDPEG) ? @@ -1783,7 +1784,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_midtexturemid = worldtop; rw_midtextureslide = ceilingfrontslide; } - rw_midtexturemid += sidedef->rowoffset; + rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; ds_p->silhouette = SIL_BOTH; ds_p->sprtopclip = screenheightarray; @@ -2022,8 +2023,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - rw_toptexturemid += sidedef->rowoffset; - rw_bottomtexturemid += sidedef->rowoffset; + rw_toptexturemid += sidedef->rowoffset + sidedef->offsety_top; + rw_bottomtexturemid += sidedef->rowoffset + sidedef->offsety_bot; // allocate space for masked texture tables if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) @@ -2266,8 +2267,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_midtexturebackslide = ceilingbackslide; } } - rw_midtexturemid += sidedef->rowoffset; - rw_midtextureback += sidedef->rowoffset; + rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; + rw_midtextureback += sidedef->rowoffset + sidedef->offsety_mid; maskedtexture = true; } @@ -2305,6 +2306,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) /// don't use texture offset for splats rw_offset2 = rw_offset + curline->offset; rw_offset += sidedef->textureoffset + curline->offset; + rw_offset_top = sidedef->offsetx_top; + rw_offset_mid = sidedef->offsetx_mid; + rw_offset_bot = sidedef->offsetx_bot; rw_centerangle = ANGLE_90 + viewangle - rw_normalangle; // calculate light table From 2c66f2ce27fa097992fbc1e224eb7cfd2da4af69 Mon Sep 17 00:00:00 2001 From: katsy Date: Mon, 3 Jul 2023 16:27:07 -0500 Subject: [PATCH 185/478] Fix homing attack and ring attraction math dumbs --- src/p_enemy.c | 2 +- src/p_user.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index fe062cffc..df2b27af2 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -828,7 +828,7 @@ static boolean P_LookForShield(mobj_t *actor) continue; if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) - && (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale))) + && (R_PointToDist2(0, 0, R_PointToDist2(0, 0, actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale))) { P_SetTarget(&actor->tracer, player->mo); diff --git a/src/p_user.c b/src/p_user.c index 38af2843b..8bb5fb2e4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9217,7 +9217,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) { fixed_t zdist = (player->mo->z + player->mo->height/2) - (mo->z + mo->height/2); - dist = P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y); + dist = R_PointToDist2(0, 0, player->mo->x-mo->x, player->mo->y-mo->y); if (bullet) { if ((R_PointToAngle2(0, 0, dist, zdist) + span) > span*2) @@ -9234,7 +9234,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) continue; } - dist = P_AproxDistance(dist, zdist); + dist = R_PointToDist2(0, 0, dist, zdist); if (dist > maxdist) continue; // out of range } From beda6109b2cc4d903c7c4fbc4cdad8e9879cef76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Mon, 3 Jul 2023 23:30:49 +0200 Subject: [PATCH 186/478] Fix segfault when trying to set a read-only field on player_t --- src/lua_playerlib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 1d06e081b..f76ec1689 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -843,7 +843,7 @@ static int player_get(lua_State *L) return 1; } -#define NOSET luaL_error(L, LUA_QL("player_t") " field " LUA_QS " should not be set directly.", field) +#define NOSET luaL_error(L, LUA_QL("player_t") " field " LUA_QS " should not be set directly.", player_opt[field]) static int player_set(lua_State *L) { player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1392,7 +1392,7 @@ static int power_len(lua_State *L) } #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) -#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", field) +#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", ticcmd_opt[field]) enum ticcmd_e { From 09b9adc8066a31926d9fdbad0e672bbb89e20435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 4 Jul 2023 18:46:49 +0200 Subject: [PATCH 187/478] Fix Lua warning when accessing custom field on mobjinfo --- src/lua_infolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index fb07ccebb..4d150347d 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1168,7 +1168,7 @@ static int mobjinfo_fields_ref = LUA_NOREF; static int mobjinfo_get(lua_State *L) { mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO)); - enum mobjinfo_e field = luaL_checkoption(L, 2, mobjinfo_opt[0], mobjinfo_opt); + enum mobjinfo_e field = Lua_optoption(L, 2, mobjinfo_doomednum, mobjinfo_fields_ref); I_Assert(info != NULL); I_Assert(info >= mobjinfo); From ff7a24df09ac9517be430ea984104ce61242511b Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 5 Jul 2023 12:10:30 +0200 Subject: [PATCH 188/478] Rename Kiwi skincolor to Pear --- src/deh_tables.c | 2 +- src/doomdef.h | 2 +- src/info.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index d53680c19..1614fbecb 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4655,7 +4655,7 @@ const char *COLOR_ENUMS[] = { "GOLDENROD", // SKINCOLOR_GOLDENROD, "YELLOW", // SKINCOLOR_YELLOW, "OLIVE", // SKINCOLOR_OLIVE, - "KIWI", // SKINCOLOR_KIWI, + "PEAR", // SKINCOLOR_PEAR, "LEMON", // SKINCOLOR_LEMON, "LIME", // SKINCOLOR_LIME, "PERIDOT", // SKINCOLOR_PERIDOT, diff --git a/src/doomdef.h b/src/doomdef.h index 20b87f230..84404d6ed 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -307,7 +307,7 @@ typedef enum SKINCOLOR_GOLDENROD, SKINCOLOR_YELLOW, SKINCOLOR_OLIVE, - SKINCOLOR_KIWI, + SKINCOLOR_PEAR, SKINCOLOR_LEMON, SKINCOLOR_LIME, SKINCOLOR_PERIDOT, diff --git a/src/info.c b/src/info.c index 32b21b702..abcf4b499 100644 --- a/src/info.c +++ b/src/info.c @@ -21632,7 +21632,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Goldenrod", { 0, 80, 81, 81, 83, 73, 73, 64, 65, 66, 67, 68, 69, 62, 44, 45}, SKINCOLOR_MAJESTY, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLDENROD {"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW {"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE - {"Kiwi", { 88, 89, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_KIWI + {"Pear", { 88, 89, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_PEAR {"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 8, V_YELLOWMAP, true}, // SKINCOLOR_LEMON {"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME {"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT @@ -21656,7 +21656,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 12, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE {"Aquamarine", { 0, 120, 121, 131, 132, 133, 134, 134, 135, 135, 149, 149, 172, 173, 174, 175}, SKINCOLOR_GARNET, 8, V_SKYMAP, true}, // SKINCOLOR_AQUAMARINE {"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY - {"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_KIWI, 13, V_SKYMAP, true}, // SKINCOLOR_MARINE + {"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_PEAR, 13, V_SKYMAP, true}, // SKINCOLOR_MARINE {"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN {"Dream", { 80, 208, 200, 200, 146, 146, 133, 134, 135, 136, 137, 138, 139, 139, 254, 254}, SKINCOLOR_FOUNDATION, 9, V_SKYMAP, true}, // SKINCOLOR_DREAM {"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY From f261b9f0e118d6b6ac7216514423b06e888ab0e1 Mon Sep 17 00:00:00 2001 From: katsy <205-katsy@users.noreply.git.do.srb2.org> Date: Wed, 5 Jul 2023 17:05:47 +0000 Subject: [PATCH 189/478] Add player->powers[pw_strong], refactor attacks and busting conditions, and allow breaking floors and ceilings separately --- src/d_player.h | 35 +++++++++++++++++ src/deh_tables.c | 28 +++++++++++++- src/p_inter.c | 34 ++++++++--------- src/p_map.c | 90 +++++++++++++++++--------------------------- src/p_saveg.c | 2 + src/p_user.c | 97 ++++++++++++++++++++++++++++++++---------------- 6 files changed, 179 insertions(+), 107 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 6df6689c5..1b2c99743 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -249,6 +249,38 @@ typedef enum CR_FAN } carrytype_t; // pw_carry +typedef enum +{ + STR_NONE = 0, // All strong powers can stack onto each other + + // Attack powers + STR_ANIM = 0x1, // remove powers when leaving current animation + STR_PUNCH = 0x2, // frontal attack (knuckles glide) + STR_TAIL = 0x4, // rear attack + STR_STOMP = 0x8, // falling onto object (fang bounce) + STR_UPPER = 0x10, // moving upwards into object (tails fly) + STR_GUARD = 0x20, //protect against damage + STR_HEAVY = 0x40, // ignore vertical rebound + STR_DASH = 0x80, // special type for machine dashmode, automatically removes your powers when leaving dashmode + + // Environment powers + STR_WALL = 0x100, // fof busting + STR_FLOOR = 0x200, + STR_CEILING = 0x400, + STR_SPRING = 0x800, // power up hit springs + STR_SPIKE = 0x1000, // break spikes + + // Shortcuts + STR_ATTACK = STR_PUNCH|STR_TAIL|STR_STOMP|STR_UPPER, + STR_BUST = STR_WALL|STR_FLOOR|STR_CEILING, + STR_FLY = STR_ANIM|STR_UPPER, + STR_GLIDE = STR_ANIM|STR_PUNCH, + STR_TWINSPIN = STR_ANIM|STR_ATTACK|STR_BUST|STR_SPRING|STR_SPIKE, + STR_MELEE = STR_ANIM|STR_PUNCH|STR_HEAVY|STR_WALL|STR_FLOOR|STR_SPRING|STR_SPIKE, + STR_BOUNCE = STR_ANIM|STR_STOMP|STR_FLOOR, + STR_METAL = STR_DASH|STR_SPIKE +} strongtype_t; // pw_strong + // Player powers. (don't edit this comment) typedef enum { @@ -293,6 +325,8 @@ typedef enum pw_ignorelatch, // Don't grab onto CR_GENERIC, add 32768 (powers[pw_ignorelatch] & 1<<15) to avoid ALL not-NiGHTS CR_ types + pw_strong, // Additional properties for powerful attacks + NUMPOWERS } powertype_t; @@ -405,6 +439,7 @@ typedef struct player_s // playing animation. panim_t panim; + UINT8 stronganim; // For screen flashing (bright). UINT16 flashcount; diff --git a/src/deh_tables.c b/src/deh_tables.c index 11d8b1a01..c7c53f650 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4768,7 +4768,9 @@ const char *const POWERS_LIST[] = { "JUSTLAUNCHED", - "IGNORELATCH" + "IGNORELATCH", + + "STRONG" }; const char *const HUDITEMS_LIST[] = { @@ -5121,6 +5123,30 @@ struct int_const_s const INT_CONST[] = { {"CR_DUSTDEVIL",CR_DUSTDEVIL}, {"CR_FAN",CR_FAN}, + // Strong powers + {"STR_NONE",STR_NONE}, + {"STR_ANIM",STR_ANIM}, + {"STR_PUNCH",STR_PUNCH}, + {"STR_TAIL",STR_TAIL}, + {"STR_STOMP",STR_STOMP}, + {"STR_UPPER",STR_UPPER}, + {"STR_GUARD",STR_GUARD}, + {"STR_HEAVY",STR_HEAVY}, + {"STR_DASH",STR_DASH}, + {"STR_WALL",STR_WALL}, + {"STR_FLOOR",STR_FLOOR}, + {"STR_CEILING",STR_CEILING}, + {"STR_SPRING",STR_SPRING}, + {"STR_SPIKE",STR_SPIKE}, + {"STR_ATTACK",STR_ATTACK}, + {"STR_BUST",STR_BUST}, + {"STR_FLY",STR_FLY}, + {"STR_GLIDE",STR_GLIDE}, + {"STR_TWINSPIN",STR_TWINSPIN}, + {"STR_MELEE",STR_MELEE}, + {"STR_BOUNCE",STR_BOUNCE}, + {"STR_METAL",STR_METAL}, + // Ring weapons (ringweapons_t) // Useful for A_GiveWeapon {"RW_AUTO",RW_AUTO}, diff --git a/src/p_inter.c b/src/p_inter.c index c230ce178..cc8a1d2b9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -465,23 +465,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1) return; // Can't hurt a Pterabyte if it's trying to pick you up - if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) + if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY))) { - if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) + fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce + + if (elementalpierce == 2) // Reset bubblewrap, part 1 + P_DoBubbleBounce(player); + toucher->momz = setmomz; + if (elementalpierce == 2) // Reset bubblewrap, part 2 { - fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce - - if (elementalpierce == 2) // Reset bubblewrap, part 1 - P_DoBubbleBounce(player); - toucher->momz = setmomz; - if (elementalpierce == 2) // Reset bubblewrap, part 2 - { - boolean underwater = toucher->eflags & MFE_UNDERWATER; - - if (underwater) - toucher->momz /= 2; - toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height! - } + boolean underwater = toucher->eflags & MFE_UNDERWATER; + + if (underwater) + toucher->momz /= 2; + toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height! } } if (player->pflags & PF_BOUNCING) @@ -500,8 +497,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->momx = 7*toucher->momx>>3; toucher->momy = 7*toucher->momy>>3; } - else if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) - && player->panim == PA_DASH) + else if ((player->powers[pw_strong] & STR_DASH) && player->panim == PA_DASH) P_DoPlayerPain(player, special, special); } P_DamageMobj(special, toucher, toucher, 1, 0); @@ -3213,7 +3209,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou return false; // Add pity. - if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super] + if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super] && !(player->powers[pw_strong] & STR_GUARD) && source->player->score > player->score) player->pity++; @@ -3683,7 +3679,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } return false; } - else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability + else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super] || (player->powers[pw_strong] & STR_GUARD)) // ignore bouncing & such in invulnerability { if (force || (inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE)) // Super Sonic is stunned! diff --git a/src/p_map.c b/src/p_map.c index 2bb02503f..3dc913435 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -152,10 +152,8 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { if (spring->info->painchance == 3) ; - else if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY) + else if (object->player->powers[pw_strong] & STR_SPRING) strong = 1; - else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2) - strong = 2; } if (spring->info->painchance == -1) // Pinball bumper mode. @@ -455,7 +453,8 @@ springstate: if (strong) { - P_TwinSpinRejuvenate(object->player, (strong == 1 ? object->player->thokitem : object->player->revitem)); + if (object->player->charability == CA_TWINSPIN || object->player->charability2 == CA2_MELEE) + P_TwinSpinRejuvenate(object->player, (object->player->charability == CA_TWINSPIN ? object->player->thokitem : object->player->revitem)); S_StartSound(object, sfx_sprong); // strong spring. sprong. } } @@ -796,43 +795,25 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - // SF_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. - if ((tmthing->player) - && ((((tmthing->player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)) && (tmthing->player->dashmode >= DASHMODE_THRESHOLD) - && (thing->flags & (MF_MONITOR) - || (thing->type == MT_SPIKE - || thing->type == MT_WALLSPIKE))) - || ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY)) - || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)) - && (thing->type == MT_SPIKE - || thing->type == MT_WALLSPIKE)))) + // STR_SPIKE users destroy spikes + if ((tmthing->player) && ((tmthing->player->powers[pw_strong] & STR_SPIKE) && (thing->type == MT_SPIKE || thing->type == MT_WALLSPIKE))) { - if ((thing->flags & (MF_MONITOR)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE))) - return true; - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - return true; // didn't hit it - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - if (thing->type == MT_SPIKE - || thing->type == MT_WALLSPIKE) - { - mobj_t *iter; - if (thing->flags & MF_SOLID) - S_StartSound(tmthing, thing->info->deathsound); - for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) - if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) - P_KillMobj(iter, tmthing, tmthing, 0); - return true; - } - else - { - if (P_DamageMobj(thing, tmthing, tmthing, 1, 0)) - return true; - } + mobj_t *iter; + blockdist = thing->radius + tmthing->radius; + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + return true; // didn't hit it + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + if (thing->flags & MF_SOLID) + S_StartSound(tmthing, thing->info->deathsound); + for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) + if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) + P_KillMobj(iter, tmthing, tmthing, 0); + return true; } // vectorise metal - done in a special case as at this point neither has the right flags for touching @@ -1687,25 +1668,22 @@ static boolean PIT_CheckThing(mobj_t *thing) // Going down? Then bounce back up. if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor && (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up - && (elementalpierce != 1)) // you're not piercing through the monitor... + && (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY))) // you're not piercing through the monitor... { - if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) + fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce + + if (elementalpierce == 2) // Reset bubblewrap, part 1 + P_DoBubbleBounce(player); + *momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically. + if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) + P_TwinSpinRejuvenate(player, player->thokitem); + if (elementalpierce == 2) // Reset bubblewrap, part 2 { - fixed_t setmomz = -*momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce + boolean underwater = tmthing->eflags & MFE_UNDERWATER; - if (elementalpierce == 2) // Reset bubblewrap, part 1 - P_DoBubbleBounce(player); - *momz = setmomz; // Therefore, you should be thrust in the opposite direction, vertically. - if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) - P_TwinSpinRejuvenate(player, player->thokitem); - if (elementalpierce == 2) // Reset bubblewrap, part 2 - { - boolean underwater = tmthing->eflags & MFE_UNDERWATER; - - if (underwater) - *momz /= 2; - *momz -= (*momz/(underwater ? 8 : 4)); // Cap the height! - } + if (underwater) + *momz /= 2; + *momz -= (*momz/(underwater ? 8 : 4)); // Cap the height! } } if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. diff --git a/src/p_saveg.c b/src/p_saveg.c index 07b3d8640..b5907cfb8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -167,6 +167,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].playerstate); WRITEUINT32(save_p, players[i].pflags); WRITEUINT8(save_p, players[i].panim); + WRITEUINT8(save_p, players[i].stronganim); WRITEUINT8(save_p, players[i].spectator); WRITEUINT16(save_p, players[i].flashpal); @@ -394,6 +395,7 @@ static void P_NetUnArchivePlayers(void) players[i].playerstate = READUINT8(save_p); players[i].pflags = READUINT32(save_p); players[i].panim = READUINT8(save_p); + players[i].stronganim = READUINT8(save_p); players[i].spectator = READUINT8(save_p); players[i].flashpal = READUINT16(save_p); diff --git a/src/p_user.c b/src/p_user.c index 2f522ad4b..464cc521d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -988,6 +988,8 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) if (player->powers[pw_carry] == CR_ROPEHANG) P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_strong] = STR_NONE; + { angle_t ang; fixed_t fallbackspeed; @@ -1105,6 +1107,7 @@ void P_ResetPlayer(player_t *player) boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) { fixed_t bottomheight, topheight; + boolean allatk = ((player->powers[pw_strong] & STR_PUNCH) && (player->powers[pw_strong] & STR_TAIL) && (player->powers[pw_strong] & STR_STOMP) && (player->powers[pw_strong] & STR_UPPER)); if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing)) return false; @@ -1129,22 +1132,33 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) // Jumping. if ((player->pflags & PF_JUMPED) - && (!(player->pflags & PF_NOJUMPDAMAGE) - || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + && (!(player->pflags & PF_NOJUMPDAMAGE))) return true; // Spinning. if (player->pflags & PF_SPINNING) return true; - if (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)) + // Shield stomp. + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)) + return true; + + // pw_strong checks below here + + // Omnidirectional attacks. + if (allatk || (player->powers[pw_strong] & STR_DASH)) return true; // From the front. - if (((player->pflags & PF_GLIDING) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) + if ((player->powers[pw_strong] & STR_PUNCH) && (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) < ANGLE_180) return true; + // From the back. + if ((player->powers[pw_strong] & STR_TAIL) + && (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) >= ANGLE_180) + return true; + // From the top/bottom. bottomheight = player->mo->z; topheight = player->mo->z + player->mo->height; @@ -1158,19 +1172,15 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) if (P_MobjFlip(player->mo)*(bottomheight - (thing->z + thing->height/2)) > 0) { - if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) < 0)) + if ((player->charflags & SF_STOMPDAMAGE || player->powers[pw_strong] & STR_STOMP) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) < 0)) return true; } else if (P_MobjFlip(player->mo)*(topheight - (thing->z + thing->height/2)) < 0) { - if (player->charability == CA_FLY && player->panim == PA_ABILITY && !(player->mo->eflags & MFE_UNDERWATER) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) + if ((player->powers[pw_strong] & STR_UPPER) && (player->mo->sprite2 != SPR2_SWIM) && (P_MobjFlip(player->mo)*(player->mo->momz - thing->momz) > 0)) return true; } - // Shield stomp. - if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)) - return true; - return false; } @@ -2324,6 +2334,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; S_StartSound(player->mo, sfx_s3k8b); player->pflags |= PF_FULLSTASIS; + player->powers[pw_strong] = STR_MELEE; // hearticles if (type) @@ -2513,17 +2524,13 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover) return true; // Passive wall breaking - if (player->charflags & SF_CANBUSTWALLS) + if (player->charflags & SF_CANBUSTWALLS || player->powers[pw_strong] & (STR_WALL|STR_FLOOR|STR_CEILING|STR_DASH)) return true; // Super if (player->powers[pw_super]) return true; - // Dashmode - if ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) && player->dashmode >= DASHMODE_THRESHOLD) - return true; - // NiGHTS drill if (player->pflags & PF_DRILLING) return true; @@ -2534,21 +2541,11 @@ static boolean P_PlayerCanBust(player_t *player, ffloor_t *rover) /* FALLTHRU */ case BT_STRONG: // Requires a "strong ability" - if (player->charflags & SF_CANBUSTWALLS) - return true; - - if (player->pflags & PF_BOUNCING) - return true; - - if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) - return true; - - if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + if (player->charflags & SF_CANBUSTWALLS || player->powers[pw_strong] & (STR_WALL|STR_FLOOR|STR_CEILING)) return true; break; } - return false; } @@ -2564,7 +2561,7 @@ static void P_CheckBustableBlocks(player_t *player) oldx = player->mo->x; oldy = player->mo->y; - if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways + if (!((player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) && (!(player->powers[pw_strong] & STR_WALL)) && (!(player->charflags & SF_CANBUSTWALLS)))) // Don't break sideways without wall powers { P_UnsetThingPosition(player->mo); player->mo->x += player->mo->momx; @@ -2591,8 +2588,24 @@ static void P_CheckBustableBlocks(player_t *player) topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); - if (((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) - || ((P_MobjFlip(player->mo)*player->mo->momz < 0) && (player->pflags & PF_BOUNCING || ((player->charability2 == CA2_MELEE) && (player->panim == PA_ABILITY2))))) + // Height checks + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if ((player->powers[pw_strong] & STR_FLOOR) && (!(player->powers[pw_strong] & STR_CEILING)) && player->mo->z > topheight) + continue; + + if ((player->powers[pw_strong] & STR_CEILING) && (!(player->powers[pw_strong] & STR_FLOOR)) && player->mo->z + player->mo->height < bottomheight) + continue; + } + else + { + if ((player->powers[pw_strong] & STR_FLOOR) && (!(player->powers[pw_strong] & STR_CEILING)) && player->mo->z < bottomheight) + continue; + + if ((player->powers[pw_strong] & STR_CEILING) && (!(player->powers[pw_strong] & STR_FLOOR)) && player->mo->z + player->mo->height > topheight) + continue; + } + if (player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) { topheight -= player->mo->momz; bottomheight -= player->mo->momz; @@ -2660,7 +2673,7 @@ static void P_CheckBustableBlocks(player_t *player) } } bustupdone: - if (!(player->pflags & PF_BOUNCING)) + if (!((player->powers[pw_strong] & (STR_FLOOR|STR_CEILING)) && (!(player->powers[pw_strong] & STR_WALL)) && (!(player->charflags & SF_CANBUSTWALLS)))) { P_UnsetThingPosition(player->mo); player->mo->x = oldx; @@ -4690,6 +4703,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) player->mo->momx += player->cmomx; player->mo->momy += player->cmomy; P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); + player->powers[pw_strong] = STR_MELEE; S_StartSound(player->mo, sfx_s3k42); } player->pflags |= PF_SPINDOWN; @@ -4937,6 +4951,7 @@ static void P_DoTwinSpin(player_t *player) S_StartSound(player->mo, sfx_s3k42); player->mo->frame = 0; P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN); + player->powers[pw_strong] = STR_TWINSPIN; } // @@ -5300,6 +5315,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags |= PF_THOKKED; else player->pflags |= (PF_THOKKED|PF_CANCARRY); + player->powers[pw_strong] = STR_FLY; } break; case CA_GLIDEANDCLIMB: @@ -5326,7 +5342,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); if (playerspeed < glidespeed) P_Thrust(player->mo, player->mo->angle, glidespeed - playerspeed); - player->pflags &= ~(PF_SPINNING|PF_STARTDASH); + player->pflags &= ~(PF_JUMPED|PF_SPINNING|PF_STARTDASH); + player->powers[pw_strong] = STR_GLIDE; } break; case CA_DOUBLEJUMP: // Double-Jump @@ -5383,6 +5400,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE); player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); player->pflags |= PF_THOKKED|PF_BOUNCING; + player->powers[pw_strong] = STR_BOUNCE; player->mo->momx >>= 1; player->mo->momy >>= 1; player->mo->momz >>= 1; @@ -12070,6 +12088,16 @@ void P_PlayerThink(player_t *player) else player->powers[pw_ignorelatch] = 0; + if (player->powers[pw_strong] & STR_ANIM) + { + if (!(player->stronganim)) + player->stronganim = player->panim; + else if (player->panim != player->stronganim) + player->powers[pw_strong] = STR_NONE; + } + else if (player->stronganim) + player->stronganim = 0; + //pw_super acts as a timer now if (player->powers[pw_super] && (player->mo->state < &states[S_PLAY_SUPER_TRANS1] @@ -12164,6 +12192,8 @@ void P_PlayerThink(player_t *player) { player->normalspeed = skins[player->skin].normalspeed; // Reset to default if not capable of entering dash mode. player->jumpfactor = skins[player->skin].jumpfactor; + if (player->powers[pw_strong] & STR_DASH) + player->powers[pw_strong] = STR_NONE; } } else if (P_IsObjectOnGround(player->mo)) // Activate dash mode if we're on the ground. @@ -12173,6 +12203,9 @@ void P_PlayerThink(player_t *player) if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height. player->jumpfactor += FRACUNIT/300; + + if ((player->charflags & SF_MACHINE) && (!(player->powers[pw_strong] == STR_METAL))) + player->powers[pw_strong] = STR_METAL; } if (player->normalspeed >= skins[player->skin].normalspeed*2) @@ -12190,6 +12223,8 @@ void P_PlayerThink(player_t *player) player->normalspeed = skins[player->skin].normalspeed; player->jumpfactor = skins[player->skin].jumpfactor; S_StartSound(player->mo, sfx_kc65); + if (player->powers[pw_strong] & STR_DASH) + player->powers[pw_strong] = STR_NONE; } dashmode = 0; } From 4342dacbdff30383d7e804cb2bb46d20045852c1 Mon Sep 17 00:00:00 2001 From: MIDIMan Date: Wed, 5 Jul 2023 14:21:53 -0400 Subject: [PATCH 190/478] Fix A_FishJump for custom objects in binary maps --- src/p_enemy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index fe062cffc..5e52993cc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4886,7 +4886,9 @@ void A_FishJump(mobj_t *actor) jumpval = locvar1; else { - if (actor->spawnpoint && actor->spawnpoint->args[0]) + if (!udmf && actor->angle) + jumpval = AngleFixed(actor->angle)>>2; + else if (actor->spawnpoint && actor->spawnpoint->args[0]) jumpval = actor->spawnpoint->args[0] << (FRACBITS - 2); else jumpval = 44 << (FRACBITS - 2); From 8f75141c0779c6ec6e8ee91dc796341029f691e8 Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 6 Jul 2023 12:38:02 +0200 Subject: [PATCH 191/478] Give drop shadows to weapon rings & panels --- src/p_mobj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index a43afc9b1..44140042e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10581,6 +10581,8 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) if (thing->flags & (MF_ENEMY|MF_BOSS)) return FRACUNIT; + else if (P_WeaponOrPanel(thing->type)) + return 2*FRACUNIT/3; else return 0; } From a4bcf4e2cefa850fa0996e19e0fdb6d502cbafad Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 6 Jul 2023 18:06:23 +0200 Subject: [PATCH 192/478] Do not consider 0 a valid executor tag for bosses --- src/p_enemy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index fe062cffc..e00a1a882 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3938,7 +3938,7 @@ static void P_DoBossVictory(mobj_t *mo) } // victory! - if (mo->spawnpoint) + if (mo->spawnpoint && mo->spawnpoint->args[3]) P_LinedefExecute(mo->spawnpoint->args[3], mo, NULL); if (stoppedclock && modeattacking) // if you're just time attacking, skip making the capsule appear since you don't need to step on it anyways. @@ -4157,7 +4157,7 @@ void A_BossDeath(mobj_t *mo) if (LUA_CallAction(A_BOSSDEATH, mo)) return; - if (mo->spawnpoint) + if (mo->spawnpoint && mo->spawnpoint->args[2]) P_LinedefExecute(mo->spawnpoint->args[2], mo, NULL); mo->health = 0; @@ -7136,7 +7136,7 @@ void A_Boss1Chase(mobj_t *actor) } else { - if (actor->spawnpoint) + if (actor->spawnpoint && actor->spawnpoint->args[4]) P_LinedefExecute(actor->spawnpoint->args[4], actor, NULL); P_SetMobjState(actor, actor->info->raisestate); } From 49528c15580f6c710ca8fd222d413fdb2caa13a6 Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 6 Jul 2023 18:11:52 +0200 Subject: [PATCH 193/478] Remove generalized FOF type (linedef action 260) --- src/p_spec.c | 65 ---------------------------------------------------- 1 file changed, 65 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 71ea145b9..9195ef019 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6880,71 +6880,6 @@ void P_SpawnSpecials(boolean fromnetsave) } break; - case 260: // GZDoom-like 3D Floor. - { - UINT8 dtype = lines[i].args[1] & 3; - UINT8 dflags1 = lines[i].args[1] - dtype; - UINT8 dflags2 = lines[i].args[2]; - UINT8 dopacity = lines[i].args[3]; - boolean isfog = false; - - if (dtype == 0) - dtype = 1; - - ffloorflags = FOF_EXISTS; - - if (dflags2 & 1) ffloorflags |= FOF_NOSHADE; // Disable light effects (Means no shadowcast) - if (dflags2 & 2) ffloorflags |= FOF_DOUBLESHADOW; // Restrict light inside (Means doubleshadow) - if (dflags2 & 4) isfog = true; // Fog effect (Explicitly render like a fog block) - - if (dflags1 & 4) ffloorflags |= FOF_BOTHPLANES|FOF_ALLSIDES; // Render-inside - if (dflags1 & 16) ffloorflags |= FOF_INVERTSIDES|FOF_INVERTPLANES; // Invert visibility rules - - // Fog block - if (isfog) - ffloorflags |= FOF_RENDERALL|FOF_CUTEXTRA|FOF_CUTSPRITES|FOF_BOTHPLANES|FOF_EXTRA|FOF_FOG|FOF_INVERTPLANES|FOF_ALLSIDES|FOF_INVERTSIDES; - else - { - ffloorflags |= FOF_RENDERALL; - - // Solid - if (dtype == 1) - ffloorflags |= FOF_SOLID|FOF_CUTLEVEL; - // Water - else if (dtype == 2) - ffloorflags |= FOF_SWIMMABLE|FOF_CUTEXTRA|FOF_CUTSPRITES|FOF_EXTRA|FOF_RIPPLE; - // Intangible - else if (dtype == 3) - ffloorflags |= FOF_CUTEXTRA|FOF_CUTSPRITES|FOF_EXTRA; - } - - // Non-opaque - if (dopacity < 255) - { - // Invisible - if (dopacity == 0) - { - // True invisible - if (ffloorflags & FOF_NOSHADE) - ffloorflags &= ~(FOF_RENDERALL|FOF_CUTEXTRA|FOF_CUTSPRITES|FOF_EXTRA|FOF_BOTHPLANES|FOF_ALLSIDES|FOF_CUTLEVEL); - // Shadow block - else - { - ffloorflags |= FOF_CUTSPRITES; - ffloorflags &= ~(FOF_RENDERALL|FOF_CUTEXTRA|FOF_EXTRA|FOF_BOTHPLANES|FOF_ALLSIDES|FOF_CUTLEVEL); - } - } - else - { - ffloorflags |= FOF_TRANSLUCENT|FOF_CUTEXTRA|FOF_EXTRA; - ffloorflags &= ~FOF_CUTLEVEL; - } - } - - P_AddFakeFloorsByLine(i, dopacity, TMB_TRANSLUCENT, ffloorflags, secthinkers); - } - break; - case 300: // Trigger linedef executor case 303: // Count rings case 305: // Character ability From 29703f8d6ad7c4923bd088416b874373f2d74d1a Mon Sep 17 00:00:00 2001 From: spherallic Date: Thu, 6 Jul 2023 18:26:30 +0200 Subject: [PATCH 194/478] Remove action 260 from the UDMF config --- extras/conf/udb/Includes/SRB222_linedefs.cfg | 46 -------------------- 1 file changed, 46 deletions(-) diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 621b4abd5..680778623 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -1221,52 +1221,6 @@ udmf } } } - 260 - { - title = "Generalized 3D Floor"; - prefix = "(260)"; - id = "Sector_Set3dFloor"; - requiresactivation = false; - - arg0 - { - title = "Target sector tag"; - type = 13; - } - arg1 - { - title = "Type"; - type = 26; - default = 1; - enum - { - 1 = "Solid"; - 2 = "Water"; - 3 = "Intangible"; - } - flags - { - 4 = "Render insides"; - 16 = "Only render insides"; - } - } - arg2 - { - title = "Flags"; - type = 12; - enum - { - 1 = "No shadow"; - 2 = "Double shadow"; - 4 = "Fog"; - } - } - arg3 - { - title = "Alpha"; - default = 255; - } - } } linedeftrigger From 8d8257b4a642cda4061c50e4afca2b62f5490af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Thu, 6 Jul 2023 19:12:29 +0200 Subject: [PATCH 195/478] Handle missing frames for sprite gracefully --- src/r_skins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_skins.c b/src/r_skins.c index 2c031ee85..db3227307 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -534,7 +534,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); if (skin->sprites[0].numframes == 0) - I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]); + CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]); } // returns whether found appropriate property From 372bb8b8fc10e2eee4f1ede2e6460c3cda6521c9 Mon Sep 17 00:00:00 2001 From: Ace Lite Date: Thu, 6 Jul 2023 19:27:32 +0000 Subject: [PATCH 196/478] [UDMF] Updated line sloping warning message --- src/p_slopes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 48a13a07d..1f07b8f37 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -328,7 +328,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) if(!frontfloor && !backfloor && !frontceil && !backceil) { - CONS_Printf("line_SpawnViaLine: Slope special with nothing to do.\n"); + CONS_Printf("line_SpawnViaLine: Unused slope special with nothing to do on line number %i\n", linenum); return; } From ecf0c4b45a756039ccde6ffd1845c0232220952d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Fri, 7 Jul 2023 21:35:41 +0200 Subject: [PATCH 197/478] Fix segfault when calling P_RemoveMobj from MobjCollide hook --- src/p_map.c | 240 ++++++++++++++++++++++++++-------------------------- 1 file changed, 122 insertions(+), 118 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 0021fe450..0221fbc11 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4005,131 +4005,135 @@ void P_BounceMove(mobj_t *mo) slidemo = mo; hitcount = 0; -retry: - if (++hitcount == 3) - goto bounceback; // don't loop forever + do + { + if (++hitcount == 3) + goto bounceback; // don't loop forever - if (mo->player) - { - mmomx = mo->player->rmomx; - mmomy = mo->player->rmomy; - } - else - { - mmomx = mo->momx; - mmomy = mo->momy; - } - - // trace along the three leading corners - if (mo->momx > 0) - { - leadx = mo->x + mo->radius; - trailx = mo->x - mo->radius; - } - else - { - leadx = mo->x - mo->radius; - trailx = mo->x + mo->radius; - } - - if (mo->momy > 0) - { - leady = mo->y + mo->radius; - traily = mo->y - mo->radius; - } - else - { - leady = mo->y - mo->radius; - traily = mo->y + mo->radius; - } - - bestslidefrac = FRACUNIT + 1; - - P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); - P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); - - // move up to the wall - if (bestslidefrac == FRACUNIT + 1) - { - // the move must have hit the middle, so bounce straight back -bounceback: - if (P_TryMove(mo, mo->x - mmomx, mo->y - mmomy, true)) + if (mo->player) { - mo->momx *= -1; - mo->momy *= -1; - mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + mmomx = mo->player->rmomx; + mmomy = mo->player->rmomy; + } + else + { + mmomx = mo->momx; + mmomy = mo->momy; + } - if (mo->player) + // trace along the three leading corners + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + bestslidefrac = FRACUNIT + 1; + + P_PathTraverse(leadx, leady, leadx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(trailx, leady, trailx + mmomx, leady + mmomy, PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(leadx, traily, leadx + mmomx, traily + mmomy, PT_ADDLINES, PTR_SlideTraverse); + + // move up to the wall + if (bestslidefrac == FRACUNIT + 1) + { + // the move must have hit the middle, so bounce straight back +bounceback: + if (P_TryMove(mo, mo->x - mmomx, mo->y - mmomy, true)) { - mo->player->cmomx *= -1; - mo->player->cmomy *= -1; - mo->player->cmomx = FixedMul(mo->player->cmomx, - (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - mo->player->cmomy = FixedMul(mo->player->cmomy, - (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + mo->momx *= -1; + mo->momy *= -1; + mo->momx = FixedMul(mo->momx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + mo->momy = FixedMul(mo->momy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + + if (mo->player) + { + mo->player->cmomx *= -1; + mo->player->cmomy *= -1; + mo->player->cmomx = FixedMul(mo->player->cmomx, + (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + mo->player->cmomy = FixedMul(mo->player->cmomy, + (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + } + } + return; + } + + // fudge a bit to make sure it doesn't hit + bestslidefrac -= 0x800; + if (bestslidefrac > 0) + { + newx = FixedMul(mmomx, bestslidefrac); + newy = FixedMul(mmomy, bestslidefrac); + + if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) + { + if (P_MobjWasRemoved(mo)) + return; + goto bounceback; } } - return; + + // Now continue along the wall. + // First calculate remainder. + bestslidefrac = FRACUNIT - bestslidefrac; + + if (bestslidefrac > FRACUNIT) + bestslidefrac = FRACUNIT; + + if (bestslidefrac <= 0) + return; + + if (mo->type == MT_SHELL) + { + tmxmove = mmomx; + tmymove = mmomy; + } + else if (mo->type == MT_THROWNBOUNCE) + { + tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); + tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); + } + else if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE) + { + // Quickly decay speed as it bounces + tmxmove = FixedDiv(mmomx, 2*FRACUNIT); + tmymove = FixedDiv(mmomy, 2*FRACUNIT); + } + else + { + tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); + } + + P_HitBounceLine(bestslideline); // clip the moves + + mo->momx = tmxmove; + mo->momy = tmymove; + + if (mo->player) + { + mo->player->cmomx = tmxmove; + mo->player->cmomy = tmymove; + } } - - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - if (bestslidefrac > 0) - { - newx = FixedMul(mmomx, bestslidefrac); - newy = FixedMul(mmomy, bestslidefrac); - - if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) - goto bounceback; - } - - // Now continue along the wall. - // First calculate remainder. - bestslidefrac = FRACUNIT - bestslidefrac; - - if (bestslidefrac > FRACUNIT) - bestslidefrac = FRACUNIT; - - if (bestslidefrac <= 0) - return; - - if (mo->type == MT_SHELL) - { - tmxmove = mmomx; - tmymove = mmomy; - } - else if (mo->type == MT_THROWNBOUNCE) - { - tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); - tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); - } - else if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE) - { - // Quickly decay speed as it bounces - tmxmove = FixedDiv(mmomx, 2*FRACUNIT); - tmymove = FixedDiv(mmomy, 2*FRACUNIT); - } - else - { - tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); - } - - P_HitBounceLine(bestslideline); // clip the moves - - mo->momx = tmxmove; - mo->momy = tmymove; - - if (mo->player) - { - mo->player->cmomx = tmxmove; - mo->player->cmomy = tmymove; - } - - if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) - goto retry; + while (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true) && !P_MobjWasRemoved(mo)); } // From 3ff9e908feac1349fefccf11a171f3e1c21d6a09 Mon Sep 17 00:00:00 2001 From: Tatsuru <44866610+TatsuruIKR@users.noreply.github.com> Date: Fri, 7 Jul 2023 18:13:44 -0300 Subject: [PATCH 198/478] Signal handler minor refactor --- src/sdl/i_system.c | 76 +++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 66eeffa30..847ab2646 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -325,56 +325,90 @@ static void write_backtrace(INT32 signal) static void I_ReportSignal(int num, int coredumped) { //static char msg[] = "oh no! back to reality!\r\n"; - const char * sigmsg; - char msg[128]; + const char *sigmsg, *sigttl; + char ttl[128]; switch (num) { // case SIGINT: -// sigmsg = "SIGINT - interrupted"; +// sigttl = "SIGINT" +// sigmsg = "SRB2 was interrupted prematurely by the user."; // break; case SIGILL: - sigmsg = "SIGILL - illegal instruction - invalid function image"; + sigmsg = "SRB2 has attempted to execute an illegal instruction and needs to close. %s"; + sigttl = "SIGILL"; // illegal instruction - invalid function image break; case SIGFPE: - sigmsg = "SIGFPE - mathematical exception"; + sigmsg = "SRB2 has encountered a mathematical exception and needs to close. %s"; + sigttl = "SIGFPE"; // mathematical exception break; case SIGSEGV: - sigmsg = "SIGSEGV - segment violation"; + sigmsg = "SRB2 has attempted to access a memory location that it shouldn't and needs to close. %s"; + sigttl = "SIGSEGV"; // segment violation break; // case SIGTERM: -// sigmsg = "SIGTERM - Software termination signal from kill"; +// sigmsg = "SRB2 was terminated by a kill signal."; +// sigttl = "SIGTERM"; // Software termination signal from kill // break; // case SIGBREAK: -// sigmsg = "SIGBREAK - Ctrl-Break sequence"; +// sigmsg = "SRB2 was terminated by a Ctrl-Break sequence."; +// sigttl = "SIGBREAK" // Ctrl-Break sequence // break; case SIGABRT: - sigmsg = "SIGABRT - abnormal termination triggered by abort call"; + sigmsg = "SRB2 was terminated by an abort signal. %s"; + sigttl = "SIGABRT"; // abnormal termination triggered by abort call break; default: - sprintf(msg,"signal number %d", num); + sigmsg = "SRB2 was terminated by an unknown signal. %s"; + + sprintf(ttl, "number %d", num); if (coredumped) - sigmsg = 0; + sigttl = 0; else - sigmsg = msg; + sigttl = ttl; } if (coredumped) { - if (sigmsg) - sprintf(msg, "%s (core dumped)", sigmsg); + if (sigttl) + sprintf(ttl, "%s (core dumped)", sigttl); else - strcat(msg, " (core dumped)"); + strcat(ttl, " (core dumped)"); - sigmsg = msg; + sigttl = ttl; } - I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg); + sprintf(ttl, "Process killed by signal: %s", sigttl); - if (!M_CheckParm("-dedicated")) - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, - "Process killed by signal", - sigmsg, NULL); + sigttl = ttl; + + I_OutputMsg("\n%s\n\n", sigttl); + + if (M_CheckParm("-dedicated")) + return; + + const SDL_MessageBoxButtonData buttons[] = { + { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 0, "OK" }, + { 0, 1, "Discord" }, + }; + + const SDL_MessageBoxData messageboxdata = { + SDL_MESSAGEBOX_ERROR, /* .flags */ + NULL, /* .window */ + sigttl, /* .title */ + va(sigmsg, + "\n\nTo help us figure out the cause, you can visit our official Discord server\nwhere you will find more instructions on how to submit a crash report.\n\nSorry for the inconvenience!"), /* .message */ + SDL_arraysize(buttons), /* .numbuttons */ + buttons, /* .buttons */ + NULL /* .colorScheme */ + }; + + int buttonid; + + SDL_ShowMessageBox(&messageboxdata, &buttonid); + + if (buttonid == 1) + SDL_OpenURL("https://www.srb2.org/discord"); } #ifndef NEWSIGNALHANDLER From 0aa763df8543cf98eb2ca8da1d3a77e80f3a3119 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sat, 8 Jul 2023 00:53:28 -0300 Subject: [PATCH 199/478] Do music fade callback on main thread --- src/sdl/mixer_sound.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index f13aaef5d..0a39c7f28 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -108,6 +108,7 @@ static UINT32 fading_timer; static UINT32 fading_duration; static INT32 fading_id; static void (*fading_callback)(void); +static boolean fading_do_callback; static boolean fading_nocleanup; #ifdef HAVE_GME @@ -213,7 +214,10 @@ static void var_cleanup(void) // HACK: See music_loop, where we want the fade timing to proceed after a non-looping // song has stopped playing if (!fading_nocleanup) + { fading_callback = NULL; + fading_do_callback = false; + } else fading_nocleanup = false; // use it once, set it back immediately @@ -330,6 +334,13 @@ void I_ShutdownSound(void) void I_UpdateSound(void) { + if (fading_do_callback) + { + if (fading_callback) + (*fading_callback)(); + fading_callback = NULL; + fading_do_callback = false; + } } /// ------------------------ @@ -654,9 +665,8 @@ static UINT32 get_adjusted_position(UINT32 position) static void do_fading_callback(void) { - if (fading_callback) - (*fading_callback)(); - fading_callback = NULL; + // TODO: Should I use a mutex here or something? + fading_do_callback = true; } /// ------------------------ From 281e6012f3cf5b27dde2816ad1bacb4fe50c8634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 8 Jul 2023 14:02:32 +0200 Subject: [PATCH 200/478] Fix segfault when exiting game with automap open --- src/d_netcmd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index af44e53d6..361d32008 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4609,6 +4609,7 @@ void Command_ExitGame_f(void) botskin = 0; cv_debug = 0; emeralds = 0; + automapactive = false; memset(&luabanks, 0, sizeof(luabanks)); if (dirmenu) From 8cc0feb21d41adebe9faef6cd5484d912e0c8e08 Mon Sep 17 00:00:00 2001 From: katsy Date: Sat, 8 Jul 2023 15:17:53 -0500 Subject: [PATCH 201/478] fix reading and writing of shieldscale and camerascale to record attack demos --- src/g_demo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 0403da16d..51001c6d0 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1493,8 +1493,8 @@ void G_BeginRecording(void) WRITEUINT8(demo_p,player->acceleration); WRITEFIXED(demo_p,player->height); WRITEFIXED(demo_p,player->spinheight); - WRITEUINT8(demo_p,player->camerascale>>FRACBITS); - WRITEUINT8(demo_p,player->shieldscale>>FRACBITS); + WRITEFIXED(demo_p,player->camerascale); + WRITEFIXED(demo_p,player->shieldscale); // Trying to convert it back to % causes demo desync due to precision loss. // Don't do it. @@ -1923,8 +1923,8 @@ void G_DoPlayDemo(char *defdemoname) acceleration = READUINT8(demo_p); height = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)< Date: Sat, 8 Jul 2023 16:14:37 -0500 Subject: [PATCH 202/478] actually, make all player stats precise --- src/g_demo.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 51001c6d0..3dbbe6c47 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -95,7 +95,7 @@ demoghost *ghosts = NULL; // DEMO RECORDING // -#define DEMOVERSION 0x000f +#define DEMOVERSION 0x0010 #define DEMOHEADER "\xF0" "SRB2Replay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -1483,11 +1483,11 @@ void G_BeginRecording(void) // Stats WRITEUINT8(demo_p,player->charability); WRITEUINT8(demo_p,player->charability2); - WRITEUINT8(demo_p,player->actionspd>>FRACBITS); - WRITEUINT8(demo_p,player->mindash>>FRACBITS); - WRITEUINT8(demo_p,player->maxdash>>FRACBITS); - WRITEUINT8(demo_p,player->normalspeed>>FRACBITS); - WRITEUINT8(demo_p,player->runspeed>>FRACBITS); + WRITEFIXED(demo_p,player->actionspd); + WRITEFIXED(demo_p,player->mindash); + WRITEFIXED(demo_p,player->maxdash); + WRITEFIXED(demo_p,player->normalspeed); + WRITEFIXED(demo_p,player->runspeed); WRITEUINT8(demo_p,player->thrustfactor); WRITEUINT8(demo_p,player->accelstart); WRITEUINT8(demo_p,player->acceleration); @@ -1687,7 +1687,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) switch(oldversion) // demoversion { case DEMOVERSION: // latest always supported - case 0x000e: // The previous demoversions also supported + case 0x000f: // The previous demoversions also supported + case 0x000e: case 0x000d: // all that changed between then and now was longer color name case 0x000c: break; @@ -1831,6 +1832,7 @@ void G_DoPlayDemo(char *defdemoname) demoversion = READUINT16(demo_p); switch(demoversion) { + case 0x000f: case 0x000d: case 0x000e: case DEMOVERSION: // latest always supported @@ -1913,18 +1915,18 @@ void G_DoPlayDemo(char *defdemoname) charability = READUINT8(demo_p); charability2 = READUINT8(demo_p); - actionspd = (fixed_t)READUINT8(demo_p)< Date: Mon, 10 Jul 2023 15:40:20 -0700 Subject: [PATCH 203/478] Buffer ticcmds when receiving two on same tic --- src/d_clisrv.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index ca9f4a24e..7d62272ff 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4565,12 +4565,17 @@ static void HandlePacketFromPlayer(SINT8 node) /// \todo Use a separate cvar for that kind of timeout? freezetimeout[node] = I_GetTime() + connectiontimeout; + // If we've alredy received a ticcmd for this tic, just submit it for the next one. + tic_t faketic = maketic; + if (!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED)) + faketic++; + // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); // Check ticcmd for "speed hacks" - if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) + if (netcmds[faketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[faketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE + || netcmds[faketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[faketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) { CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); //D_Clearticcmd(k); @@ -4582,9 +4587,10 @@ static void HandlePacketFromPlayer(SINT8 node) // Splitscreen cmd if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) && nodetoplayer2[node] >= 0) - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], + G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], &netbuffer->u.client2pak.cmd2, 1); + // Check player consistancy during the level if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) From 576262f6c59d000efc7c9f48e860d3b74a2b1da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 11 Jul 2023 16:37:45 +0200 Subject: [PATCH 204/478] Fix inaccuracies in FPS counter --- src/screen.c | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/screen.c b/src/screen.c index f8af4c504..f4982111d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -462,11 +462,10 @@ double averageFPS = 0.0f; #define USE_FPS_SAMPLES #ifdef USE_FPS_SAMPLES -#define FPS_SAMPLE_RATE (0.05) // How often to update FPS samples, in seconds -#define NUM_FPS_SAMPLES (16) // Number of samples to store +#define NUM_FPS_SAMPLES (32) // Number of samples to store static double fps_samples[NUM_FPS_SAMPLES]; -static double updateElapsed = 0.0; +static int fps_index; #endif static boolean fps_init = false; @@ -475,6 +474,7 @@ static precise_t fps_enter = 0; void SCR_CalculateFPS(void) { precise_t fps_finish = 0; + int i; double frameElapsed = 0.0; @@ -489,35 +489,13 @@ void SCR_CalculateFPS(void) fps_enter = fps_finish; #ifdef USE_FPS_SAMPLES - updateElapsed += frameElapsed; + fps_samples[fps_index] = frameElapsed / NUM_FPS_SAMPLES; + fps_index = (fps_index + 1) % NUM_FPS_SAMPLES; - if (updateElapsed >= FPS_SAMPLE_RATE) - { - static int sampleIndex = 0; - int i; - - fps_samples[sampleIndex] = frameElapsed; - - sampleIndex++; - if (sampleIndex >= NUM_FPS_SAMPLES) - sampleIndex = 0; - - averageFPS = 0.0; - for (i = 0; i < NUM_FPS_SAMPLES; i++) - { - averageFPS += fps_samples[i]; - } - - if (averageFPS > 0.0) - { - averageFPS = 1.0 / (averageFPS / NUM_FPS_SAMPLES); - } - } - - while (updateElapsed >= FPS_SAMPLE_RATE) - { - updateElapsed -= FPS_SAMPLE_RATE; - } + averageFPS = 0.0; + for (i = 0; i < NUM_FPS_SAMPLES; i++) + averageFPS += fps_samples[i]; + averageFPS = 1.0 / averageFPS; #else // Direct, unsampled counter. averageFPS = 1.0 / frameElapsed; From 73ded4787c9c2c5d529917ab456510e9f32fa6a6 Mon Sep 17 00:00:00 2001 From: spherallic Date: Tue, 11 Jul 2023 19:00:47 +0200 Subject: [PATCH 205/478] Fix ammo/panel/emerald hitboxes, add shadows to thrown rings --- src/info.c | 38 +++++++++++++++++++------------------- src/p_mobj.c | 25 +++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/info.c b/src/info.c index abcf4b499..eab6ac82a 100644 --- a/src/info.c +++ b/src/info.c @@ -7194,7 +7194,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD1, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7220,7 +7220,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD2, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7246,7 +7246,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD3, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7272,7 +7272,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD4, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7298,7 +7298,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD5, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7324,7 +7324,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD6, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -7350,7 +7350,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_cgot, // deathsound EMERALD7, // speed 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 24*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage @@ -18344,7 +18344,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_bouncering, // mass @@ -18371,7 +18371,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_railring, // mass @@ -18425,7 +18425,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_automaticring, // mass @@ -18452,7 +18452,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_explosionring, // mass @@ -18479,7 +18479,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_scatterring, // mass @@ -18506,7 +18506,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_itemup, // deathsound 60*FRACUNIT, // speed - 24*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset pw_grenadering, // mass @@ -18535,7 +18535,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_bouncering, // mass 2*TICRATE, // damage @@ -18562,7 +18562,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_railring, // mass 2*TICRATE, // damage @@ -18589,7 +18589,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_automaticring, // mass 2*TICRATE, // damage @@ -18616,7 +18616,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_explosionring, // mass 2*TICRATE, // damage @@ -18643,7 +18643,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_scatterring, // mass 2*TICRATE, // damage @@ -18670,7 +18670,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_ncitem, // deathsound 60*FRACUNIT, // speed 24*FRACUNIT, // radius - 24*FRACUNIT, // height + 40*FRACUNIT, // height 0, // display offset pw_grenadering, // mass 2*TICRATE, // damage diff --git a/src/p_mobj.c b/src/p_mobj.c index 44140042e..152513d1b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10541,6 +10541,29 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) case MT_REDFLAG: case MT_BLUEFLAG: + case MT_BOUNCERING: + case MT_AUTOMATICRING: + case MT_INFINITYRING: + case MT_RAILRING: + case MT_EXPLOSIONRING: + case MT_SCATTERRING: + case MT_GRENADERING: + + case MT_BOUNCEPICKUP: + case MT_RAILPICKUP: + case MT_AUTOPICKUP: + case MT_EXPLODEPICKUP: + case MT_SCATTERPICKUP: + case MT_GRENADEPICKUP: + + case MT_REDRING: + case MT_THROWNBOUNCE: + case MT_THROWNINFINITY: + case MT_THROWNAUTOMATIC: + case MT_THROWNSCATTER: + case MT_THROWNEXPLOSION: + case MT_THROWNGRENADE: + case MT_EMBLEM: case MT_TOKEN: @@ -10581,8 +10604,6 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) if (thing->flags & (MF_ENEMY|MF_BOSS)) return FRACUNIT; - else if (P_WeaponOrPanel(thing->type)) - return 2*FRACUNIT/3; else return 0; } From 464110ed814a4ed1f8a7b1d4ac7c3c4815728fe7 Mon Sep 17 00:00:00 2001 From: SteelT Date: Thu, 13 Jul 2023 01:02:15 -0400 Subject: [PATCH 206/478] Add CV_TrueFalse as possible value types for console variables This also adds support for using true/false as value aliases for On/Off, Yes/No or 1/0 --- src/command.c | 15 +++++++++------ src/command.h | 1 + src/lua_consolelib.c | 4 +++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/command.c b/src/command.c index a34d9694a..b03d2d8c1 100644 --- a/src/command.c +++ b/src/command.c @@ -76,6 +76,7 @@ CV_PossibleValue_t CV_OnOff[] = {{0, "Off"}, {1, "On"}, {0, NULL}}; CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}}; CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; +CV_PossibleValue_t CV_TrueFalse[] = {{0, "False"}, {1, "True"}, {0, NULL}}; // Filter consvars by EXECVERSION // First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20) @@ -863,9 +864,11 @@ static void COM_Help_f(void) { CONS_Printf(" Possible values:\n"); if (cvar->PossibleValue == CV_YesNo) - CONS_Printf(" Yes or No (On or Off, 1 or 0)\n"); + CONS_Printf(" Yes or No (On or Off, True or False, 1 or 0)\n"); else if (cvar->PossibleValue == CV_OnOff) - CONS_Printf(" On or Off (Yes or No, 1 or 0)\n"); + CONS_Printf(" On or Off (Yes or No, True or False, 1 or 0)\n"); + else if (cvar->PossibleValue == CV_TrueFalse) + CONS_Printf(" True or False (On or Off, Yes or No, 1 or 0)\n"); else if (cvar->PossibleValue == Color_cons_t) { for (i = 1; i < numskincolors; ++i) @@ -1016,7 +1019,7 @@ static void COM_Toggle_f(void) if (CV_Immutable(cvar)) return; - if (!(cvar->PossibleValue == CV_YesNo || cvar->PossibleValue == CV_OnOff)) + if (!(cvar->PossibleValue == CV_YesNo || cvar->PossibleValue == CV_OnOff || cvar->PossibleValue == CV_TrueFalse)) { CONS_Alert(CONS_NOTICE, M_GetText("%s is not a boolean value\n"), COM_Argv(1)); return; @@ -1507,12 +1510,12 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth) goto found; } // Not found ... but wait, there's hope! - if (var->PossibleValue == CV_OnOff || var->PossibleValue == CV_YesNo) + if (var->PossibleValue == CV_OnOff || var->PossibleValue == CV_YesNo || var->PossibleValue == CV_TrueFalse) { overrideval = -1; - if (!stricmp(valstr, "on") || !stricmp(valstr, "yes")) + if (!stricmp(valstr, "on") || !stricmp(valstr, "yes") || !stricmp(valstr, "true")) overrideval = 1; - else if (!stricmp(valstr, "off") || !stricmp(valstr, "no")) + else if (!stricmp(valstr, "off") || !stricmp(valstr, "no") || !stricmp(valstr, "false")) overrideval = 0; if (overrideval != -1) diff --git a/src/command.h b/src/command.h index 69d1890d3..619d8c1dc 100644 --- a/src/command.h +++ b/src/command.h @@ -177,6 +177,7 @@ extern CV_PossibleValue_t CV_OnOff[]; extern CV_PossibleValue_t CV_YesNo[]; extern CV_PossibleValue_t CV_Unsigned[]; extern CV_PossibleValue_t CV_Natural[]; +extern CV_PossibleValue_t CV_TrueFalse[]; // Filter consvars by version extern consvar_t cv_execversion; diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 1d15b3b14..9e5d1e2ee 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -357,7 +357,7 @@ static int lib_cvRegisterVar(lua_State *L) if (lua_islightuserdata(L, 4)) { CV_PossibleValue_t *pv = lua_touserdata(L, 4); - if (pv == CV_OnOff || pv == CV_YesNo || pv == CV_Unsigned || pv == CV_Natural) + if (pv == CV_OnOff || pv == CV_YesNo || pv == CV_Unsigned || pv == CV_Natural || pv == CV_TrueFalse) cvar->PossibleValue = pv; else FIELDERROR("PossibleValue", "CV_PossibleValue_t expected, got unrecognised pointer") @@ -652,6 +652,8 @@ int LUA_ConsoleLib(lua_State *L) lua_setglobal(L, "CV_Unsigned"); lua_pushlightuserdata(L, CV_Natural); lua_setglobal(L, "CV_Natural"); + lua_pushlightuserdata(L, CV_TrueFalse); + lua_setglobal(L, "CV_TrueFalse"); // Set global functions lua_pushvalue(L, LUA_GLOBALSINDEX); From 8755582901c70a8eff73084690d50da29d9c93cd Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 14 Jul 2023 02:33:33 -0700 Subject: [PATCH 207/478] Don't submit future ticcmds if they could overwrite a needed ticcmd --- src/d_clisrv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7d62272ff..210619164 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4567,7 +4567,8 @@ static void HandlePacketFromPlayer(SINT8 node) // If we've alredy received a ticcmd for this tic, just submit it for the next one. tic_t faketic = maketic; - if (!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED)) + if ((!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED)) + && (maketic - firstticstosend < BACKUPTICS)) faketic++; // Copy ticcmd From bfbbaf9f56a3622d9748251f09e8cd8d56ab3966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Fri, 14 Jul 2023 13:25:09 +0200 Subject: [PATCH 208/478] Make sure all allocations are properly aligned --- src/d_netfil.c | 2 +- src/lua_hudlib_drawlist.c | 6 +++--- src/r_fps.c | 17 ++++++----------- src/w_wad.c | 2 +- src/z_zone.c | 3 ++- src/z_zone.h | 8 ++++---- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/d_netfil.c b/src/d_netfil.c index e60af2c2c..3fef75681 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -498,7 +498,7 @@ INT32 CL_CheckFiles(void) CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files - for (j = mainwads; wadfiles[j]; j++) + for (j = mainwads; j < numwadfiles; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index f46f207c1..6f83094ac 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -103,7 +103,7 @@ huddrawlist_h LUA_HUD_CreateDrawList(void) { huddrawlist_h drawlist; - drawlist = (huddrawlist_h) Z_CallocAlign(sizeof(struct huddrawlist_s), PU_STATIC, NULL, 64); + drawlist = (huddrawlist_h) Z_Calloc(sizeof(struct huddrawlist_s), PU_STATIC, NULL); drawlist->items = NULL; drawlist->items_capacity = 0; drawlist->items_len = 0; @@ -160,7 +160,7 @@ static size_t AllocateDrawItem(huddrawlist_h list) { if (list->items_capacity == 0) list->items_capacity = 128; else list->items_capacity *= 2; - list->items = (drawitem_t *) Z_ReallocAlign(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL, 64); + list->items = (drawitem_t *) Z_Realloc(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL); } return list->items_len++; @@ -179,7 +179,7 @@ static const char *CopyString(huddrawlist_h list, const char* str) { if (list->strbuf_capacity == 0) list->strbuf_capacity = 256; else list->strbuf_capacity *= 2; - list->strbuf = (char*) Z_ReallocAlign(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL, 8); + list->strbuf = (char*) Z_Realloc(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL); } const char *result = (const char *) &list->strbuf[list->strbuf_len]; strncpy(&list->strbuf[list->strbuf_len], str, lenstr + 1); diff --git a/src/r_fps.c b/src/r_fps.c index 2d30c9f01..6166f0408 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -369,12 +369,11 @@ static void AddInterpolator(levelinterpolator_t* interpolator) levelinterpolators_size *= 2; } - levelinterpolators = Z_ReallocAlign( + levelinterpolators = Z_Realloc( (void*) levelinterpolators, sizeof(levelinterpolator_t*) * levelinterpolators_size, PU_LEVEL, - NULL, - sizeof(levelinterpolator_t*) * 8 + NULL ); } @@ -384,11 +383,8 @@ static void AddInterpolator(levelinterpolator_t* interpolator) static levelinterpolator_t *CreateInterpolator(levelinterpolator_type_e type, thinker_t *thinker) { - levelinterpolator_t *ret = (levelinterpolator_t*) Z_CallocAlign( - sizeof(levelinterpolator_t), - PU_LEVEL, - NULL, - sizeof(levelinterpolator_t) * 8 + levelinterpolator_t *ret = (levelinterpolator_t*) Z_Calloc( + sizeof(levelinterpolator_t), PU_LEVEL, NULL ); ret->type = type; @@ -703,12 +699,11 @@ void R_AddMobjInterpolator(mobj_t *mobj) interpolated_mobjs_capacity *= 2; } - interpolated_mobjs = Z_ReallocAlign( + interpolated_mobjs = Z_Realloc( interpolated_mobjs, sizeof(mobj_t *) * interpolated_mobjs_capacity, PU_LEVEL, - NULL, - 64 + NULL ); } diff --git a/src/w_wad.c b/src/w_wad.c index 456afef7b..b13dc8cc1 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -972,7 +972,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) // add the wadfile // CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps); - wadfiles = Z_Realloc(wadfiles, sizeof(wadfile_t) * (numwadfiles + 1), PU_STATIC, NULL); + wadfiles = Z_Realloc(wadfiles, sizeof(wadfile_t *) * (numwadfiles + 1), PU_STATIC, NULL); wadfiles[numwadfiles] = wadfile; numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded diff --git a/src/z_zone.c b/src/z_zone.c index 11c4bcb2c..d23c43b7b 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -287,7 +287,8 @@ void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) #endif { - size_t extrabytes = (1<= 0 && alignbits < (INT32)(sizeof(size_t) * 8)); + size_t extrabytes = ((size_t)1< Date: Fri, 14 Jul 2023 12:51:16 +0000 Subject: [PATCH 209/478] Draw hitboxes last in OpenGL --- src/hardware/hw_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e7550fd6e..bb05f2a6d 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4532,9 +4532,9 @@ static int CompareVisSprites(const void *p1, const void *p2) int linkdraw1; int linkdraw2; - // bbox doesn't need to be sorted + // draw bbox after everything else if (spr1->bbox || spr2->bbox) - return 0; + return (spr1->bbox - spr2->bbox); // check for precip first, because then sprX->mobj is actually a precipmobj_t and does not have flags2 or tracer linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer; From 34ce172a907778bc4c220dba02cd5ab3761ae761 Mon Sep 17 00:00:00 2001 From: spherallic Date: Fri, 14 Jul 2023 15:03:43 +0200 Subject: [PATCH 210/478] Allow toggling PF_NoDepthTest for OpenGL hitboxes --- src/d_netcmd.c | 1 + src/hardware/hw_main.c | 4 ++-- src/r_bbox.c | 3 ++- src/screen.h | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0f859a569..c3cd7daa8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -874,6 +874,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_fullscreen); CV_RegisterVar(&cv_renderview); CV_RegisterVar(&cv_renderhitboxinterpolation); + CV_RegisterVar(&cv_renderhitboxgldepth); CV_RegisterVar(&cv_renderhitbox); CV_RegisterVar(&cv_renderer); CV_RegisterVar(&cv_scr_depth); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bb05f2a6d..194d68c54 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4081,8 +4081,8 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis) v[017].y = v[020].y = v[021].y = v[025].y = v[026].y = v[027].y = vis->gzt; // top Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj)); - - HWR_ProcessPolygon(&Surf, v, 24, PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false); + + HWR_ProcessPolygon(&Surf, v, 24, (cv_renderhitboxgldepth.value ? 0 : PF_NoDepthTest)|PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false); } // -----------------+ diff --git a/src/r_bbox.c b/src/r_bbox.c index 7ed693fd0..59d0893c4 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -34,8 +34,9 @@ static CV_PossibleValue_t renderhitbox_cons_t[] = { {RENDERHITBOX_RINGS, "Rings"}, {0}}; -consvar_t cv_renderhitbox = CVAR_INIT ("renderhitbox", "Off", 0, renderhitbox_cons_t, NULL); +consvar_t cv_renderhitbox = CVAR_INIT ("renderhitbox", "Off", CV_CHEAT, renderhitbox_cons_t, NULL); consvar_t cv_renderhitboxinterpolation = CVAR_INIT ("renderhitbox_interpolation", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_renderhitboxgldepth = CVAR_INIT ("renderhitbox_gldepth", "Off", CV_SAVE, CV_OnOff, NULL); struct bbox_col { INT32 x; diff --git a/src/screen.h b/src/screen.h index b021a419d..9222805fb 100644 --- a/src/screen.h +++ b/src/screen.h @@ -199,7 +199,8 @@ extern CV_PossibleValue_t cv_renderer_t[]; extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders -extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_renderhitbox, cv_renderhitboxinterpolation, cv_fullscreen; +extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen; +extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth; // wait for page flipping to end or not extern consvar_t cv_vidwait; extern consvar_t cv_timescale; From 28849c31a8bed7854f1f28cdd37cb3fad0623287 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 15 Jul 2023 11:26:13 +0200 Subject: [PATCH 211/478] Update (U)ZB config with hitbox tweaks --- extras/conf/SRB2-22.cfg | 15 ++++++++++----- extras/conf/udb/Includes/SRB222_things.cfg | 21 ++++++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index dd5cdb46b..bcb6e6241 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -4367,7 +4367,6 @@ thingtypes { color = 14; // Yellow title = "Rings and Weapon Panels"; - width = 24; height = 24; flags8height = 24; flags8text = "[8] Float"; @@ -4377,7 +4376,6 @@ thingtypes { title = "Ring"; sprite = "RINGA0"; - width = 16; } 301 { @@ -4393,6 +4391,7 @@ thingtypes { title = "Infinity Ring"; sprite = "RNGIA0"; + width = 24; } 304 { @@ -4418,43 +4417,48 @@ thingtypes { title = "CTF Team Ring (Red)"; sprite = "internal:TRNGA0R"; - width = 16; } 309 { title = "CTF Team Ring (Blue)"; sprite = "internal:TRNGA0B"; - width = 16; } 330 { title = "Bounce Ring Panel"; sprite = "PIKBA0"; + width = 24; + height = 40; } 331 { title = "Rail Ring Panel"; sprite = "PIKRA0"; + width = 24; } 332 { title = "Automatic Ring Panel"; sprite = "PIKAA0"; + width = 24; } 333 { title = "Explosion Ring Panel"; sprite = "PIKEA0"; + width = 24; } 334 { title = "Scatter Ring Panel"; sprite = "PIKSA0"; + width = 24; } 335 { title = "Grenade Ring Panel"; sprite = "PIKGA0"; + width = 24; } } @@ -4463,7 +4467,7 @@ thingtypes color = 10; // Light Green title = "Other Collectibles"; width = 16; - height = 32; + height = 24; sort = 1; sprite = "CEMGA0"; @@ -4529,6 +4533,7 @@ thingtypes { title = "Emerald Hunt Location"; sprite = "SHRDA0"; + height = 32; flags8height = 24; flags8text = "[8] Float"; } diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index df08e3ac5..9eb227974 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -1185,7 +1185,7 @@ udmf { color = 14; // Yellow title = "Rings and Weapon Panels"; - width = 24; + width = 16; height = 24; sprite = "RINGA0"; @@ -1193,7 +1193,6 @@ udmf { title = "Ring"; sprite = "RINGA0"; - width = 16; arg0 { title = "Float?"; @@ -1227,6 +1226,7 @@ udmf { title = "Infinity Ring"; sprite = "RNGIA0"; + width = 24; arg0 { title = "Float?"; @@ -1282,7 +1282,6 @@ udmf { title = "CTF Team Ring (Red)"; sprite = "internal:TRNGA0R"; - width = 16; arg0 { title = "Float?"; @@ -1294,7 +1293,6 @@ udmf { title = "CTF Team Ring (Blue)"; sprite = "internal:TRNGA0B"; - width = 16; arg0 { title = "Float?"; @@ -1306,6 +1304,8 @@ udmf { title = "Bounce Ring Panel"; sprite = "PIKBA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1317,6 +1317,8 @@ udmf { title = "Rail Ring Panel"; sprite = "PIKRA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1328,6 +1330,8 @@ udmf { title = "Automatic Ring Panel"; sprite = "PIKAA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1339,6 +1343,8 @@ udmf { title = "Explosion Ring Panel"; sprite = "PIKEA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1350,6 +1356,8 @@ udmf { title = "Scatter Ring Panel"; sprite = "PIKSA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1361,6 +1369,8 @@ udmf { title = "Grenade Ring Panel"; sprite = "PIKGA0"; + width = 24; + height = 40; arg0 { title = "Float?"; @@ -1375,7 +1385,7 @@ udmf color = 10; // Light_Green title = "Other Collectibles"; width = 16; - height = 32; + height = 24; sort = 1; sprite = "CEMGA0"; @@ -1445,6 +1455,7 @@ udmf { title = "Emerald Hunt Location"; sprite = "SHRDA0"; + height = 32; arg0 { title = "Float?"; From e3824b9f1b759c319df85d7c710bf76a70573c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 15 Jul 2023 12:51:07 +0200 Subject: [PATCH 212/478] fixup! Fix inaccuracies in FPS counter --- src/screen.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/screen.c b/src/screen.c index f4982111d..b09ee81d2 100644 --- a/src/screen.c +++ b/src/screen.c @@ -462,10 +462,11 @@ double averageFPS = 0.0f; #define USE_FPS_SAMPLES #ifdef USE_FPS_SAMPLES -#define NUM_FPS_SAMPLES (32) // Number of samples to store +#define MAX_FRAME_TIME 0.05 +#define NUM_FPS_SAMPLES (16) // Number of samples to store -static double fps_samples[NUM_FPS_SAMPLES]; -static int fps_index; +static double total_frame_time = 0.0; +static int frame_index; #endif static boolean fps_init = false; @@ -474,7 +475,6 @@ static precise_t fps_enter = 0; void SCR_CalculateFPS(void) { precise_t fps_finish = 0; - int i; double frameElapsed = 0.0; @@ -489,13 +489,13 @@ void SCR_CalculateFPS(void) fps_enter = fps_finish; #ifdef USE_FPS_SAMPLES - fps_samples[fps_index] = frameElapsed / NUM_FPS_SAMPLES; - fps_index = (fps_index + 1) % NUM_FPS_SAMPLES; - - averageFPS = 0.0; - for (i = 0; i < NUM_FPS_SAMPLES; i++) - averageFPS += fps_samples[i]; - averageFPS = 1.0 / averageFPS; + total_frame_time += frameElapsed; + if (frame_index++ >= NUM_FPS_SAMPLES || total_frame_time >= MAX_FRAME_TIME) + { + averageFPS = 1.0 / (total_frame_time / frame_index); + total_frame_time = 0.0; + frame_index = 0; + } #else // Direct, unsampled counter. averageFPS = 1.0 / frameElapsed; From c64b242f012adbaa6d3e77070baebbf190313247 Mon Sep 17 00:00:00 2001 From: spherallic Date: Sat, 15 Jul 2023 13:07:55 +0200 Subject: [PATCH 213/478] Note to self: don't do busywork right after waking up from a short night of sleep --- extras/conf/SRB2-22.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index bcb6e6241..41ad99889 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -4435,30 +4435,35 @@ thingtypes title = "Rail Ring Panel"; sprite = "PIKRA0"; width = 24; + height = 40; } 332 { title = "Automatic Ring Panel"; sprite = "PIKAA0"; width = 24; + height = 40; } 333 { title = "Explosion Ring Panel"; sprite = "PIKEA0"; width = 24; + height = 40; } 334 { title = "Scatter Ring Panel"; sprite = "PIKSA0"; width = 24; + height = 40; } 335 { title = "Grenade Ring Panel"; sprite = "PIKGA0"; width = 24; + height = 40; } } From 9a386111e285af2e9eea0293ff484f0375fd61a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 16 Jul 2023 14:19:19 +0200 Subject: [PATCH 214/478] Fix crash when P_ZMovement calls from Lua removes the object --- src/lua_baselib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 25fa38769..0b0c93be4 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1078,7 +1078,8 @@ static int lib_pZMovement(lua_State *L) if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_ZMovement(actor)); - P_CheckPosition(actor, actor->x, actor->y); + if (!P_MobjWasRemoved(actor)) + P_CheckPosition(actor, actor->x, actor->y); P_SetTarget(&tmthing, ptmthing); return 1; } @@ -1106,7 +1107,8 @@ static int lib_pSceneryZMovement(lua_State *L) if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SceneryZMovement(actor)); - P_CheckPosition(actor, actor->x, actor->y); + if (!P_MobjWasRemoved(actor)) + P_CheckPosition(actor, actor->x, actor->y); P_SetTarget(&tmthing, ptmthing); return 1; } From c55b2f29434ab6959873f5e455040d17d65838ba Mon Sep 17 00:00:00 2001 From: SteelT Date: Sun, 16 Jul 2023 13:56:42 -0400 Subject: [PATCH 215/478] Print list of existing alias commands --- src/command.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/command.c b/src/command.c index b03d2d8c1..2cb3d821c 100644 --- a/src/command.c +++ b/src/command.c @@ -681,6 +681,17 @@ static void COM_ExecuteString(char *ptext) // SCRIPT COMMANDS // ========================================================================= +static void print_alias(void) +{ + cmdalias_t *a; + + CONS_Printf("\x82""Current alias commands:\n"); + for (a = com_alias; a; a = a->next) + { + CONS_Printf("%s : %s", a->name, a->value); + } +} + /** Creates a command name that replaces another command. */ static void COM_Alias_f(void) @@ -692,6 +703,7 @@ static void COM_Alias_f(void) if (COM_Argc() < 3) { CONS_Printf(M_GetText("alias : create a shortcut command that executes other command(s)\n")); + print_alias(); return; } From a90151570f3db849d93a41dd6812f2f42e9d1a67 Mon Sep 17 00:00:00 2001 From: SteelT Date: Sun, 16 Jul 2023 15:44:48 -0400 Subject: [PATCH 216/478] Replace the alias if an alias already exists Reduces wasting memory by having multiple aliases with the same name --- src/command.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/command.c b/src/command.c index 2cb3d821c..e1a43522d 100644 --- a/src/command.c +++ b/src/command.c @@ -692,11 +692,36 @@ static void print_alias(void) } } +static void add_alias(char *newname, char *newcmd) +{ + cmdalias_t *a; + + // Check for existing aliases first + for (a = com_alias; a; a = a->next) + { + if (!stricmp(newname, a->name)) + { + Z_Free(a->value); // Free old cmd + a->value = newcmd; + return; + } + } + + // No alias found, add it instead + a = ZZ_Alloc(sizeof *a); + a->next = com_alias; + com_alias = a; + + a->name = newname; + a->value = newcmd; +} + /** Creates a command name that replaces another command. */ static void COM_Alias_f(void) { - cmdalias_t *a; + char *name; + char *zcmd; char cmd[1024]; size_t i, c; @@ -707,11 +732,7 @@ static void COM_Alias_f(void) return; } - a = ZZ_Alloc(sizeof *a); - a->next = com_alias; - com_alias = a; - - a->name = Z_StrDup(COM_Argv(1)); + name = Z_StrDup(COM_Argv(1)); // copy the rest of the command line cmd[0] = 0; // start out with a null string @@ -723,8 +744,8 @@ static void COM_Alias_f(void) strcat(cmd, " "); } strcat(cmd, "\n"); - - a->value = Z_StrDup(cmd); + zcmd = Z_StrDup(cmd); + add_alias(name, zcmd); } /** Prints a line of text to the console. From 1ced8acc6a3c301f638753cf404a29cdfecb4d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 16 Jul 2023 23:25:22 +0200 Subject: [PATCH 217/478] Fix softlocking as Sonic & Tails when Player 2 has no name --- src/d_clisrv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 210619164..05af083bd 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1293,6 +1293,7 @@ static boolean CL_AskFileList(INT32 firstfile) static boolean CL_SendJoin(void) { UINT8 localplayers = 1; + char const *player2name; if (netgame) CONS_Printf(M_GetText("Sending join request...\n")); netbuffer->packettype = PT_CLIENTJOIN; @@ -1309,9 +1310,11 @@ static boolean CL_SendJoin(void) CleanupPlayerName(consoleplayer, cv_playername.zstring); if (splitscreen) CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ + // Avoid empty string on bots to avoid softlocking in singleplayer + player2name = botingame ? "a" : cv_playername2.zstring; strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); - strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); + strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); } From 80bf4d6c2d1cc413c41b0df69e2cf9334675377b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 12 Jun 2023 22:34:42 -0400 Subject: [PATCH 218/478] Port SRB2Kart join on intermission fix All gamestates besides GS_LEVEL are unsupported by the save game functions. This commit forces players joining during these gamestates into GS_WAITINGPLAYERS, which is a basic gamestate that just maintains the connection until we can enter the start of a new one. Also provides an extremely simple drawer for GS_WAITINGPLAYERS so the joining player knows what's going on. --- src/console.c | 2 +- src/d_clisrv.c | 2 ++ src/d_main.c | 7 +++++++ src/d_netcmd.c | 2 +- src/f_finale.c | 33 +++++++++++++++++++++++++++++++++ src/f_finale.h | 4 ++++ src/g_game.c | 9 ++++++--- src/p_saveg.c | 6 +++++- 8 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/console.c b/src/console.c index 6d273f620..119079464 100644 --- a/src/console.c +++ b/src/console.c @@ -1889,7 +1889,7 @@ void CON_Drawer(void) CON_DrawConsole(); else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_ENDING || gamestate == GS_CUTSCENE - || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) + || gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_WAITINGPLAYERS) CON_DrawHudlines(); Unlock_state(); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 210619164..9b3187cbb 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2600,6 +2600,8 @@ static void CL_ConnectToServer(void) } while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); + if (netgame) + F_StartWaitingPlayers(); DEBFILE(va("Synchronisation Finished\n")); displayplayer = consoleplayer; diff --git a/src/d_main.c b/src/d_main.c index 5861f9886..2db400258 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -458,6 +458,13 @@ static void D_Display(void) case GS_WAITINGPLAYERS: // The clientconnect drawer is independent... + if (netgame) + { + // I don't think HOM from nothing drawing is independent... + F_WaitingPlayersDrawer(); + HU_Erase(); + HU_Drawer(); + } case GS_DEDICATEDSERVER: case GS_NULL: break; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b23aaa5a0..2cdf70843 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2174,7 +2174,7 @@ static void Command_Pause(void) if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer))) { - if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) || (marathonmode && gamestate == GS_INTERMISSION)) + if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_WAITINGPLAYERS) || (marathonmode && gamestate == GS_INTERMISSION)) { CONS_Printf(M_GetText("You can't pause here.\n")); return; diff --git a/src/f_finale.c b/src/f_finale.c index 299a6a054..529244b5a 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -4660,3 +4660,36 @@ void F_TextPromptTicker(void) animtimer--; } } + +// ================ +// WAITINGPLAYERS +// ================ + +void F_StartWaitingPlayers(void) +{ + wipegamestate = GS_TITLESCREEN; // technically wiping from title screen + finalecount = 0; +} + +void F_WaitingPlayersTicker(void) +{ + if (paused) + return; + + finalecount++; + + // dumb hack, only start the music on the 1st tick so if you instantly go into the map you aren't hearing a tic of music + if (finalecount == 2) + S_ChangeMusicInternal("_CHSEL", true); +} + +void F_WaitingPlayersDrawer(void) +{ + const char *waittext1 = "You will join"; + const char *waittext2 = "next level..."; + + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + + V_DrawCreditString((160 - (V_CreditStringWidth(waittext1)>>1))<>1))< Date: Mon, 17 Jul 2023 00:44:34 -0400 Subject: [PATCH 219/478] Even more SRB2Kart netcode improvement ports - Prevent connection timeout during the waiting gamestate from the last commit. - Keep client connections alive during fades / other internal loops. - More consistently timeout clients when they reach the end of BACKUPTICS. - Dedicated servers will not run any game logic if no nodes are sending packets to it, to reduce CPU usage when there is no one interacting with your server. - Unlike SRB2Kart, the amount of time is configurable with the "dedicatedidletime" console variable. Setting this to 0 will disable this feature. - CL_SendClientCmd uses exact packet types instead of magic number offsets. --- src/d_clisrv.c | 274 +++++++++++++++++++++++++++++++++++++++---------- src/d_clisrv.h | 6 ++ src/d_net.c | 3 + src/d_netcmd.c | 1 + src/f_wipe.c | 2 + src/g_game.c | 1 + src/p_setup.c | 1 + 7 files changed, 235 insertions(+), 53 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 9b3187cbb..13dab4539 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -120,6 +120,8 @@ UINT8 hu_redownloadinggamestate = 0; // true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks boolean hu_stopped = false; +consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); + UINT8 adminpassmd5[16]; boolean adminpasswordset = false; @@ -4520,6 +4522,7 @@ static void HandlePacketFromPlayer(SINT8 node) netconsole = 0; else netconsole = nodetoplayer[node]; + #ifdef PARANOIA if (netconsole >= MAXPLAYERS) I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); @@ -4558,15 +4561,20 @@ static void HandlePacketFromPlayer(SINT8 node) // Update the nettics nettics[node] = realend; - // Don't do anything for packets of type NODEKEEPALIVE? - if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE - || netbuffer->packettype == PT_NODEKEEPALIVEMIS) + // This should probably still timeout though, as the node should always have a player 1 number + if (netconsole == -1) break; // As long as clients send valid ticcmds, the server can keep running, so reset the timeout /// \todo Use a separate cvar for that kind of timeout? freezetimeout[node] = I_GetTime() + connectiontimeout; + // Don't do anything for packets of type NODEKEEPALIVE? + // Sryder 2018/07/01: Update the freezetimeout still! + if (netbuffer->packettype == PT_NODEKEEPALIVE + || netbuffer->packettype == PT_NODEKEEPALIVEMIS) + break; + // If we've alredy received a ticcmd for this tic, just submit it for the next one. tic_t faketic = maketic; if ((!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED)) @@ -4630,6 +4638,21 @@ static void HandlePacketFromPlayer(SINT8 node) } } break; + case PT_BASICKEEPALIVE: + if (client) + break; + + // This should probably still timeout though, as the node should always have a player 1 number + if (netconsole == -1) + break; + + // If a client sends this it should mean they are done receiving the savegame + sendingsavegame[node] = false; + + // As long as clients send keep alives, the server can keep running, so reset the timeout + /// \todo Use a separate cvar for that kind of timeout? + freezetimeout[node] = I_GetTime() + connectiontimeout; + break; case PT_TEXTCMD2: // splitscreen special netconsole = nodetoplayer2[node]; /* FALLTHRU */ @@ -5056,39 +5079,66 @@ static INT16 Consistancy(void) return (INT16)(ret & 0xFFFF); } +// confusing, but this DOESN'T send PT_NODEKEEPALIVE, it sends PT_BASICKEEPALIVE +// used during wipes to tell the server that a node is still connected +static void CL_SendClientKeepAlive(void) +{ + netbuffer->packettype = PT_BASICKEEPALIVE; + + HSendPacket(servernode, false, 0, 0); +} + +static void SV_SendServerKeepAlive(void) +{ + INT32 n; + + for (n = 1; n < MAXNETNODES; n++) + { + if (nodeingame[n]) + { + netbuffer->packettype = PT_BASICKEEPALIVE; + HSendPacket(n, false, 0, 0); + } + } +} + // send the client packet to the server static void CL_SendClientCmd(void) { size_t packetsize = 0; + boolean mis = false; netbuffer->packettype = PT_CLIENTCMD; if (cl_packetmissed) - netbuffer->packettype++; + { + netbuffer->packettype = PT_CLIENTMIS; + mis = true; + } + netbuffer->u.clientpak.resendfrom = (UINT8)(neededtic & UINT8_MAX); netbuffer->u.clientpak.client_tic = (UINT8)(gametic & UINT8_MAX); if (gamestate == GS_WAITINGPLAYERS) { // Send PT_NODEKEEPALIVE packet - netbuffer->packettype += 4; + netbuffer->packettype = (mis ? PT_NODEKEEPALIVEMIS : PT_NODEKEEPALIVE); packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); HSendPacket(servernode, false, 0, packetsize); } else if (gamestate != GS_NULL && (addedtogame || dedicated)) { + packetsize = sizeof (clientcmd_pak); G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); // Send a special packet with 2 cmd for splitscreen if (splitscreen || botingame) { - netbuffer->packettype += 2; - G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); + netbuffer->packettype = (mis ? PT_CLIENT2MIS : PT_CLIENT2CMD); packetsize = sizeof (client2cmd_pak); + G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); } - else - packetsize = sizeof (clientcmd_pak); HSendPacket(servernode, false, 0, packetsize); } @@ -5099,7 +5149,7 @@ static void CL_SendClientCmd(void) if (localtextcmd[0]) { netbuffer->packettype = PT_TEXTCMD; - M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); + M_Memcpy(netbuffer->u.textcmd, localtextcmd, localtextcmd[0]+1); // All extra data have been sent if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... localtextcmd[0] = 0; @@ -5479,28 +5529,11 @@ static inline void PingUpdate(void) pingmeasurecount = 1; //Reset count } -void NetUpdate(void) +static tic_t gametime = 0; + +static void UpdatePingTable(void) { - static tic_t gametime = 0; - static tic_t resptime = 0; - tic_t nowtime; INT32 i; - INT32 realtics; - - nowtime = I_GetTime(); - realtics = nowtime - gametime; - - if (realtics <= 0) // nothing new to update - return; - if (realtics > 5) - { - if (server) - realtics = 1; - else - realtics = 5; - } - - gametime = nowtime; if (server) { @@ -5512,6 +5545,150 @@ void NetUpdate(void) realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); pingmeasurecount++; } +} + +// Handle timeouts to prevent definitive freezes from happenning +static void HandleNodeTimeouts(void) +{ + INT32 i; + + if (server) + { + for (i = 1; i < MAXNETNODES; i++) + if (nodeingame[i] && freezetimeout[i] < I_GetTime()) + Net_ConnectionTimeout(i); + + // In case the cvar value was lowered + if (joindelay) + joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE); + } +} + +// Keep the network alive while not advancing tics! +void NetKeepAlive(void) +{ + tic_t nowtime; + INT32 realtics; + + nowtime = I_GetTime(); + realtics = nowtime - gametime; + + // return if there's no time passed since the last call + if (realtics <= 0) // nothing new to update + return; + + UpdatePingTable(); + + GetPackets(); + +#ifdef MASTERSERVER + MasterClient_Ticker(); +#endif + + if (client) + { + // send keep alive + CL_SendClientKeepAlive(); + // No need to check for resynch because we aren't running any tics + } + else + { + SV_SendServerKeepAlive(); + } + + // No else because no tics are being run and we can't resynch during this + + Net_AckTicker(); + HandleNodeTimeouts(); + FileSendTicker(); +} + +void NetUpdate(void) +{ + static tic_t resptime = 0; + tic_t nowtime; + INT32 i; + INT32 realtics; + + nowtime = I_GetTime(); + realtics = nowtime - gametime; + + if (realtics <= 0) // nothing new to update + return; + + if (realtics > 5) + { + if (server) + realtics = 1; + else + realtics = 5; + } + + if (server && dedicated && gamestate == GS_LEVEL) + { + const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE; + static tic_t dedicatedidletimeprev = 0; + static tic_t dedicatedidle = 0; + + if (dedicatedidletime > 0) + { + for (i = 1; i < MAXNETNODES; ++i) + if (nodeingame[i]) + { + if (dedicatedidle >= dedicatedidletime) + { + CONS_Printf("DEDICATED: Awakening from idle (Node %d detected...)\n", i); + dedicatedidle = 0; + } + break; + } + + if (i == MAXNETNODES) + { + if (leveltime == 2) + { + // On next tick... + dedicatedidle = dedicatedidletime-1; + } + else if (dedicatedidle >= dedicatedidletime) + { + if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic+1, 0)) + { + CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n"); + dedicatedidle = 0; + } + else + { + realtics = 0; + } + } + else if ((dedicatedidle += realtics) >= dedicatedidletime) + { + const char *idlereason = "at round start"; + if (leveltime > 3) + idlereason = va("for %d seconds", dedicatedidle/TICRATE); + + CONS_Printf("DEDICATED: No nodes %s, idling...\n", idlereason); + realtics = 0; + dedicatedidle = dedicatedidletime; + } + } + } + else + { + if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev) + { + CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n"); + } + dedicatedidle = 0; + } + + dedicatedidletimeprev = dedicatedidletime; + } + + gametime = nowtime; + + UpdatePingTable(); if (client) maketic = neededtic; @@ -5543,25 +5720,26 @@ void NetUpdate(void) } else { - if (!demoplayback) + if (!demoplayback && realtics > 0) { INT32 counts; hu_redownloadinggamestate = false; - firstticstosend = gametic; - for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i] && nettics[i] < firstticstosend) - { - firstticstosend = nettics[i]; - - if (maketic + 1 >= nettics[i] + BACKUPTICS) - Net_ConnectionTimeout(i); - } - // Don't erase tics not acknowledged counts = realtics; + firstticstosend = gametic; + for (i = 0; i < MAXNETNODES; i++) + { + if (!nodeingame[i]) + continue; + if (nettics[i] < firstticstosend) + firstticstosend = nettics[i]; + if (maketic + counts >= nettics[i] + (BACKUPTICS - TICRATE)) + Net_ConnectionTimeout(i); + } + if (maketic + counts >= firstticstosend + BACKUPTICS) counts = firstticstosend+BACKUPTICS-maketic-1; @@ -5578,20 +5756,10 @@ void NetUpdate(void) } Net_AckTicker(); - - // Handle timeouts to prevent definitive freezes from happenning - if (server) - { - for (i = 1; i < MAXNETNODES; i++) - if (nodeingame[i] && freezetimeout[i] < I_GetTime()) - Net_ConnectionTimeout(i); - - // In case the cvar value was lowered - if (joindelay) - joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE); - } + HandleNodeTimeouts(); nowtime /= NEWTICRATERATIO; + if (nowtime > resptime) { resptime = nowtime; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 04a7b5ba2..49fb5fc1d 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -77,6 +77,8 @@ typedef enum PT_ASKLUAFILE, // Client telling the server they don't have the file PT_HASLUAFILE, // Client telling the server they have the file + PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called + // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL @@ -398,6 +400,7 @@ extern tic_t servermaxping; extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout; extern consvar_t cv_resynchattempts, cv_blamecfail; extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed; +extern consvar_t cv_dedicatedidletime; // Used in d_net, the only dependence tic_t ExpandTics(INT32 low, INT32 node); @@ -412,6 +415,9 @@ void SendKick(UINT8 playernum, UINT8 msg); // Create any new ticcmds and broadcast to other players. void NetUpdate(void); +// Maintain connections to nodes without timing them all out. +void NetKeepAlive(void); + void SV_StartSinglePlayerServer(void); boolean SV_SpawnServer(void); void SV_StopServer(void); diff --git a/src/d_net.c b/src/d_net.c index 768c9ac7e..6d8c72942 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -869,6 +869,9 @@ static void DebugPrintpacket(const char *header) (UINT32)ExpandTics(netbuffer->u.clientpak.client_tic, doomcom->remotenode), (UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom, doomcom->remotenode)); break; + case PT_BASICKEEPALIVE: + fprintf(debugfile, " wipetime\n"); + break; case PT_TEXTCMD: case PT_TEXTCMD2: fprintf(debugfile, " length %d\n ", netbuffer->u.textcmd[0]); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 2cdf70843..8fd207037 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -599,6 +599,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_joinnextround); CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_blamecfail); + CV_RegisterVar(&cv_dedicatedidletime); #endif COM_AddCommand("ping", Command_Ping_f, COM_LUA); diff --git a/src/f_wipe.c b/src/f_wipe.c index 6014fb7f9..4bcfb029b 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -614,6 +614,8 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) if (moviemode) M_SaveFrame(); + + NetKeepAlive(); // Update the network so we don't cause timeouts } WipeInAction = false; diff --git a/src/g_game.c b/src/g_game.c index bcfe69105..eea804c83 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1915,6 +1915,7 @@ void G_PreLevelTitleCard(void) ST_runTitleCard(); ST_preLevelTitleCardDrawer(); I_FinishUpdate(); // page flip or blit buffer + NetKeepAlive(); // Prevent timeouts if (moviemode) M_SaveFrame(); diff --git a/src/p_setup.c b/src/p_setup.c index a10326986..e4a46c0f4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7436,6 +7436,7 @@ static void P_RunSpecialStageWipe(void) lastwipetic = nowtime; if (moviemode) // make sure we save frames for the white hold too M_SaveFrame(); + NetKeepAlive(); // Prevent timeout } } From ff56d46827e9ff9ba71222248eda3483ac106cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Mon, 17 Jul 2023 16:41:22 +0200 Subject: [PATCH 220/478] fixup! Fix softlocking as Sonic & Tails when Player 2 has no name --- src/d_clisrv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 05af083bd..9a8aedefa 100755 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1311,7 +1311,10 @@ static boolean CL_SendJoin(void) if (splitscreen) CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ // Avoid empty string on bots to avoid softlocking in singleplayer - player2name = botingame ? "a" : cv_playername2.zstring; + if (botingame) + player2name = strcmp(cv_playername.zstring, "Tails") == 0 ? "Tail" : "Tails"; + else + player2name = cv_playername2.zstring; strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME); From 8cf65e83018e02e4bcdea186082a9fc82f23e50c Mon Sep 17 00:00:00 2001 From: katsy <205-katsy@users.noreply.git.do.srb2.org> Date: Wed, 19 Jul 2023 19:43:15 +0000 Subject: [PATCH 221/478] Fix inconsistency with title card patch coloring (color the title card patch used in the credits to skin) --- src/f_finale.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 8dd03d44f..2a551da7e 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1301,14 +1301,23 @@ void F_CreditDrawer(void) UINT16 i; INT16 zagpos = (timetonext - finalecount - animtimer) % 32; fixed_t y = (80<>1); + UINT8 colornum; + const UINT8 *colormap; + + if (players[consoleplayer].skincolor) + colornum = players[consoleplayer].skincolor; + else + colornum = cv_playercolor.value; + + colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Zig Zagz - V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); - V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); - V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); - V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY)); + V_DrawFixedPatch(-16*FRACUNIT, zagpos< Date: Wed, 19 Jul 2023 23:17:21 +0200 Subject: [PATCH 222/478] Clean up and simplify zone memory allocation --- src/z_zone.c | 225 +++++++++------------------------------------------ 1 file changed, 39 insertions(+), 186 deletions(-) diff --git a/src/z_zone.c b/src/z_zone.c index d23c43b7b..5750f8ae0 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -51,27 +51,11 @@ static boolean Z_calloc = false; //#define ZDEBUG2 #endif -struct memblock_s; - -typedef struct -{ - struct memblock_s *block; // Describing this memory - UINT32 id; // Should be ZONEID -} ATTRPACK memhdr_t; - -// Some code might want aligned memory. Assume it wants memory n bytes -// aligned -- then we allocate n-1 extra bytes and return a pointer to -// the first byte aligned as requested. -// Thus, "real" is the pointer we get from malloc() and will free() -// later, but "hdr" is where the memhdr_t starts. -// For non-aligned allocations they will be the same. typedef struct memblock_s { - void *real; - memhdr_t *hdr; - void **user; INT32 tag; // purgelevel + UINT32 id; // Should be ZONEID size_t size; // including the header and blocks size_t realsize; // size of real data only @@ -82,7 +66,10 @@ typedef struct memblock_s #endif struct memblock_s *next, *prev; -} ATTRPACK memblock_t; +} memblock_t; + +#define MEMORY(x) (void *)((uintptr_t)(x) + sizeof(memblock_t)) +#define MEMBLOCK(x) (memblock_t *)((uintptr_t)(x) - sizeof(memblock_t)) // both the head and tail of the zone memory block list static memblock_t head; @@ -128,64 +115,6 @@ void Z_Init(void) // Zone memory allocation // ---------------------- -/** Returns the corresponding memblock_t for a given memory block. - * - * \param ptr A pointer to allocated memory, - * assumed to have been allocated with Z_Malloc/Z_Calloc. - * \param func A string containing the name of the function that called this, - * to be printed if the function I_Errors - * \return A pointer to the memblock_t for the given memory. - * \sa Z_Free, Z_ReallocAlign - */ -#ifdef ZDEBUG -#define Ptr2Memblock(s, f) Ptr2Memblock2(s, f, __FILE__, __LINE__) -static memblock_t *Ptr2Memblock2(void *ptr, const char* func, const char *file, INT32 line) -#else -static memblock_t *Ptr2Memblock(void *ptr, const char* func) -#endif -{ - memhdr_t *hdr; - memblock_t *block; - - if (ptr == NULL) - return NULL; - -#ifdef ZDEBUG2 - CONS_Printf("%s %s:%d\n", func, file, line); -#endif - - hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr); - -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif - -#ifdef VALGRIND_MEMPOOL_EXISTS - if (!VALGRIND_MEMPOOL_EXISTS(hdr->block)) - { -#ifdef ZDEBUG - I_Error("%s: bad memblock from %s:%d", func, file, line); -#else - I_Error("%s: bad memblock", func); -#endif - } -#endif - if (hdr->id != ZONEID) - { -#ifdef ZDEBUG - I_Error("%s: wrong id from %s:%d", func, file, line); -#else - I_Error("%s: wrong id", func); -#endif - } - block = hdr->block; -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); -#endif - return block; - -} - /** Frees allocated memory. * * \param ptr A pointer to allocated memory, @@ -207,10 +136,14 @@ void Z_Free(void *ptr) CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line); #endif + block = MEMBLOCK(ptr); +#ifdef PARANOIA + if (block->id != ZONEID) #ifdef ZDEBUG - block = Ptr2Memblock2(ptr, "Z_Free", file, line); + I_Error("Z_Free at %s:%d: wrong id", file, line); #else - block = Ptr2Memblock(ptr, "Z_Free"); + I_Error("Z_Free: wrong id"); +#endif #endif #ifdef ZDEBUG @@ -229,8 +162,6 @@ void Z_Free(void *ptr) if (block->user != NULL) *block->user = NULL; - // Free the memory and get rid of the block. - free(block->real); #ifdef VALGRIND_DESTROY_MEMPOOL VALGRIND_DESTROY_MEMPOOL(block); #endif @@ -287,35 +218,17 @@ void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) #endif { - I_Assert(alignbits >= 0 && alignbits < (INT32)(sizeof(size_t) * 8)); - size_t extrabytes = ((size_t)1<next->prev = block; - block->real = ptr; - block->hdr = hdr; block->tag = tag; block->user = NULL; #ifdef ZDEBUG block->ownerline = line; block->ownerfile = file; #endif - block->size = blocksize; + block->size = sizeof (memblock_t) + size; block->realsize = size; #ifdef VALGRIND_CREATE_MEMPOOL - VALGRIND_CREATE_MEMPOOL(block, padsize, Z_calloc); + VALGRIND_CREATE_MEMPOOL(block, size, Z_calloc); #endif -//#ifdef VALGRIND_MEMPOOL_ALLOC -// VALGRIND_MEMPOOL_ALLOC(block, hdr, size + sizeof *hdr); -//#endif - hdr->id = ZONEID; - hdr->block = block; - -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); -#endif + block->id = ZONEID; if (user != NULL) { block->user = user; - *(void **)user = given; + *(void **)user = ptr; } else if (tag >= PU_PURGELEVEL) I_Error("Z_Malloc: attempted to allocate purgable block " "(size %s) with no user", sizeu1(size)); - return given; + return ptr; } /** The Z_CallocAlign function. @@ -437,10 +340,14 @@ void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignb #endif } + block = MEMBLOCK(ptr); +#ifdef PARANOIA + if (block->id != ZONEID) #ifdef ZDEBUG - block = Ptr2Memblock2(ptr, "Z_Realloc", file, line); + I_Error("Z_ReallocAlign at %s:%d: wrong id", file, line); #else - block = Ptr2Memblock(ptr, "Z_Realloc"); + I_Error("Z_ReallocAlign: wrong id"); +#endif #endif if (block == NULL) @@ -491,9 +398,8 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) for (block = head.next; block != &head; block = next) { next = block->next; // get link before freeing - if (block->tag >= lowtag && block->tag <= hightag) - Z_Free((UINT8 *)block->hdr + sizeof *block->hdr); + Z_Free(MEMORY(block)); } } @@ -516,7 +422,7 @@ void Z_IterateTags(INT32 lowtag, INT32 hightag, boolean (*iterfunc)(void *)) if (block->tag >= lowtag && block->tag <= hightag) { - void *mem = (UINT8 *)block->hdr + sizeof *block->hdr; + void *mem = MEMORY(block); boolean free = iterfunc(mem); if (free) Z_Free(mem); @@ -561,15 +467,13 @@ void Z_CheckMemCleanup(void) void Z_CheckHeap(INT32 i) { memblock_t *block; - memhdr_t *hdr; UINT32 blocknumon = 0; void *given; for (block = head.next; block != &head; block = block->next) { blocknumon++; - hdr = block->hdr; - given = (UINT8 *)hdr + sizeof *hdr; + given = MEMORY(block); #ifdef ZDEBUG2 CONS_Debug(DBG_MEMORY, "block %u owned by %s:%d\n", blocknumon, block->ownerfile, block->ownerline); @@ -585,7 +489,7 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } #endif if (block->user != NULL && *(block->user) != given) @@ -598,7 +502,7 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } if (block->next->prev != block) { @@ -610,7 +514,7 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } if (block->prev->next != block) { @@ -622,25 +526,9 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif - if (hdr->block != block) - { - I_Error("Z_CheckHeap %d: block %u" -#ifdef ZDEBUG - "(owned by %s:%d)" -#endif - " doesn't have linkback from allocated memory", - i, blocknumon -#ifdef ZDEBUG - , block->ownerfile, block->ownerline -#endif - ); - } - if (hdr->id != ZONEID) + if (block->id != ZONEID) { I_Error("Z_CheckHeap %d: block %u" #ifdef ZDEBUG @@ -650,11 +538,8 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); -#endif } } @@ -676,35 +561,14 @@ void Z_ChangeTag(void *ptr, INT32 tag) #endif { memblock_t *block; - memhdr_t *hdr; if (ptr == NULL) return; - hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr); + block = MEMBLOCK(ptr); -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif - -#ifdef VALGRIND_MEMPOOL_EXISTS - if (!VALGRIND_MEMPOOL_EXISTS(hdr->block)) - { #ifdef PARANOIA - I_Error("Z_CT at %s:%d: bad memblock", file, line); -#else - I_Error("Z_CT: bad memblock"); -#endif - } -#endif -#ifdef PARANOIA - if (hdr->id != ZONEID) I_Error("Z_CT at %s:%d: wrong id", file, line); -#endif - - block = hdr->block; - -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); + if (block->id != ZONEID) I_Error("Z_ChangeTag at %s:%d: wrong id", file, line); #endif if (tag >= PU_PURGELEVEL && block->user == NULL) @@ -728,25 +592,14 @@ void Z_SetUser(void *ptr, void **newuser) #endif { memblock_t *block; - memhdr_t *hdr; if (ptr == NULL) return; - hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr); - -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif + block = MEMBLOCK(ptr); #ifdef PARANOIA - if (hdr->id != ZONEID) I_Error("Z_CT at %s:%d: wrong id", file, line); -#endif - - block = hdr->block; - -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); + if (block->id != ZONEID) I_Error("Z_SetUser at %s:%d: wrong id", file, line); #endif if (block->tag >= PU_PURGELEVEL && newuser == NULL) From 36e6a2001a8a3f5ea3faf9add65a84ffc3ac08b9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 20 Jul 2023 01:43:10 -0400 Subject: [PATCH 223/478] Paired down OS Lua library Pretty much removed everything except for time operations. File operations steps on the toes of the IO library, and the others were useless or invasive. The only one I wasn't sure about was `os.tmpname()`, but I think that's something that could be implemented for IO library instead if necessary. The main reason I want this is because os.time provides an OK way to initially seed RNG on game first boot. But it would also be cute to let Lua modders be able to re-implement Christmas mode / day&night cycles themselves :p --- src/blua/Sourcefile | 1 + src/blua/linit.c | 1 + src/blua/loslib.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ src/blua/lualib.h | 3 + 4 files changed, 172 insertions(+) create mode 100644 src/blua/loslib.c diff --git a/src/blua/Sourcefile b/src/blua/Sourcefile index f99c89c8d..dae943109 100644 --- a/src/blua/Sourcefile +++ b/src/blua/Sourcefile @@ -23,3 +23,4 @@ lstring.c ltable.c ltm.c lvm.c +loslib.c diff --git a/src/blua/linit.c b/src/blua/linit.c index d17390b20..dcf05d9f2 100644 --- a/src/blua/linit.c +++ b/src/blua/linit.c @@ -18,6 +18,7 @@ static const luaL_Reg lualibs[] = { {"", luaopen_base}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, {NULL, NULL} }; diff --git a/src/blua/loslib.c b/src/blua/loslib.c new file mode 100644 index 000000000..ba2e1e384 --- /dev/null +++ b/src/blua/loslib.c @@ -0,0 +1,167 @@ +/* +** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define loslib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + lua_setfield(L, -2, key); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_getfield(L, -1, key); + res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_getfield(L, -1, key); + if (lua_isnumber(L, -1)) + res = (int)lua_tointeger(L, -1); + else { + if (d < 0) + return luaL_error(L, "field " LUA_QS " missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int os_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + struct tm *stm; + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char cc[3]; + luaL_Buffer b; + cc[0] = '%'; cc[2] = '\0'; + luaL_buffinit(L, &b); + for (; *s; s++) { + if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ + luaL_addchar(&b, *s); + else { + size_t reslen; + char buff[200]; /* should be big enough for any conversion result */ + cc[1] = *(++s); + reslen = strftime(buff, sizeof(buff), cc, stm); + luaL_addlstring(&b, buff, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -1); + ts.tm_mon = getfield(L, "month", -1) - 1; + ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + } + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, (lua_Number)t); + return 1; +} + + +static int os_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"time", os_time}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_os (lua_State *L) { + luaL_register(L, LUA_OSLIBNAME, syslib); + return 1; +} diff --git a/src/blua/lualib.h b/src/blua/lualib.h index 4ea97edf3..7127e4d77 100644 --- a/src/blua/lualib.h +++ b/src/blua/lualib.h @@ -24,6 +24,9 @@ LUALIB_API int (luaopen_table) (lua_State *L); #define LUA_IOLIBNAME "io" LUALIB_API int (luaopen_io) (lua_State *L); +#define LUA_OSLIBNAME "os" +LUALIB_API int (luaopen_os) (lua_State *L); + #define LUA_STRLIBNAME "string" LUALIB_API int (luaopen_string) (lua_State *L); From dee24896205c4ed9ae18662bdf8c4aa4a9865770 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Jul 2023 17:54:47 +0100 Subject: [PATCH 224/478] P_GetNodeType: Do not dereference invalid pointer for **nodedata parameter --- src/p_setup.c | 52 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index a10326986..3c83c6c91 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3205,10 +3205,17 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) nodetype_t nodetype = NT_UNSUPPORTED; char signature[4 + 1]; + *nodedata = NULL; + if (udmf) { - *nodedata = vres_Find(virt, "ZNODES")->data; - supported[NT_XGLN] = supported[NT_XGL3] = true; + virtlump_t *virtznodes = vres_Find(virt, "ZNODES"); + + if (virtznodes && virtznodes->size) + { + *nodedata = virtznodes->data; + supported[NT_XGLN] = supported[NT_XGL3] = true; + } } else { @@ -3217,24 +3224,39 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) if (virtsegs && virtsegs->size) { - *nodedata = vres_Find(virt, "NODES")->data; - return NT_DOOM; // Traditional map format BSP tree. - } - - virtssectors = vres_Find(virt, "SSECTORS"); - - if (virtssectors && virtssectors->size) - { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. - *nodedata = virtssectors->data; - supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; + virtlump_t *virtnodes = vres_Find(virt, "NODES"); + if (virtnodes && virtnodes->size) + { + *nodedata = virtnodes->data; + return NT_DOOM; // Traditional map format BSP tree. + } } else - { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. - *nodedata = vres_Find(virt, "NODES")->data; - supported[NT_XNOD] = supported[NT_ZNOD] = true; + { + virtssectors = vres_Find(virt, "SSECTORS"); + + if (virtssectors && virtssectors->size) + { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. + *nodedata = virtssectors->data; + supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; + } + else + { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. + virtlump_t *virtnodes = vres_Find(virt, "NODES"); + if (virtnodes && virtnodes->size) + { + *nodedata = virtnodes->data; + supported[NT_XNOD] = supported[NT_ZNOD] = true; + } + } } } + if (*nodedata == NULL) + { + I_Error("Level has no nodes (does your map have at least 2 sectors?)"); + } + M_Memcpy(signature, *nodedata, 4); signature[4] = '\0'; (*nodedata) += 4; From 66dd952fdd854800832aa563047c17e813a36c71 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Jul 2023 19:42:21 +0100 Subject: [PATCH 225/478] Tidier conversion of string properties on linedefs to UDMF Previously, many concatenated texture field strings were turned to text, then had that string run through get_number, then had it converted back into a string to become a stringarg. Now, the concatenated string is copied directly to the relevant stringarg, with no intermediary steps. This fixes an issue where a map with object or state properties would have "context drift" - breaking when the object or state list changed, due to differently ordered freeslots, or new hardcoded objects. Affected types: - doomednum 1110/Action 9 (Custom Mace/Chain) - doomednum 700 and those immediately following (Ambient Sound) - Action 4 and 414 (dash pad, play sound effect) - Action 14 (bustable block parameters) - Action 434 (Award Power) - doomednum 757/Action 15 (fan particle generator) - doomednum 1202 (bumpable hazard rock/apple spawner) - This one has undefined behaviour in the binary map format which was not previously forbidden. This undefined behaviour is EXTREMELY vulnerable to context drift, and so it's simply not worth creating a system to write numerical values into object types - we write an explicit name only for the intended range, and otherwise report the threat of context drift when converting. In addition, to reduce duplicated zone memory, (sidedef_t).text and (linedef_t).text have been removed from all but the Lua API. In Lua, in binary maps, they point to the host line's stringargs - the line's text and a frontside's text will return stringargs[0], while a backside's text will return stringargs[1]. I've done my best to match the previous API as closely possible, to the point of reporting false nils if the line didn't previously have text available. However, there are four linedef Actions for which the sidedef text will be different between builds containing and not containing this commit - 331, 332, 333 (the Character-specific linedef executors), and 443 (Call Lua Script), and only if the text is long enough to go over two lines. Given that both halves would be incomplete nonsense in this case, I'm willing to wager this minor point of discrepancy is not a breaking issue. --- src/lua_maplib.c | 35 +++++- src/p_setup.c | 322 ++++++++++++++++++++++++++--------------------- src/r_defs.h | 3 - 3 files changed, 208 insertions(+), 152 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index f73b3c7d2..904b4316b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1032,8 +1032,24 @@ static int line_get(lua_State *L) LUA_PushUserdata(L, line->polyobj, META_POLYOBJ); return 1; case line_text: - lua_pushstring(L, line->text); - return 1; + { + if (udmf) + { + LUA_Deprecated(L, "(linedef_t).text", "(linedef_t).stringargs"); + lua_pushnil(L); + return 1; + } + + if (line->special == 331 || line->special == 443) + { + // See P_ProcessLinedefsAfterSidedefs, P_ConvertBinaryLinedefTypes + lua_pushstring(L, line->stringargs[0]); + } + else + lua_pushnil(L); + + return 1; + } case line_callcount: lua_pushinteger(L, line->callcount); return 1; @@ -1149,8 +1165,19 @@ static int side_get(lua_State *L) lua_pushinteger(L, side->repeatcnt); return 1; case side_text: - lua_pushstring(L, side->text); - return 1; + { + if (udmf) + { + LUA_Deprecated(L, "(sidedef_t).text", "(sidedef_t).line.stringargs"); + lua_pushnil(L); + return 1; + } + + boolean isfrontside = side->line->sidenum[0] == side-sides; + + lua_pushstring(L, side->line->stringargs[isfrontside ? 0 : 1]); + return 1; + } } return 0; } diff --git a/src/p_setup.c b/src/p_setup.c index 3c83c6c91..27ddb0775 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1103,7 +1103,6 @@ static void P_InitializeLinedef(line_t *ld) ld->validcount = 0; ld->polyobj = NULL; - ld->text = NULL; ld->callcount = 0; // cph 2006/09/30 - fix sidedef errors right away. @@ -1207,10 +1206,108 @@ static void P_InitializeSidedef(side_t *sd) sd->special = sd->line->special; } - sd->text = NULL; sd->colormap_data = NULL; } +static boolean contextdrift = false; + +// In Ring Racers, this is just the reference implementation. +// But in SRB2, backwards compatibility is a design goal!? +// So we let the map function on load, but report that there's +// an issue which could prevent saving it as a UDMF map. +// +// ... "context drift" is a term I learned from the story "Lena", +// styled after a wikipedia article on a man whose brain scan +// spawns an industry of digital brain emulation. It is a term +// to describe that the understanding of the world MMAcevedo has +// is rooted in a specific moment and time and will lose relevance +// as societal norms, languages, and events change and are changed. +// It is on the real wikipedia, but under the name "concept drift". +// I am connecting the idea of the rooted-in-time brainstate with +// the numerical evaluation of get_number(), the ground truth +// CONTEXT for all these silly integers, that will trip up future +// builds of SRB2 that have modified states and object lists. +// Golden statues rotating in place of carousel rides is perhaps +// not quite what qntm meant, but is a TEXTMAP, a human-readable +// document for imparting a sense of place made/read by machines, +// not its own language providing a vulnerable context? +// ~toast 200723, see https://qntm.org/mmacevedo +// +static void P_WriteConstant(INT32 constant, char **target, const char *desc, UINT32 id) +{ + char buffer[12]; + size_t len; + + CONS_Alert( + CONS_WARNING, M_GetText( + "P_WriteConstant has been called for %s %d, " + "this level is vulnerable to context drift " + "if -writetextmap is used.\n"), + desc, id + ); + + contextdrift = true; + + sprintf(buffer, "%d", constant); + len = strlen(buffer) + 1; + *target = Z_Malloc(len, PU_LEVEL, NULL); + M_Memcpy(*target, buffer, len); +} + +static void P_WriteDuplicateText(const char *text, char **target) +{ + if (text == NULL || text[0] == '\0') + return; + + size_t len = strlen(text) + 1; + *target = Z_Malloc(len, PU_LEVEL, NULL); + M_Memcpy(*target, text, len); +} + +static void P_WriteSkincolor(INT32 constant, char **target) +{ + if (constant <= SKINCOLOR_NONE + || constant >= (INT32)numskincolors) + return; + + P_WriteDuplicateText( + va("SKINCOLOR_%s", skincolors[constant].name), + target + ); +} + +static void P_WriteSfx(INT32 constant, char **target) +{ + if (constant <= sfx_None + || constant >= (INT32)sfxfree) + return; + + P_WriteDuplicateText( + va("sfx_%s", S_sfx[constant].name), + target + ); +} + +static void P_WriteTics(INT32 tics, char **target) +{ + if (!tics) + return; + + INT32 seconds = (tics / TICRATE); + tics %= TICRATE; + + const char *text; + + if (tics && !seconds) + text = va("%d", tics); + else if (seconds && !tics) + text = va("(%d*TICRATE)", seconds); + else + text = va("(%d*TICRATE)%s%d", seconds, (tics > 0) ? "+" : "", tics); + + P_WriteDuplicateText(text, target); +} + static void P_LoadSidedefs(UINT8 *data) { mapsidedef_t *msd = (mapsidedef_t*)data; @@ -1259,9 +1356,13 @@ static void P_LoadSidedefs(UINT8 *data) case 413: // Change music { + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + + if (!isfrontside) + break; + char process[8+1]; - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') { M_Memcpy(process,msd->bottomtexture,8); @@ -1276,48 +1377,39 @@ static void P_LoadSidedefs(UINT8 *data) sd->midtexture = get_number(process); } - sd->text = Z_Malloc(7, PU_LEVEL, NULL); - if (isfrontside && !(msd->toptexture[0] == '-' && msd->toptexture[1] == '\0')) + if (msd->toptexture[0] != '-' && msd->toptexture[1] != '\0') { + sd->line->stringargs[0] = Z_Malloc(7, PU_LEVEL, NULL); + M_Memcpy(process,msd->toptexture,8); process[8] = '\0'; // If they type in O_ or D_ and their music name, just shrug, // then copy the rest instead. if ((process[0] == 'O' || process[0] == 'D') && process[7]) - M_Memcpy(sd->text, process+2, 6); + M_Memcpy(sd->line->stringargs[0], process+2, 6); else // Assume it's a proper music name. - M_Memcpy(sd->text, process, 6); - sd->text[6] = 0; + M_Memcpy(sd->line->stringargs[0], process, 6); + sd->line->stringargs[0][6] = '\0'; } - else - sd->text[0] = 0; + break; } case 4: // Speed pad parameters - { - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') - { - char process[8+1]; - M_Memcpy(process,msd->toptexture,8); - process[8] = '\0'; - sd->toptexture = get_number(process); - } - break; - } - case 414: // Play SFX { sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + + if (!isfrontside) + break; + if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') { char process[8 + 1]; M_Memcpy(process, msd->toptexture, 8); process[8] = '\0'; - sd->text = Z_Malloc(strlen(process) + 1, PU_LEVEL, NULL); - M_Memcpy(sd->text, process, strlen(process) + 1); + P_WriteDuplicateText(process, &sd->line->stringargs[0]); } break; } @@ -1326,21 +1418,13 @@ static void P_LoadSidedefs(UINT8 *data) case 14: // Bustable block parameters case 15: // Fan particle spawner parameters { - char process[8*3+1]; - memset(process,0,8*3+1); - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - if (msd->toptexture[0] == '-' && msd->toptexture[1] == '\0') + if (msd->toptexture[7] == '\0' && strcasecmp(msd->toptexture, "MT_NULL") == 0) + { + // Don't bulk the conversion with irrelevant types break; - else - M_Memcpy(process,msd->toptexture,8); - if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') - M_Memcpy(process+strlen(process), msd->midtexture, 8); - if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') - M_Memcpy(process+strlen(process), msd->bottomtexture, 8); - sd->toptexture = get_number(process); - break; + } } - + // FALLTHRU case 331: // Trigger linedef executor: Skin - Continuous case 332: // Trigger linedef executor: Skin - Each time case 333: // Trigger linedef executor: Skin - Once @@ -1366,8 +1450,11 @@ static void P_LoadSidedefs(UINT8 *data) M_Memcpy(process+strlen(process), msd->midtexture, 8); if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') M_Memcpy(process+strlen(process), msd->bottomtexture, 8); - sd->text = Z_Malloc(strlen(process)+1, PU_LEVEL, NULL); - M_Memcpy(sd->text, process, strlen(process)+1); + + P_WriteDuplicateText( + process, + &sd->line->stringargs[(isfrontside) ? 0 : 1] + ); break; } @@ -2716,6 +2803,15 @@ static void P_WriteTextmap(void) Z_Free(wlines); Z_Free(wsides); Z_Free(specialthings); + + if (contextdrift) + { + CONS_Alert( + CONS_WARNING, M_GetText( + "Some elements of this level are vulnerable to context drift." + "Please check the console log for more information.\n") + ); + } } /** Loads the textmap data, after obtaining the elements count and allocating their respective space. @@ -2909,15 +3005,20 @@ static void P_ProcessLinedefsAfterSidedefs(void) case 332: // Trigger linedef executor: Skin - Each time case 333: // Trigger linedef executor: Skin - Once case 443: // Calls a named Lua function - if (sides[ld->sidenum[0]].text) + if (ld->stringargs[0] && ld->stringargs[1]) { - size_t len = strlen(sides[ld->sidenum[0]].text) + 1; - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - len += strlen(sides[ld->sidenum[1]].text); - ld->text = Z_Malloc(len, PU_LEVEL, NULL); - M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text) + 1); - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - M_Memcpy(ld->text + strlen(ld->text) + 1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text) + 1); + size_t len[2]; + len[0] = strlen(ld->stringargs[0]); + len[1] = strlen(ld->stringargs[1]); + + if (len[1]) + { + ld->stringargs[0] = Z_Realloc(ld->stringargs[0], len[0] + len[1] + 1, PU_LEVEL, NULL); + M_Memcpy(ld->stringargs[0] + len[0] + 1, ld->stringargs[1], len[1] + 1); + } + + Z_Free(ld->stringargs[1]); + ld->stringargs[1] = NULL; } break; case 447: // Change colormap @@ -4033,14 +4134,6 @@ static void P_AddBinaryMapTags(void) } } -static void P_WriteConstant(INT32 constant, char **target) -{ - char buffer[12]; - sprintf(buffer, "%d", constant); - *target = Z_Malloc(strlen(buffer) + 1, PU_LEVEL, NULL); - M_Memcpy(*target, buffer, strlen(buffer) + 1); -} - static line_t *P_FindPointPushLine(taglist_t *list) { INT32 i, l; @@ -4183,7 +4276,6 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] |= TMSP_NOTELEPORT; if (lines[i].flags & ML_WRAPMIDTEX) lines[i].args[1] |= TMSP_FORCESPIN; - P_WriteConstant(sides[lines[i].sidenum[0]].toptexture ? sides[lines[i].sidenum[0]].toptexture : sfx_spdpad, &lines[i].stringargs[0]); break; case 7: //Sector flat alignment lines[i].args[0] = tag; @@ -4269,8 +4361,6 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; lines[i].args[2] = !!(lines[i].flags & ML_SKEWTD); - if (sides[lines[i].sidenum[0]].toptexture) - P_WriteConstant(sides[lines[i].sidenum[0]].toptexture, &lines[i].stringargs[0]); break; case 16: //Minecart parameters lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; @@ -4733,7 +4823,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[2] = 16; } if (lines[i].flags & ML_MIDSOLID) - P_WriteConstant(sides[lines[i].sidenum[0]].textureoffset >> FRACBITS, &lines[i].stringargs[0]); + P_WriteSfx(sides[lines[i].sidenum[0]].textureoffset >> FRACBITS, &lines[i].stringargs[0]); break; case 252: //FOF: Shatter block case 253: //FOF: Shatter block, translucent @@ -5000,11 +5090,6 @@ static void P_ConvertBinaryLinedefTypes(void) else lines[i].args[0] = TMT_CONTINUOUS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); - if (lines[i].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(lines[i].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], lines[i].text, strlen(lines[i].text) + 1); - } lines[i].special = 331; break; case 334: // Object dye - continuous @@ -5017,11 +5102,6 @@ static void P_ConvertBinaryLinedefTypes(void) else lines[i].args[0] = TMT_CONTINUOUS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } lines[i].special = 334; break; case 337: //Emerald check - continuous @@ -5168,11 +5248,6 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[4] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : 0; lines[i].args[5] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].rowoffset >> FRACBITS : -1; lines[i].args[6] = sides[lines[i].sidenum[0]].bottomtexture; - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } break; case 414: //Play sound effect lines[i].args[2] = tag; @@ -5212,11 +5287,6 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] = TMSL_EVERYONE; } } - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } break; case 415: //Run script { @@ -5307,13 +5377,6 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = !!(lines[i].flags & ML_NOCLIMB); break; - case 425: //Change object state - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } - break; case 426: //Stop object lines[i].args[0] = !!(lines[i].flags & ML_NOCLIMB); break; @@ -5353,18 +5416,18 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[2] = !!(lines[i].flags & ML_BLOCKMONSTERS); break; case 434: //Award power-up - if (sides[lines[i].sidenum[0]].text) + if ((lines[i].flags & ML_BLOCKMONSTERS) == 0) { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); + // do NOT read power from back sidedef if this flag is not present + if (lines[i].stringargs[1] != NULL) + { + Z_Free(lines[i].stringargs[1]); + lines[i].stringargs[1] = NULL; + } + + // Instead... write the desired time! + P_WriteTics((lines[i].flags & ML_NOCLIMB) ? -1 : (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS), &lines[i].stringargs[1]); } - if (lines[i].sidenum[1] != 0xffff && lines[i].flags & ML_BLOCKMONSTERS) // read power from back sidedef - { - lines[i].stringargs[1] = Z_Malloc(strlen(sides[lines[i].sidenum[1]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[1], sides[lines[i].sidenum[1]].text, strlen(sides[lines[i].sidenum[1]].text) + 1); - } - else - P_WriteConstant((lines[i].flags & ML_NOCLIMB) ? -1 : (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS), &lines[i].stringargs[1]); break; case 435: //Change plane scroller direction lines[i].args[0] = tag; @@ -5392,30 +5455,10 @@ static void P_ConvertBinaryLinedefTypes(void) break; case 442: //Change object type state lines[i].args[0] = tag; - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } - if (lines[i].sidenum[1] == 0xffff) - lines[i].args[1] = 1; - else - { - lines[i].args[1] = 0; - if (sides[lines[i].sidenum[1]].text) - { - lines[i].stringargs[1] = Z_Malloc(strlen(sides[lines[i].sidenum[1]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[1], sides[lines[i].sidenum[1]].text, strlen(sides[lines[i].sidenum[1]].text) + 1); - } - } + lines[i].args[3] = (lines[i].sidenum[1] == 0xffff) ? 1 : 0; break; case 443: //Call Lua function - if (lines[i].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(lines[i].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], lines[i].text, strlen(lines[i].text) + 1); - } - else + if (lines[i].stringargs[0] == NULL) CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i)); break; case 444: //Earthquake @@ -5568,11 +5611,6 @@ static void P_ConvertBinaryLinedefTypes(void) if (lines[i].flags & ML_MIDSOLID) lines[i].args[2] |= TMP_FREEZETHINKERS;*/ lines[i].args[3] = (lines[i].sidenum[1] != 0xFFFF) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : tag; - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } break; case 460: //Award rings lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; @@ -5600,18 +5638,6 @@ static void P_ConvertBinaryLinedefTypes(void) } else lines[i].args[4] = 0; - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } - break; - case 463: //Dye object - if (sides[lines[i].sidenum[0]].text) - { - lines[i].stringargs[0] = Z_Malloc(strlen(sides[lines[i].sidenum[0]].text) + 1, PU_LEVEL, NULL); - M_Memcpy(lines[i].stringargs[0], sides[lines[i].sidenum[0]].text, strlen(sides[lines[i].sidenum[0]].text) + 1); - } break; case 464: //Trigger egg capsule lines[i].args[0] = tag; @@ -6440,7 +6466,7 @@ static void P_ConvertBinaryThingTypes(void) break; case 543: //Balloon if (mapthings[i].angle > 0) - P_WriteConstant(((mapthings[i].angle - 1) % (numskincolors - 1)) + 1, &mapthings[i].stringargs[0]); + P_WriteSkincolor(((mapthings[i].angle - 1) % (numskincolors - 1)) + 1, &mapthings[i].stringargs[0]); mapthings[i].args[0] = !!(mapthings[i].options & MTF_AMBUSH); break; case 555: //Diagonal yellow spring @@ -6465,22 +6491,22 @@ static void P_ConvertBinaryThingTypes(void) case 706: //Water ambience G case 707: //Water ambience H mapthings[i].args[0] = 35; - P_WriteConstant(sfx_amwtr1 + mapthings[i].type - 700, &mapthings[i].stringargs[0]); + P_WriteSfx(sfx_amwtr1 + mapthings[i].type - 700, &mapthings[i].stringargs[0]); mapthings[i].type = 700; break; case 708: //Disco ambience mapthings[i].args[0] = 512; - P_WriteConstant(sfx_ambint, &mapthings[i].stringargs[0]); + P_WriteSfx(sfx_ambint, &mapthings[i].stringargs[0]); mapthings[i].type = 700; break; case 709: //Volcano ambience mapthings[i].args[0] = 220; - P_WriteConstant(sfx_ambin2, &mapthings[i].stringargs[0]); + P_WriteSfx(sfx_ambin2, &mapthings[i].stringargs[0]); mapthings[i].type = 700; break; case 710: //Machine ambience mapthings[i].args[0] = 24; - P_WriteConstant(sfx_ambmac, &mapthings[i].stringargs[0]); + P_WriteSfx(sfx_ambmac, &mapthings[i].stringargs[0]); mapthings[i].type = 700; break; case 750: //Slope vertex @@ -6543,8 +6569,7 @@ static void P_ConvertBinaryThingTypes(void) mapthings[i].args[3] = sides[lines[j].sidenum[0]].rowoffset >> FRACBITS; mapthings[i].args[4] = lines[j].backsector ? sides[lines[j].sidenum[1]].textureoffset >> FRACBITS : 0; mapthings[i].args[6] = mapthings[i].angle; - if (sides[lines[j].sidenum[0]].toptexture) - P_WriteConstant(sides[lines[j].sidenum[0]].toptexture, &mapthings[i].stringargs[0]); + P_WriteDuplicateText(lines[j].stringargs[0], &mapthings[i].stringargs[0]); break; } case 762: //PolyObject spawn point (crush) @@ -6633,8 +6658,8 @@ static void P_ConvertBinaryThingTypes(void) mapthings[i].args[8] |= TMM_ALWAYSTHINK; if (mapthings[i].type == 1110) { - P_WriteConstant(sides[lines[j].sidenum[0]].toptexture, &mapthings[i].stringargs[0]); - P_WriteConstant(lines[j].backsector ? sides[lines[j].sidenum[1]].toptexture : MT_NULL, &mapthings[i].stringargs[1]); + P_WriteDuplicateText(lines[j].stringargs[0], &mapthings[i].stringargs[0]); + P_WriteDuplicateText(lines[j].stringargs[1], &mapthings[i].stringargs[1]); } break; } @@ -6675,7 +6700,13 @@ static void P_ConvertBinaryThingTypes(void) mapthings[i].args[0] = P_AproxDistance(lines[j].dx, lines[j].dy) >> FRACBITS; mapthings[i].args[1] = sides[lines[j].sidenum[0]].textureoffset >> FRACBITS; mapthings[i].args[2] = !!(lines[j].flags & ML_NOCLIMB); - P_WriteConstant(MT_ROCKCRUMBLE1 + (sides[lines[j].sidenum[0]].rowoffset >> FRACBITS), &mapthings[i].stringargs[0]); + INT32 id = (sides[lines[j].sidenum[0]].rowoffset >> FRACBITS); + // Rather than introduce deh_tables.h as a dependency for literally one + // conversion, we just... recreate the string expected to be produced. + if (id > 0 && id < 16) + P_WriteDuplicateText(va("MT_ROCKCRUMBLE%d", id+1), &mapthings[i].stringargs[0]); + else + P_WriteConstant(MT_ROCKCRUMBLE1 + id, &mapthings[i].stringargs[0], "Mapthing", i); break; } case 1221: //Minecart saloon door @@ -6808,6 +6839,7 @@ static void P_ConvertBinaryLinedefFlags(void) //For maps in binary format, converts setup of specials to UDMF format. static void P_ConvertBinaryMap(void) { + contextdrift = false; P_ConvertBinaryLinedefTypes(); P_ConvertBinarySectorTypes(); P_ConvertBinaryThingTypes(); diff --git a/src/r_defs.h b/src/r_defs.h index 963d655b1..2c98ec3f3 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -547,7 +547,6 @@ typedef struct line_s size_t validcount; // if == validcount, already checked polyobj_t *polyobj; // Belongs to a polyobject? - char *text; // a concatenation of all front and back texture names, for linedef specials that require a string. INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 } line_t; @@ -576,8 +575,6 @@ typedef struct INT16 special; // the special of the linedef this side belongs to INT16 repeatcnt; // # of times to repeat midtexture - char *text; // a concatenation of all top, bottom, and mid texture names, for linedef specials that require a string. - extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors. } side_t; From e914c19e8fe18339ff9688503eb5c3d5485b6f8d Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 21 Jul 2023 14:41:22 +0100 Subject: [PATCH 226/478] P_WriteSfx: Work around the weird case sensitivity in internal instances of get_number by always providing an uppercase prefix on conversion --- src/p_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 27ddb0775..05c9572d5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1283,7 +1283,7 @@ static void P_WriteSfx(INT32 constant, char **target) return; P_WriteDuplicateText( - va("sfx_%s", S_sfx[constant].name), + va("SFX_%s", S_sfx[constant].name), target ); } From 69089e0858170fecad52461cc663400aa3d881fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 22 Jul 2023 22:47:52 +0200 Subject: [PATCH 227/478] Fix build errors when building without SDL --- src/dummy/i_video.c | 2 ++ src/hardware/Sourcefile | 1 - src/hardware/hw_model.c | 2 +- src/{hardware => }/u_list.c | 2 +- src/{hardware => }/u_list.h | 0 5 files changed, 4 insertions(+), 3 deletions(-) rename src/{hardware => }/u_list.c (99%) rename src/{hardware => }/u_list.h (100%) diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index 3b0a12a32..bb796b676 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -57,6 +57,8 @@ const char *VID_GetModeName(INT32 modenum) return NULL; } +UINT32 I_GetRefreshRate(void) { return 35; } + void I_UpdateNoBlit(void){} void I_FinishUpdate(void){} diff --git a/src/hardware/Sourcefile b/src/hardware/Sourcefile index 1c05de76c..6c374621d 100644 --- a/src/hardware/Sourcefile +++ b/src/hardware/Sourcefile @@ -8,6 +8,5 @@ hw_cache.c hw_md2load.c hw_md3load.c hw_model.c -u_list.c hw_batching.c r_opengl/r_opengl.c diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 4ed03744b..b69bce0e2 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -15,7 +15,7 @@ #include "hw_md2load.h" #include "hw_md3load.h" #include "hw_md2.h" -#include "u_list.h" +#include "../u_list.h" #include static float PI = (3.1415926535897932384626433832795f); diff --git a/src/hardware/u_list.c b/src/u_list.c similarity index 99% rename from src/hardware/u_list.c rename to src/u_list.c index dc49a74e7..d5cfd5717 100644 --- a/src/hardware/u_list.c +++ b/src/u_list.c @@ -8,7 +8,7 @@ */ #include "u_list.h" -#include "../z_zone.h" +#include "z_zone.h" // Utility for managing // structures in a linked diff --git a/src/hardware/u_list.h b/src/u_list.h similarity index 100% rename from src/hardware/u_list.h rename to src/u_list.h From d42d1e9a45ff9bc5ac4bdcefa1297f92c198e90b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 22 Jul 2023 22:56:17 +0200 Subject: [PATCH 228/478] fixup! Fix build errors when building without SDL --- src/Sourcefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Sourcefile b/src/Sourcefile index fb08c2171..7c5305000 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -83,6 +83,7 @@ i_tcp.c lzf.c vid_copy.s b_bot.c +u_list.c lua_script.c lua_baselib.c lua_mathlib.c From 4bc7b2da1172f9a0142555c5c6d2ea5bdc7303cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 22 Jul 2023 22:59:00 +0200 Subject: [PATCH 229/478] fixup! fixup! Fix build errors when building without SDL --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b23aaa5a0..0f14a4965 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -49,7 +49,7 @@ #include "m_anigif.h" #include "md5.h" #include "m_perfstats.h" -#include "hardware/u_list.h" // TODO: this should be a standard utility class +#include "u_list.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR From 66f8908b03b68cc0d350b1556f49af3d6eb39ab6 Mon Sep 17 00:00:00 2001 From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com> Date: Sat, 22 Jul 2023 20:44:22 -0500 Subject: [PATCH 230/478] Reset Camera only if a new camera is set / Fix Lua jank with setting awayviewmobj or awayviewtics solo --- src/lua_playerlib.c | 27 ++++++++++++++++++++------- src/p_spec.c | 8 ++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 1c3b4f46c..4b4c9d30f 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1278,17 +1278,30 @@ static int player_set(lua_State *L) mobj_t *mo = NULL; if (!lua_isnil(L, 3)) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); - P_SetTarget(&plr->awayviewmobj, mo); - if (plr == &players[displayplayer]) - P_ResetCamera(plr, &camera); // reset p1 camera on p1 getting an awayviewmobj - else if (splitscreen && plr == &players[secondarydisplayplayer]) - P_ResetCamera(plr, &camera2); // reset p2 camera on p2 getting an awayviewmobj + if (plr->awayviewmobj != mo) { + P_SetTarget(&plr->awayviewmobj, mo); + if (plr->awayviewtics) { + if (!plr->awayviewmobj) + plr->awayviewtics = 0; // can't have a NULL awayviewmobj with awayviewtics! + if (plr == &players[displayplayer]) + P_ResetCamera(plr, &camera); // reset p1 camera on p1 getting an awayviewmobj + else if (splitscreen && plr == &players[secondarydisplayplayer]) + P_ResetCamera(plr, &camera2); // reset p2 camera on p2 getting an awayviewmobj + } + } break; } case player_awayviewtics: - plr->awayviewtics = (INT32)luaL_checkinteger(L, 3); - if (plr->awayviewtics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!! + INT32 tics = (INT32)luaL_checkinteger(L, 3); + if (tics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!! P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now. + if ((tics && !plr->awayviewtics) || (!tics && plr->awayviewtics)) { + if (plr == &players[displayplayer]) + P_ResetCamera(plr, &camera); // reset p1 camera on p1 transitioning to/from zero awayviewtics + else if (splitscreen && plr == &players[secondarydisplayplayer]) + P_ResetCamera(plr, &camera2); // reset p2 camera on p2 transitioning to/from zero awayviewtics + } + plr->awayviewtics = tics; break; case player_awayviewaiming: plr->awayviewaiming = luaL_checkangle(L, 3); diff --git a/src/p_spec.c b/src/p_spec.c index 877b9c7bc..33253e521 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2661,10 +2661,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // This is not revoked until overwritten; awayviewtics is ignored if (titlemapinaction) titlemapcameraref = altview; - else - { + else if (!mo->player->awayviewtics || mo->player->awayviewmobj != altview) { P_SetTarget(&mo->player->awayviewmobj, altview); - mo->player->awayviewtics = line->args[1]; if (mo->player == &players[displayplayer]) P_ResetCamera(mo->player, &camera); // reset p1 camera on p1 getting an awayviewmobj @@ -2679,8 +2677,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) aim <<= 8; if (titlemapinaction) titlemapcameraref->cusval = (angle_t)aim; - else + else { mo->player->awayviewaiming = (angle_t)aim; + mo->player->awayviewtics = line->args[1]; + } } break; From 95cbee52c6b9293c03cb6c33007e73b2f1df7895 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 28 May 2019 17:21:22 -0400 Subject: [PATCH 231/478] Model tilts - Add modeltilt variable, for more manual control of the model tilting. By default this just copies standingslope, but doesn't get cleared in the air. - Shadows & trailing bananas now tilt to match the ground they are on. - Rocket Sneakers & afterimages now tilt to match the player's current orientation. --- src/hardware/hw_md2.c | 8 ++++---- src/p_map.c | 6 ++++++ src/p_mobj.c | 6 ++++++ src/p_mobj.h | 3 +++ src/p_saveg.c | 4 ++++ src/p_slopes.c | 6 ++++++ src/p_user.c | 4 ++++ 7 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 38e8e8fc4..16f25118f 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1647,11 +1647,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) #ifdef USE_FTRANSFORM_ANGLEZ // Slope rotation from Kart p.anglez = 0.0f; - if (spr->mobj->standingslope) + if (spr->mobj->modeltilt) { - fixed_t tempz = spr->mobj->standingslope->normal.z; - fixed_t tempy = spr->mobj->standingslope->normal.y; - fixed_t tempx = spr->mobj->standingslope->normal.x; + fixed_t tempz = spr->mobj->modeltilt->normal.z; + fixed_t tempy = spr->mobj->modeltilt->normal.y; + fixed_t tempx = spr->mobj->modeltilt->normal.x; fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx)); p.anglez = FIXED_TO_FLOAT(tempangle); tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy)); diff --git a/src/p_map.c b/src/p_map.c index 0021fe450..e486136ff 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2928,6 +2928,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz <= 0) { thing->standingslope = tmfloorslope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); } @@ -2939,6 +2942,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz >= 0) { thing->standingslope = tmceilingslope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); } diff --git a/src/p_mobj.c b/src/p_mobj.c index a43afc9b1..cce79b496 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1985,6 +1985,9 @@ void P_XYMovement(mobj_t *mo) // Now compare the Zs of the different quantizations if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later mo->standingslope = oldslope; +#ifdef HWRENDER + mo->modeltilt = mo->standingslope; +#endif P_SlopeLaunch(mo); //CONS_Printf("launched off of slope - "); @@ -2557,6 +2560,9 @@ boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; +#ifdef HWRENDER + mo->modeltilt = mo->standingslope; +#endif P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } diff --git a/src/p_mobj.h b/src/p_mobj.h index f573e9020..a17b94b87 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -394,6 +394,9 @@ typedef struct mobj_s INT32 cvmem; struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) +#ifdef HWRENDER + struct pslope_s *modeltilt; // Slope used for model tilting. Also is not synched, this is totally visual. +#endif boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation) boolean colorized; // Whether the mobj uses the rainbow colormap diff --git a/src/p_saveg.c b/src/p_saveg.c index 40fd65638..65c9eff64 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2996,7 +2996,11 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_HPREV) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); if (diff2 & MD2_SLOPE) + { mobj->standingslope = P_SlopeById(READUINT16(save_p)); +#ifdef HWRENDER + mobj->modeltilt = mobj->standingslope; +#endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); if (diff2 & MD2_MIRRORED) diff --git a/src/p_slopes.c b/src/p_slopes.c index 1f07b8f37..023ee46b9 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -899,6 +899,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { thing->standingslope = slope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) thing->momz = -P_MobjFlip(thing); } @@ -915,6 +918,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) thing->momx = mom.x; thing->momy = mom.y; thing->standingslope = slope; +#ifdef HWRENDER + thing->modeltilt = thing->standingslope; +#endif if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) thing->momz = -P_MobjFlip(thing); } diff --git a/src/p_user.c b/src/p_user.c index 1adf6bc3f..f8cbf8fdb 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1995,6 +1995,10 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->fuse = ghost->info->damage; ghost->skin = mobj->skin; + ghost->standingslope = mobj->standingslope; +#ifdef HWRENDER + ghost->modeltilt = mobj->modeltilt; +#endif if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; From ae233b000ff7d859e0fcdf43cfc9df4d2ade904d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 28 Oct 2020 18:36:26 -0400 Subject: [PATCH 232/478] Remove modeltilt, use roll & pitch instead Broken currently, about half of the slopes you can go into have the wrong tilt --- src/hardware/hw_defs.h | 7 +------ src/hardware/hw_md2.c | 20 ++++++++------------ src/hardware/r_opengl/r_opengl.c | 2 -- src/p_local.h | 1 + src/p_map.c | 10 ++++------ src/p_mobj.c | 28 ++++++++++++++++++++++------ src/p_mobj.h | 3 --- src/p_saveg.c | 4 ---- src/p_slopes.c | 9 +++------ src/p_user.c | 5 ++--- 10 files changed, 41 insertions(+), 48 deletions(-) diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 227fdf92b..131d2caa3 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -94,8 +94,7 @@ typedef struct FVector //BP: transform order : scale(rotation_x(rotation_y(translation(v)))) // Kart features -//#define USE_FTRANSFORM_ANGLEZ -//#define USE_FTRANSFORM_MIRROR +#define USE_FTRANSFORM_MIRROR // Vanilla features #define USE_MODEL_NEXTFRAME @@ -103,11 +102,7 @@ typedef struct FVector typedef struct { FLOAT x,y,z; // position -#ifdef USE_FTRANSFORM_ANGLEZ FLOAT anglex,angley,anglez; // aimingangle / viewangle -#else - FLOAT anglex,angley; // aimingangle / viewangle -#endif FLOAT scalex,scaley,scalez; FLOAT fovxangle, fovyangle; UINT8 splitscreen; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 16f25118f..cc7ef1e71 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1642,22 +1642,18 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.rollflip *= -1; } + p.anglez = 0.0f; p.anglex = 0.0f; -#ifdef USE_FTRANSFORM_ANGLEZ - // Slope rotation from Kart - p.anglez = 0.0f; - if (spr->mobj->modeltilt) + if (spr->mobj->pitch) { - fixed_t tempz = spr->mobj->modeltilt->normal.z; - fixed_t tempy = spr->mobj->modeltilt->normal.y; - fixed_t tempx = spr->mobj->modeltilt->normal.x; - fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx)); - p.anglez = FIXED_TO_FLOAT(tempangle); - tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy)); - p.anglex = FIXED_TO_FLOAT(tempangle); + p.anglez = FIXED_TO_FLOAT(-AngleFixed(spr->mobj->pitch)); + } + + if (spr->mobj->roll) + { + p.anglex = FIXED_TO_FLOAT(AngleFixed(spr->mobj->roll)); } -#endif // SRB2CBTODO: MD2 scaling support finalscale *= FIXED_TO_FLOAT(interp.scale); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 2fc1df881..0ba32a27e 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2815,9 +2815,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float if (hflipped) scalez = -scalez; -#ifdef USE_FTRANSFORM_ANGLEZ pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart -#endif pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); diff --git a/src/p_local.h b/src/p_local.h index 3c84d6fe2..563e257d8 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -537,5 +537,6 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_DoSuperTransformation(player_t *player, boolean giverings); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); +void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); #endif // __P_LOCAL__ diff --git a/src/p_map.c b/src/p_map.c index e486136ff..4dffb8e10 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2928,9 +2928,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz <= 0) { thing->standingslope = tmfloorslope; -#ifdef HWRENDER - thing->modeltilt = thing->standingslope; -#endif + P_SetPitchRollFromSlope(thing, thing->standingslope); + if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); } @@ -2942,9 +2941,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz >= 0) { thing->standingslope = tmceilingslope; -#ifdef HWRENDER - thing->modeltilt = thing->standingslope; -#endif + P_SetPitchRollFromSlope(thing, thing->standingslope); + if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); } diff --git a/src/p_mobj.c b/src/p_mobj.c index cce79b496..9c6df4cf5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1551,6 +1551,26 @@ void P_CheckGravity(mobj_t *mo, boolean affect) } } +// +// P_SetPitchRollFromSlope +// +void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) +{ + if (slope) + { + fixed_t tempz = slope->normal.z; + fixed_t tempy = slope->normal.y; + fixed_t tempx = slope->normal.x; + + mo->pitch = -R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx); + mo->roll = -R_PointToAngle2(0, 0, tempz, tempy); + } + else + { + mo->pitch = mo->roll = 0; + } +} + #define STOPSPEED (FRACUNIT) // @@ -1985,9 +2005,7 @@ void P_XYMovement(mobj_t *mo) // Now compare the Zs of the different quantizations if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later mo->standingslope = oldslope; -#ifdef HWRENDER - mo->modeltilt = mo->standingslope; -#endif + P_SetPitchRollFromSlope(mo, mo->standingslope); P_SlopeLaunch(mo); //CONS_Printf("launched off of slope - "); @@ -2560,9 +2578,7 @@ boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; -#ifdef HWRENDER - mo->modeltilt = mo->standingslope; -#endif + P_SetPitchRollFromSlope(mo, mo->standingslope); P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } diff --git a/src/p_mobj.h b/src/p_mobj.h index a17b94b87..f573e9020 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -394,9 +394,6 @@ typedef struct mobj_s INT32 cvmem; struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) -#ifdef HWRENDER - struct pslope_s *modeltilt; // Slope used for model tilting. Also is not synched, this is totally visual. -#endif boolean resetinterp; // if true, some fields should not be interpolated (see R_InterpolateMobjState implementation) boolean colorized; // Whether the mobj uses the rainbow colormap diff --git a/src/p_saveg.c b/src/p_saveg.c index 65c9eff64..40fd65638 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2996,11 +2996,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_HPREV) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); if (diff2 & MD2_SLOPE) - { mobj->standingslope = P_SlopeById(READUINT16(save_p)); -#ifdef HWRENDER - mobj->modeltilt = mobj->standingslope; -#endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); if (diff2 & MD2_MIRRORED) diff --git a/src/p_slopes.c b/src/p_slopes.c index 023ee46b9..6aca116a5 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -899,9 +899,8 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { thing->standingslope = slope; -#ifdef HWRENDER - thing->modeltilt = thing->standingslope; -#endif + P_SetPitchRollFromSlope(thing, slope); + if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) thing->momz = -P_MobjFlip(thing); } @@ -918,9 +917,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) thing->momx = mom.x; thing->momy = mom.y; thing->standingslope = slope; -#ifdef HWRENDER - thing->modeltilt = thing->standingslope; -#endif + P_SetPitchRollFromSlope(thing, slope); if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) thing->momz = -P_MobjFlip(thing); } diff --git a/src/p_user.c b/src/p_user.c index f8cbf8fdb..74b5b7175 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1976,6 +1976,8 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->colorized = mobj->colorized; // alternatively, "true" for sonic advance style colourisation ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle); + ghost->roll = mobj->roll; + ghost->pitch = mobj->pitch; ghost->rollangle = mobj->rollangle; ghost->sprite = mobj->sprite; @@ -1996,9 +1998,6 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->fuse = ghost->info->damage; ghost->skin = mobj->skin; ghost->standingslope = mobj->standingslope; -#ifdef HWRENDER - ghost->modeltilt = mobj->modeltilt; -#endif if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; From 5c23fdda246f412b2342e80a298c02518336c8fd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 28 Oct 2020 21:05:58 -0400 Subject: [PATCH 233/478] Fix incorrect tilts --- src/hardware/hw_md2.c | 14 ++------------ src/hardware/r_opengl/r_opengl.c | 4 ++-- src/p_mobj.c | 4 ++-- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index cc7ef1e71..83a9146cd 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1642,18 +1642,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.rollflip *= -1; } - p.anglez = 0.0f; - p.anglex = 0.0f; - - if (spr->mobj->pitch) - { - p.anglez = FIXED_TO_FLOAT(-AngleFixed(spr->mobj->pitch)); - } - - if (spr->mobj->roll) - { - p.anglex = FIXED_TO_FLOAT(AngleFixed(spr->mobj->roll)); - } + p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch)); + p.anglex = FIXED_TO_FLOAT(AngleFixed(spr->mobj->roll)); // SRB2CBTODO: MD2 scaling support finalscale *= FIXED_TO_FLOAT(interp.scale); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 0ba32a27e..f50479a71 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2815,9 +2815,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float if (hflipped) scalez = -scalez; - pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart - pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); + pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); + pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); if (pos->roll) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 9c6df4cf5..9b22647c8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1562,8 +1562,8 @@ void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) fixed_t tempy = slope->normal.y; fixed_t tempx = slope->normal.x; - mo->pitch = -R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx); - mo->roll = -R_PointToAngle2(0, 0, tempz, tempy); + mo->pitch = R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx); + mo->roll = R_PointToAngle2(0, 0, tempz, tempy); } else { From 7c2a2410426a5143b7879af0e19b5ab16f1e1d62 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 30 Oct 2020 02:15:49 -0400 Subject: [PATCH 234/478] Remove the need for setting rotation axis in spriteinfo for models Now it just does it like Software --- src/deh_soc.c | 2 +- src/hardware/hw_defs.h | 8 +------ src/hardware/hw_main.c | 14 +++++++---- src/hardware/hw_md2.c | 41 ++++++++++---------------------- src/hardware/r_opengl/r_opengl.c | 26 ++------------------ src/lua_infolib.c | 9 ++++--- src/lua_mobjlib.c | 16 ++++++++----- src/p_enemy.c | 8 +++---- src/p_inter.c | 2 +- src/p_mobj.c | 11 +++++++-- src/p_mobj.h | 4 ++-- src/p_saveg.c | 14 +++++------ src/p_user.c | 19 ++++++++------- src/r_fps.c | 19 +++++++++++++++ src/r_fps.h | 3 +++ src/r_picformats.c | 8 ------- src/r_picformats.h | 1 - src/r_splats.c | 2 +- src/r_things.c | 6 ++--- 19 files changed, 102 insertions(+), 111 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 8dd849daf..2193cd875 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -912,7 +912,7 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) else if (fastcmp(word, "YPIVOT")) sprinfo->pivot[frame].y = value; else if (fastcmp(word, "ROTAXIS")) - sprinfo->pivot[frame].rotaxis = value; + deh_warning("SpriteInfo: ROTAXIS is deprecated and will be removed."); else { f->curpos = lastline; diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 131d2caa3..74c4ed7d2 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -93,9 +93,6 @@ typedef struct FVector //Hurdler: Transform (coords + angles) //BP: transform order : scale(rotation_x(rotation_y(translation(v)))) -// Kart features -#define USE_FTRANSFORM_MIRROR - // Vanilla features #define USE_MODEL_NEXTFRAME @@ -108,13 +105,10 @@ typedef struct UINT8 splitscreen; boolean flip; // screenflip boolean roll; - SINT8 rollflip; FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ - UINT8 rotaxis; FLOAT centerx, centery; -#ifdef USE_FTRANSFORM_MIRROR + FLOAT rollx, rollz; boolean mirror; // SRB2Kart: Encore Mode -#endif boolean shearing; // 14042019 float viewaiming; // 17052019 } FTransform; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 4e1b7975e..bb2ce9001 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4158,7 +4158,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) angle = viewangle; if (!spr->rotated) - angle += spr->mobj->rollangle; + angle += spr->mobj->spriteroll; angle = -angle; angle += ANGLE_90; @@ -5245,17 +5245,17 @@ static void HWR_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lumpoff].topoffset; #ifdef ROTSPRITE - if (thing->rollangle + if (interp.spriteroll && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { if (papersprite) { // a positive rollangle should should pitch papersprites upwards relative to their facing angle - rollangle = R_GetRollAngle(InvAngle(thing->rollangle)); + rollangle = R_GetRollAngle(InvAngle(interp.spriteroll)); } else { - rollangle = R_GetRollAngle(thing->rollangle); + rollangle = R_GetRollAngle(interp.spriteroll); } rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); @@ -5913,6 +5913,8 @@ static void HWR_DrawSkyBackground(player_t *player) fixed_t rol = AngleFixed(player->viewrollangle); dometransform.rollangle = FIXED_TO_FLOAT(rol); dometransform.roll = true; + dometransform.rollx = 1.0f; + dometransform.rollz = 0.0f; } dometransform.splitscreen = splitscreen; @@ -6191,6 +6193,8 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) fixed_t rol = AngleFixed(player->viewrollangle); atransform.rollangle = FIXED_TO_FLOAT(rol); atransform.roll = true; + atransform.rollx = 1.0f; + atransform.rollz = 0.0f; } atransform.splitscreen = splitscreen; @@ -6405,6 +6409,8 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) fixed_t rol = AngleFixed(player->viewrollangle); atransform.rollangle = FIXED_TO_FLOAT(rol); atransform.roll = true; + atransform.rollx = 1.0f; + atransform.rollz = 0.0f; } atransform.splitscreen = splitscreen; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 83a9146cd..baacc2490 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1346,8 +1346,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj)); spritedef_t *sprdef; spriteframe_t *sprframe; - spriteinfo_t *sprinfo; - angle_t ang; INT32 mod; float finalscale; interpmobjstate_t interp; @@ -1388,12 +1386,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) { md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2->skin = (skin_t*)spr->mobj->skin-skins; - sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; } else { md2 = &md2_models[spr->mobj->sprite]; - sprinfo = &spriteinfo[spr->mobj->sprite]; } // texture loading before model init, so it knows if sprite graphics are used, which @@ -1615,43 +1611,32 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } p.rollangle = 0.0f; - p.rollflip = 1; - p.rotaxis = 0; - if (spr->mobj->rollangle) + + if (interp.spriteroll) { - fixed_t anglef = AngleFixed(spr->mobj->rollangle); + fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know + fixed_t anglef = AngleFixed(interp.spriteroll); + p.rollangle = FIXED_TO_FLOAT(anglef); p.roll = true; // rotation pivot - p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2); - p.centery = FIXED_TO_FLOAT(spr->mobj->height/(flip ? -2 : 2)); + p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); + p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); - // rotation axis - if (sprinfo->available) - p.rotaxis = (UINT8)(sprinfo->pivot[(spr->mobj->frame & FF_FRAMEMASK)].rotaxis); - - // for NiGHTS specifically but should work everywhere else - ang = R_PointToAngle (interp.x, interp.y) - interp.angle; - if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right - p.rollflip = 1; - else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left - p.rollflip = -1; - - if (flip) - p.rollflip *= -1; + // rotation axes relative to camera + p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); } - p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch)); - p.anglex = FIXED_TO_FLOAT(AngleFixed(spr->mobj->roll)); + p.anglez = FIXED_TO_FLOAT(AngleFixed(interp.pitch)); + p.anglex = FIXED_TO_FLOAT(AngleFixed(interp.roll)); // SRB2CBTODO: MD2 scaling support finalscale *= FIXED_TO_FLOAT(interp.scale); p.flip = atransform.flip; -#ifdef USE_FTRANSFORM_MIRROR - p.mirror = atransform.mirror; // from Kart -#endif + p.mirror = atransform.mirror; HWD.pfnSetShader(SHADER_MODEL); // model shader HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index f50479a71..d785b3cbf 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2782,7 +2782,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); -#ifdef USE_FTRANSFORM_MIRROR // flipped is if the object is vertically flipped // hflipped is if the object is horizontally flipped // pos->flip is if the screen is flipped vertically @@ -2795,17 +2794,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float else pglCullFace(GL_BACK); } -#else - // pos->flip is if the screen is flipped too - if (flipped ^ hflipped ^ pos->flip) // If one or three of these are active, but not two, invert the model's culling - { - pglCullFace(GL_FRONT); - } - else - { - pglCullFace(GL_BACK); - } -#endif pglPushMatrix(); // should be the same as glLoadIdentity //Hurdler: now it seems to work @@ -2821,14 +2809,8 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float if (pos->roll) { - float roll = (1.0f * pos->rollflip); pglTranslatef(pos->centerx, pos->centery, 0); - if (pos->rotaxis == 2) // Z - pglRotatef(pos->rollangle, 0.0f, 0.0f, roll); - else if (pos->rotaxis == 1) // Y - pglRotatef(pos->rollangle, 0.0f, roll, 0.0f); - else // X - pglRotatef(pos->rollangle, roll, 0.0f, 0.0f); + pglRotatef(pos->rollangle, pos->rollx, 0.0f, pos->rollz); pglTranslatef(-pos->centerx, -pos->centery, 0); } @@ -3001,13 +2983,9 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) if (stransform) { used_fov = stransform->fovxangle; -#ifdef USE_FTRANSFORM_MIRROR - // mirroring from Kart if (stransform->mirror) pglScalef(-stransform->scalex, stransform->scaley, -stransform->scalez); - else -#endif - if (stransform->flip) + else if (stransform->flip) pglScalef(stransform->scalex, -stransform->scaley, -stransform->scalez); else pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez); diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 578878b21..10baa3c67 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -319,7 +319,7 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in else if (ikey == 2 || (key && fastcmp(key, "y"))) pivot[idx].y = (INT32)value; else if (ikey == 3 || (key && fastcmp(key, "rotaxis"))) - pivot[idx].rotaxis = (UINT8)value; + LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") else if (ikey == -1 && (key != NULL)) FIELDERROR("pivot key", va("invalid option %s", key)); okcool = 1; @@ -576,7 +576,10 @@ static int framepivot_get(lua_State *L) else if (fastcmp("y", field)) lua_pushinteger(L, framepivot->y); else if (fastcmp("rotaxis", field)) - lua_pushinteger(L, (UINT8)framepivot->rotaxis); + { + LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed."); + lua_pushinteger(L, 0); + } else return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); @@ -602,7 +605,7 @@ static int framepivot_set(lua_State *L) else if (fastcmp("y", field)) framepivot->y = luaL_checkinteger(L, 3); else if (fastcmp("rotaxis", field)) - framepivot->rotaxis = luaL_checkinteger(L, 3); + LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") else return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 09d244c91..404af016a 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -33,7 +33,8 @@ enum mobj_e { mobj_angle, mobj_pitch, mobj_roll, - mobj_rollangle, + mobj_spriteroll, + mobj_rollangle, // backwards compat mobj_sprite, mobj_frame, mobj_sprite2, @@ -110,7 +111,8 @@ static const char *const mobj_opt[] = { "angle", "pitch", "roll", - "rollangle", + "spriteroll", + "rollangle", // backwards compat "sprite", "frame", "sprite2", @@ -229,8 +231,9 @@ static int mobj_get(lua_State *L) case mobj_roll: lua_pushangle(L, mo->roll); break; - case mobj_rollangle: - lua_pushangle(L, mo->rollangle); + case mobj_spriteroll: + case mobj_rollangle: // backwards compat + lua_pushangle(L, mo->spriteroll); break; case mobj_sprite: lua_pushinteger(L, mo->sprite); @@ -518,8 +521,9 @@ static int mobj_set(lua_State *L) case mobj_roll: mo->roll = luaL_checkangle(L, 3); break; - case mobj_rollangle: - mo->rollangle = luaL_checkangle(L, 3); + case mobj_spriteroll: + case mobj_rollangle: // backwards compat + mo->spriteroll = luaL_checkangle(L, 3); break; case mobj_sprite: mo->sprite = luaL_checkinteger(L, 3); diff --git a/src/p_enemy.c b/src/p_enemy.c index d9b44e603..b40525b2d 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8687,10 +8687,10 @@ void A_RollAngle(mobj_t *actor) // relative (default) if (!locvar2) - actor->rollangle += angle; + actor->spriteroll += angle; // absolute else - actor->rollangle = angle; + actor->spriteroll = angle; } // Function: A_ChangeRollAngleRelative @@ -8715,7 +8715,7 @@ void A_ChangeRollAngleRelative(mobj_t *actor) I_Error("A_ChangeRollAngleRelative: var1 is greater than var2"); #endif - actor->rollangle += FixedAngle(P_RandomRange(amin, amax)); + actor->spriteroll += FixedAngle(P_RandomRange(amin, amax)); } // Function: A_ChangeRollAngleAbsolute @@ -8740,7 +8740,7 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor) I_Error("A_ChangeRollAngleAbsolute: var1 is greater than var2"); #endif - actor->rollangle = FixedAngle(P_RandomRange(amin, amax)); + actor->spriteroll = FixedAngle(P_RandomRange(amin, amax)); } // Function: A_PlaySound diff --git a/src/p_inter.c b/src/p_inter.c index 8c57beac8..4d22ba343 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3117,7 +3117,7 @@ static void P_NiGHTSDamage(mobj_t *target, mobj_t *source) P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN); S_StartSound(target, sfx_nghurt); - player->mo->rollangle = 0; + player->mo->spriteroll = 0; if (oldnightstime > 10*TICRATE && player->nightstime < 10*TICRATE) diff --git a/src/p_mobj.c b/src/p_mobj.c index 9b22647c8..9a889d516 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9868,9 +9868,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) break; case MT_MINUS: if (P_IsObjectOnGround(mobj)) - mobj->rollangle = 0; + mobj->spriteroll = 0; else - mobj->rollangle = R_PointToAngle2(0, 0, P_MobjFlip(mobj)*mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); + mobj->spriteroll = R_PointToAngle2(0, 0, P_MobjFlip(mobj)*mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); break; case MT_PUSH: P_PointPushThink(mobj); @@ -14167,6 +14167,13 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo newmobj->old_angle = mobj->old_angle; } + newmobj->old_pitch2 = mobj->old_pitch2; + newmobj->old_pitch = mobj->old_pitch; + newmobj->old_roll2 = mobj->old_roll2; + newmobj->old_roll = mobj->old_roll; + newmobj->old_spriteroll2 = mobj->old_spriteroll2; + newmobj->old_spriteroll = mobj->old_spriteroll; + newmobj->old_scale2 = mobj->old_scale2; newmobj->old_scale = mobj->old_scale; newmobj->old_spritexscale = mobj->old_spritexscale; diff --git a/src/p_mobj.h b/src/p_mobj.h index f573e9020..6a5ab84c4 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -292,7 +292,7 @@ typedef struct mobj_s angle_t angle, pitch, roll; // orientation angle_t old_angle, old_pitch, old_roll; // orientation interpolation angle_t old_angle2, old_pitch2, old_roll2; - angle_t rollangle; + angle_t spriteroll, old_spriteroll, old_spriteroll2; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h UINT8 sprite2; // player sprites @@ -429,7 +429,7 @@ typedef struct precipmobj_s angle_t angle, pitch, roll; // orientation angle_t old_angle, old_pitch, old_roll; // orientation interpolation angle_t old_angle2, old_pitch2, old_roll2; - angle_t rollangle; + angle_t spriteroll, old_spriteroll, old_spriteroll2; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h UINT8 sprite2; // player sprites diff --git a/src/p_saveg.c b/src/p_saveg.c index 40fd65638..ce0b262a3 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1565,7 +1565,7 @@ typedef enum MD2_SLOPE = 1<<11, MD2_COLORIZED = 1<<12, MD2_MIRRORED = 1<<13, - MD2_ROLLANGLE = 1<<14, + MD2_SPRITEROLL = 1<<14, MD2_SHADOWSCALE = 1<<15, MD2_RENDERFLAGS = 1<<16, MD2_BLENDMODE = 1<<17, @@ -1783,8 +1783,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_COLORIZED; if (mobj->mirrored) diff2 |= MD2_MIRRORED; - if (mobj->rollangle) - diff2 |= MD2_ROLLANGLE; + if (mobj->spriteroll) + diff2 |= MD2_SPRITEROLL; if (mobj->shadowscale) diff2 |= MD2_SHADOWSCALE; if (mobj->renderflags) @@ -1951,8 +1951,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, mobj->colorized); if (diff2 & MD2_MIRRORED) WRITEUINT8(save_p, mobj->mirrored); - if (diff2 & MD2_ROLLANGLE) - WRITEANGLE(save_p, mobj->rollangle); + if (diff2 & MD2_SPRITEROLL) + WRITEANGLE(save_p, mobj->spriteroll); if (diff2 & MD2_SHADOWSCALE) WRITEFIXED(save_p, mobj->shadowscale); if (diff2 & MD2_RENDERFLAGS) @@ -3001,8 +3001,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->colorized = READUINT8(save_p); if (diff2 & MD2_MIRRORED) mobj->mirrored = READUINT8(save_p); - if (diff2 & MD2_ROLLANGLE) - mobj->rollangle = READANGLE(save_p); + if (diff2 & MD2_SPRITEROLL) + mobj->spriteroll = READANGLE(save_p); if (diff2 & MD2_SHADOWSCALE) mobj->shadowscale = READFIXED(save_p); if (diff2 & MD2_RENDERFLAGS) diff --git a/src/p_user.c b/src/p_user.c index 74b5b7175..16952f775 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -676,7 +676,7 @@ static void P_DeNightserizePlayer(player_t *player) player->marebonuslap = 0; player->flyangle = 0; player->anotherflyangle = 0; - player->mo->rollangle = 0; + player->mo->spriteroll = 0; P_SetTarget(&player->mo->target, NULL); P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL)); @@ -802,7 +802,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->secondjump = 0; player->flyangle = 0; player->anotherflyangle = 0; - player->mo->rollangle = 0; + player->mo->spriteroll = 0; player->powers[pw_shield] = SH_NONE; player->powers[pw_super] = 0; @@ -1978,7 +1978,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle); ghost->roll = mobj->roll; ghost->pitch = mobj->pitch; - ghost->rollangle = mobj->rollangle; + ghost->spriteroll = mobj->spriteroll; ghost->sprite = mobj->sprite; ghost->sprite2 = mobj->sprite2; @@ -2017,6 +2017,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->old_angle = (mobj->player ? mobj->player->old_drawangle2 : mobj->old_angle2); ghost->old_pitch = mobj->old_pitch2; ghost->old_roll = mobj->old_roll2; + ghost->old_spriteroll = mobj->old_spriteroll2; return ghost; } @@ -6793,9 +6794,9 @@ static void P_DoNiGHTSCapsule(player_t *player) { if ((player->mo->state == &states[S_PLAY_NIGHTS_PULL]) && (player->mo->sprite2 == SPR2_NPUL)) - player->mo->rollangle -= ANG30; + player->mo->spriteroll -= ANG30; else - player->mo->rollangle = 0; + player->mo->spriteroll = 0; } if (G_IsSpecialStage(gamemap)) @@ -7248,7 +7249,7 @@ static void P_NiGHTSMovement(player_t *player) && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) { player->mo->momx = player->mo->momy = player->mo->momz = 0; - player->mo->rollangle = 0; + player->mo->spriteroll = 0; return; } @@ -7266,7 +7267,7 @@ static void P_NiGHTSMovement(player_t *player) { if (player->mo->state != &states[S_PLAY_NIGHTS_DRILL]) P_SetPlayerMobjState(player->mo, S_PLAY_NIGHTS_DRILL); - player->mo->rollangle = ANGLE_90; + player->mo->spriteroll = ANGLE_90; } else #endif @@ -7599,9 +7600,9 @@ static void P_NiGHTSMovement(player_t *player) P_SetPlayerMobjState(player->mo, flystate); if (player->charflags & SF_NONIGHTSROTATION) - player->mo->rollangle = 0; + player->mo->spriteroll = 0; else - player->mo->rollangle = rollangle; + player->mo->spriteroll = rollangle; P_SetPlayerAngle(player, player->mo->angle); diff --git a/src/r_fps.c b/src/r_fps.c index 6166f0408..e8f43f499 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -294,6 +294,9 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out) out->scale = mobj->scale; out->subsector = mobj->subsector; out->angle = mobj->player ? mobj->player->drawangle : mobj->angle; + out->pitch = mobj->pitch; + out->roll = mobj->roll; + out->spriteroll = mobj->spriteroll; out->spritexscale = mobj->spritexscale; out->spriteyscale = mobj->spriteyscale; out->spritexoffset = mobj->spritexoffset; @@ -323,6 +326,10 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out) { out->angle = mobj->resetinterp ? mobj->angle : R_LerpAngle(mobj->old_angle, mobj->angle, frac); } + + out->pitch = mobj->resetinterp ? mobj->pitch : R_LerpAngle(mobj->old_pitch, mobj->pitch, frac); + out->roll = mobj->resetinterp ? mobj->roll : R_LerpAngle(mobj->old_roll, mobj->roll, frac); + out->spriteroll = mobj->resetinterp ? mobj->spriteroll : R_LerpAngle(mobj->old_spriteroll, mobj->spriteroll, frac); } void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjstate_t *out) @@ -335,6 +342,9 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst out->scale = FRACUNIT; out->subsector = mobj->subsector; out->angle = mobj->angle; + out->pitch = mobj->angle; + out->roll = mobj->roll; + out->spriteroll = mobj->spriteroll; out->spritexscale = mobj->spritexscale; out->spriteyscale = mobj->spriteyscale; out->spritexoffset = mobj->spritexoffset; @@ -354,6 +364,9 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst out->subsector = R_PointInSubsector(out->x, out->y); out->angle = R_LerpAngle(mobj->old_angle, mobj->angle, frac); + out->pitch = R_LerpAngle(mobj->old_pitch, mobj->pitch, frac); + out->roll = R_LerpAngle(mobj->old_roll, mobj->roll, frac); + out->spriteroll = R_LerpAngle(mobj->old_spriteroll, mobj->spriteroll, frac); } static void AddInterpolator(levelinterpolator_t* interpolator) @@ -766,6 +779,7 @@ void R_ResetMobjInterpolationState(mobj_t *mobj) mobj->old_angle2 = mobj->old_angle; mobj->old_pitch2 = mobj->old_pitch; mobj->old_roll2 = mobj->old_roll; + mobj->old_spriteroll2 = mobj->old_spriteroll; mobj->old_scale2 = mobj->old_scale; mobj->old_x = mobj->x; mobj->old_y = mobj->y; @@ -773,6 +787,7 @@ void R_ResetMobjInterpolationState(mobj_t *mobj) mobj->old_angle = mobj->angle; mobj->old_pitch = mobj->pitch; mobj->old_roll = mobj->roll; + mobj->old_spriteroll = mobj->spriteroll; mobj->old_scale = mobj->scale; mobj->old_spritexscale = mobj->spritexscale; mobj->old_spriteyscale = mobj->spriteyscale; @@ -801,10 +816,14 @@ void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj) mobj->old_angle2 = mobj->old_angle; mobj->old_pitch2 = mobj->old_pitch; mobj->old_roll2 = mobj->old_roll; + mobj->old_spriteroll2 = mobj->old_spriteroll; mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; mobj->old_angle = mobj->angle; + mobj->old_pitch = mobj->pitch; + mobj->old_roll = mobj->roll; + mobj->old_spriteroll = mobj->spriteroll; mobj->old_spritexscale = mobj->spritexscale; mobj->old_spriteyscale = mobj->spriteyscale; mobj->old_spritexoffset = mobj->spritexoffset; diff --git a/src/r_fps.h b/src/r_fps.h index 85c87a2f4..9a8bfa38a 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -59,6 +59,9 @@ typedef struct { fixed_t z; subsector_t *subsector; angle_t angle; + angle_t pitch; + angle_t roll; + angle_t spriteroll; fixed_t scale; fixed_t spritexscale; fixed_t spriteyscale; diff --git a/src/r_picformats.c b/src/r_picformats.c index 9aea8c6c1..3e817f4a0 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1407,7 +1407,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) UINT8 frameFrame = 0xFF; INT16 frameXPivot = 0; INT16 frameYPivot = 0; - rotaxis_t frameRotAxis = 0; // Sprite identifier sprinfoToken = M_GetToken(NULL); @@ -1458,12 +1457,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) { Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); - if ((stricmp(sprinfoToken, "X")==0) || (stricmp(sprinfoToken, "XAXIS")==0) || (stricmp(sprinfoToken, "ROLL")==0)) - frameRotAxis = ROTAXIS_X; - else if ((stricmp(sprinfoToken, "Y")==0) || (stricmp(sprinfoToken, "YAXIS")==0) || (stricmp(sprinfoToken, "PITCH")==0)) - frameRotAxis = ROTAXIS_Y; - else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) - frameRotAxis = ROTAXIS_Z; } Z_Free(sprinfoToken); @@ -1480,7 +1473,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) // set fields info->pivot[frameFrame].x = frameXPivot; info->pivot[frameFrame].y = frameYPivot; - info->pivot[frameFrame].rotaxis = frameRotAxis; } // diff --git a/src/r_picformats.h b/src/r_picformats.h index 4f9637460..4050a1b71 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -95,7 +95,6 @@ typedef enum typedef struct { INT32 x, y; - rotaxis_t rotaxis; } spriteframepivot_t; typedef struct diff --git a/src/r_splats.c b/src/r_splats.c index 72bfe74b3..d182d628b 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -191,7 +191,7 @@ void R_DrawFloorSplat(vissprite_t *spr) splatangle = spr->viewpoint.angle; if (!(spr->cut & SC_ISROTATED)) - splatangle += mobj->rollangle; + splatangle += mobj->spriteroll; splat.angle = -splatangle; splat.angle += ANGLE_90; diff --git a/src/r_things.c b/src/r_things.c index 19b8ee83d..eab8d13c2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1743,17 +1743,17 @@ static void R_ProjectSprite(mobj_t *thing) patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); #ifdef ROTSPRITE - if (thing->rollangle + if (interp.spriteroll && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { if (papersprite && ang >= ANGLE_180) { // Makes Software act much more sane like OpenGL - rollangle = R_GetRollAngle(InvAngle(thing->rollangle)); + rollangle = R_GetRollAngle(InvAngle(interp.spriteroll)); } else { - rollangle = R_GetRollAngle(thing->rollangle); + rollangle = R_GetRollAngle(interp.spriteroll); } rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); From b6129a6d42babaec67319e523db12af9d9e7b4a2 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 30 Oct 2020 15:54:58 -0400 Subject: [PATCH 235/478] Add R_SpriteRotationAngle function Gets the rotation angle for the mobj's sprite. Meant for pitch & roll later, but that part is if'd out currently and just returns mobj->rollangle --- src/hardware/hw_main.c | 10 +++++++--- src/r_patch.h | 2 ++ src/r_patchrotation.c | 18 ++++++++++++++++++ src/r_things.c | 9 ++++++--- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bb2ce9001..8c1bc09e0 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5078,6 +5078,7 @@ static void HWR_ProjectSprite(mobj_t *thing) #ifdef ROTSPRITE patch_t *rotsprite = NULL; INT32 rollangle = 0; + angle_t spriterotangle = 0; #endif // uncapped/interpolation @@ -5245,18 +5246,21 @@ static void HWR_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lumpoff].topoffset; #ifdef ROTSPRITE - if (interp.spriteroll + spriterotangle = R_SpriteRotationAngle(&interp); + + if (spriterotangle != 0 && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { if (papersprite) { // a positive rollangle should should pitch papersprites upwards relative to their facing angle - rollangle = R_GetRollAngle(InvAngle(interp.spriteroll)); + rollangle = R_GetRollAngle(InvAngle(spriterotangle)); } else { - rollangle = R_GetRollAngle(interp.spriteroll); + rollangle = R_GetRollAngle(spriterotangle); } + rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); if (rotsprite != NULL) diff --git a/src/r_patch.h b/src/r_patch.h index d2106a390..27f7bddb6 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -14,6 +14,7 @@ #include "r_defs.h" #include "r_picformats.h" +#include "r_fps.h" #include "doomdef.h" // Patch functions @@ -38,6 +39,7 @@ patch_t *Patch_GetRotatedSprite( size_t frame, size_t spriteangle, boolean flip, boolean adjustfeet, void *info, INT32 rotationangle); +angle_t R_SpriteRotationAngle(interpmobjstate_t *interp); INT32 R_GetRollAngle(angle_t rollangle); #endif diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 3d3c6c512..f9c4ec797 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -13,11 +13,29 @@ #include "r_things.h" // FEETADJUST #include "z_zone.h" #include "w_wad.h" +#include "r_main.h" // R_PointToAngle #ifdef ROTSPRITE fixed_t rollcosang[ROTANGLES]; fixed_t rollsinang[ROTANGLES]; +// +// R_SpriteRotationAngle +// +// Gets the rollangle for the input object. +// +angle_t R_SpriteRotationAngle(interpmobjstate_t *interp) +{ + angle_t viewingAngle = R_PointToAngle(interp->x, interp->y); + + fixed_t pitchMul = -FINESINE(viewingAngle >> ANGLETOFINESHIFT); + fixed_t rollMul = FINECOSINE(viewingAngle >> ANGLETOFINESHIFT); + + angle_t rollOrPitch = FixedMul(interp->pitch, pitchMul) + FixedMul(interp->roll, rollMul); + + return (rollOrPitch + interp->spriteroll); +} + INT32 R_GetRollAngle(angle_t rollangle) { INT32 ra = AngleFixed(rollangle)>>FRACBITS; diff --git a/src/r_things.c b/src/r_things.c index eab8d13c2..248357e11 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1594,6 +1594,7 @@ static void R_ProjectSprite(mobj_t *thing) #ifdef ROTSPRITE patch_t *rotsprite = NULL; INT32 rollangle = 0; + angle_t spriterotangle = 0; #endif // uncapped/interpolation @@ -1743,17 +1744,19 @@ static void R_ProjectSprite(mobj_t *thing) patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); #ifdef ROTSPRITE - if (interp.spriteroll + spriterotangle = R_SpriteRotationAngle(&interp); + + if (spriterotangle != 0 && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { if (papersprite && ang >= ANGLE_180) { // Makes Software act much more sane like OpenGL - rollangle = R_GetRollAngle(InvAngle(interp.spriteroll)); + rollangle = R_GetRollAngle(InvAngle(spriterotangle)); } else { - rollangle = R_GetRollAngle(interp.spriteroll); + rollangle = R_GetRollAngle(spriterotangle); } rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); From 7db09b657b2735ea7b5655a6aa8df52f30dc913e Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 22:13:56 -0800 Subject: [PATCH 236/478] Tilt models --- src/hardware/hw_md2.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index baacc2490..a20d80848 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1610,23 +1610,26 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.angley = FIXED_TO_FLOAT(anglef); } - p.rollangle = 0.0f; - - if (interp.spriteroll) { - fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know - fixed_t anglef = AngleFixed(interp.spriteroll); + fixed_t anglef = AngleFixed(R_SpriteRotationAngle(&interp)); - p.rollangle = FIXED_TO_FLOAT(anglef); - p.roll = true; + p.rollangle = 0.0f; - // rotation pivot - p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); - p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + if (anglef) + { + fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know - // rotation axes relative to camera - p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); - p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + p.rollangle = FIXED_TO_FLOAT(anglef); + p.roll = true; + + // rotation pivot + p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); + p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + + // rotation axes relative to camera + p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT)); + } } p.anglez = FIXED_TO_FLOAT(AngleFixed(interp.pitch)); From c065029b01d6e3bfea4542b5f3443ad3115422fc Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 9 Dec 2021 22:41:35 -0800 Subject: [PATCH 237/478] Model stretching --- src/hardware/hw_drv.h | 3 +-- src/hardware/hw_md2.c | 6 +++++- src/hardware/r_opengl/r_opengl.c | 15 ++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 426d2f283..1c4cd99ab 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -51,7 +51,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); @@ -136,4 +136,3 @@ extern struct hwdriver_s hwdriver; #endif //not defined _CREATE_DLL_ #endif //__HWR_DRV_H__ - diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index a20d80848..0f9195a75 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1642,7 +1642,11 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.mirror = atransform.mirror; HWD.pfnSetShader(SHADER_MODEL); // model shader - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf); + { + float xs = finalscale * FIXED_TO_FLOAT(spr->mobj->spritexscale); + float ys = finalscale * FIXED_TO_FLOAT(spr->mobj->spriteyscale); + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, xs, ys, flip, hflip, &Surf); + } } return true; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index d785b3cbf..71cb5ca70 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2679,7 +2679,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) #define BUFFER_OFFSET(i) ((void*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) +static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { static GLRGBAFloat poly = {0,0,0,0}; static GLRGBAFloat tint = {0,0,0,0}; @@ -2703,10 +2703,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float #endif // Affect input model scaling - scale *= 0.5f; - scalex = scale; - scaley = scale; - scalez = scale; + hscale *= 0.5f; + vscale *= 0.5f; + scalex = hscale; + scaley = vscale; + scalez = hscale; if (duration > 0.0 && tics >= 0.0) // don't interpolate if instantaneous or infinite in length { @@ -2964,9 +2965,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float // -----------------+ // HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface); } // -----------------+ From 6d9512d2905ff2ad5defd06de60e044ae5a79932 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 10 Dec 2021 00:32:46 -0800 Subject: [PATCH 238/478] Do not factor roll and pitch into model rollangle Those transformations are applied separately so the model tilts in 3d space. --- src/hardware/hw_md2.c | 2 +- src/r_patch.h | 1 + src/r_patchrotation.c | 12 ++++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 0f9195a75..096d24f52 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1611,7 +1611,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } { - fixed_t anglef = AngleFixed(R_SpriteRotationAngle(&interp)); + fixed_t anglef = AngleFixed(R_ModelRotationAngle(&interp)); p.rollangle = 0.0f; diff --git a/src/r_patch.h b/src/r_patch.h index 27f7bddb6..a0ab3e75a 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -39,6 +39,7 @@ patch_t *Patch_GetRotatedSprite( size_t frame, size_t spriteangle, boolean flip, boolean adjustfeet, void *info, INT32 rotationangle); +angle_t R_ModelRotationAngle(interpmobjstate_t *interp); angle_t R_SpriteRotationAngle(interpmobjstate_t *interp); INT32 R_GetRollAngle(angle_t rollangle); #endif diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index f9c4ec797..a17b725d6 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -19,11 +19,11 @@ fixed_t rollcosang[ROTANGLES]; fixed_t rollsinang[ROTANGLES]; -// -// R_SpriteRotationAngle -// -// Gets the rollangle for the input object. -// +angle_t R_ModelRotationAngle(interpmobjstate_t *interp) +{ + return interp->spriteroll; +} + angle_t R_SpriteRotationAngle(interpmobjstate_t *interp) { angle_t viewingAngle = R_PointToAngle(interp->x, interp->y); @@ -33,7 +33,7 @@ angle_t R_SpriteRotationAngle(interpmobjstate_t *interp) angle_t rollOrPitch = FixedMul(interp->pitch, pitchMul) + FixedMul(interp->roll, rollMul); - return (rollOrPitch + interp->spriteroll); + return (rollOrPitch + R_ModelRotationAngle(interp)); } INT32 R_GetRollAngle(angle_t rollangle) From a71a7f271036487eb608ef7196c0fe3b3575d321 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 25 Oct 2022 02:36:35 -0700 Subject: [PATCH 239/478] Support spritexoffset/spriteyoffset for 3D models --- src/hardware/hw_main.c | 2 +- src/hardware/hw_main.h | 1 + src/hardware/hw_md2.c | 22 ++++++++++++++-------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8c1bc09e0..cb519877c 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -140,7 +140,7 @@ static fixed_t dup_viewx, dup_viewy, dup_viewz; static angle_t dup_viewangle; static float gl_viewx, gl_viewy, gl_viewz; -static float gl_viewsin, gl_viewcos; +float gl_viewsin, gl_viewcos; // Maybe not necessary with the new T&L code (needs to be checked!) static float gl_viewludsin, gl_viewludcos; // look up down kik test diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4a1b412fc..9450ca2c5 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -115,6 +115,7 @@ extern float gl_viewwindowx, gl_basewindowcentery; // BP: big hack for a test in lighting ref : 1249753487AB extern fixed_t *hwbbox; extern FTransform atransform; +extern float gl_viewsin, gl_viewcos; // Render stats diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 096d24f52..f0108969f 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1347,7 +1347,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) spritedef_t *sprdef; spriteframe_t *sprframe; INT32 mod; - float finalscale; interpmobjstate_t interp; if (R_UsingFrameInterpolation() && !paused) @@ -1451,7 +1450,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } //HWD.pfnSetBlend(blend); // This seems to actually break translucency? - finalscale = md2->scale; //Hurdler: arf, I don't like that implementation at all... too much crappy if (gpatch && hwrPatch && hwrPatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture @@ -1635,17 +1633,25 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.anglez = FIXED_TO_FLOAT(AngleFixed(interp.pitch)); p.anglex = FIXED_TO_FLOAT(AngleFixed(interp.roll)); - // SRB2CBTODO: MD2 scaling support - finalscale *= FIXED_TO_FLOAT(interp.scale); - p.flip = atransform.flip; p.mirror = atransform.mirror; HWD.pfnSetShader(SHADER_MODEL); // model shader { - float xs = finalscale * FIXED_TO_FLOAT(spr->mobj->spritexscale); - float ys = finalscale * FIXED_TO_FLOAT(spr->mobj->spriteyscale); - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, xs, ys, flip, hflip, &Surf); + float this_scale = FIXED_TO_FLOAT(interp.scale); + + float xs = this_scale * FIXED_TO_FLOAT(interp.spritexscale); + float ys = this_scale * FIXED_TO_FLOAT(interp.spriteyscale); + + float ox = xs * FIXED_TO_FLOAT(interp.spritexoffset); + float oy = ys * FIXED_TO_FLOAT(interp.spriteyoffset); + + // offset perpendicular to the camera angle + p.x -= ox * gl_viewsin; + p.y += ox * gl_viewcos; + p.z += oy; + + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, hflip, &Surf); } } From bc9e7c146126bdd65f79c8fb5f37930d41b2816e Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 25 Oct 2022 22:20:20 -0700 Subject: [PATCH 240/478] Disable sprite/model rotation on slopes for now --- src/hardware/hw_md2.c | 5 +++++ src/p_mobj.c | 5 +++++ src/r_patchrotation.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index f0108969f..fca3af217 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1630,8 +1630,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } } +#if 0 p.anglez = FIXED_TO_FLOAT(AngleFixed(interp.pitch)); p.anglex = FIXED_TO_FLOAT(AngleFixed(interp.roll)); +#else + p.anglez = 0.f; + p.anglex = 0.f; +#endif p.flip = atransform.flip; p.mirror = atransform.mirror; diff --git a/src/p_mobj.c b/src/p_mobj.c index 9a889d516..a25b5643b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1556,6 +1556,7 @@ void P_CheckGravity(mobj_t *mo, boolean affect) // void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) { +#if 0 if (slope) { fixed_t tempz = slope->normal.z; @@ -1569,6 +1570,10 @@ void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) { mo->pitch = mo->roll = 0; } +#else + (void)mo; + (void)slope; +#endif } #define STOPSPEED (FRACUNIT) diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index a17b725d6..b0cbeaa42 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -26,6 +26,7 @@ angle_t R_ModelRotationAngle(interpmobjstate_t *interp) angle_t R_SpriteRotationAngle(interpmobjstate_t *interp) { +#if 0 angle_t viewingAngle = R_PointToAngle(interp->x, interp->y); fixed_t pitchMul = -FINESINE(viewingAngle >> ANGLETOFINESHIFT); @@ -34,6 +35,9 @@ angle_t R_SpriteRotationAngle(interpmobjstate_t *interp) angle_t rollOrPitch = FixedMul(interp->pitch, pitchMul) + FixedMul(interp->roll, rollMul); return (rollOrPitch + R_ModelRotationAngle(interp)); +#else + return R_ModelRotationAngle(interp); +#endif } INT32 R_GetRollAngle(angle_t rollangle) From 516e06bcba5fd9477ec951be63637eb7a0c65519 Mon Sep 17 00:00:00 2001 From: katsy <205-katsy@users.noreply.git.do.srb2.org> Date: Mon, 24 Jul 2023 09:12:05 +0000 Subject: [PATCH 241/478] Autobackup old gamedatas (resolves #1031) --- src/g_game.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/g_game.c b/src/g_game.c index b23980044..e188a772b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4372,6 +4372,17 @@ void G_LoadGameData(gamedata_t *data) { goto datacorrupt; } + + // make a backup of the old data + char currentfilename[64]; + char backupfilename[69]; + char bak[5]; + + strcpy(bak, ".bak"); + strcpy(currentfilename, gamedatafilename); + STRBUFCPY(backupfilename, strcat(currentfilename, bak)); + + FIL_WriteFile(va(pandf, srb2home, backupfilename), savebuffer, length); } else #endif From a9d0630b15293ebdb403db9da979d40b1dac9373 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Thu, 8 Jul 2021 18:07:34 -0400 Subject: [PATCH 242/478] Add lives check to Team name HUD --- src/st_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 9cac145a7..3e1638370 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -884,7 +884,7 @@ static void ST_drawLivesArea(void) } } // Team name - else if (G_GametypeHasTeams()) + else if (G_GametypeHasTeams() && !(gametyperules & GTR_LIVES)) { if (stplyr->ctfteam == 1) { From 84e448eb63a3d805cc9ac98446461975b339378f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 24 Jul 2023 06:09:50 -0400 Subject: [PATCH 243/478] Improve handling of team lives labels The lives counter check is now always run, and team name is displayed in its place when its false. --- src/st_stuff.c | 73 +++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 3e1638370..c6e6befc6 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -815,7 +815,7 @@ static inline void ST_drawRings(void) static void ST_drawLivesArea(void) { INT32 v_colmap = V_YELLOWMAP, livescount; - boolean notgreyedout; + boolean notgreyedout = false; if (!stplyr->skincolor) return; // Just joined a server, skin isn't loaded yet! @@ -868,39 +868,36 @@ static void ST_drawLivesArea(void) if (metalrecording) { if (((2*leveltime)/TICRATE) & 1) + { V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC"); + } } // Spectator else if (stplyr->spectator) + { v_colmap = V_GRAYMAP; - // Tag - else if (gametyperules & GTR_TAG) - { - if (stplyr->pflags & PF_TAGIT) - { - V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "IT!"); - v_colmap = V_ORANGEMAP; - } } - // Team name - else if (G_GametypeHasTeams() && !(gametyperules & GTR_LIVES)) - { - if (stplyr->ctfteam == 1) - { - V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "RED"); - v_colmap = V_REDMAP; - } - else if (stplyr->ctfteam == 2) - { - V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "BLUE"); - v_colmap = V_BLUEMAP; - } - } - // Lives number else { - boolean candrawlives = true; + boolean candrawlives = false; + + // Set the player's name color. + if (G_TagGametype() && (stplyr->pflags & PF_TAGIT)) + { + v_colmap = V_ORANGEMAP; + } + else if (G_GametypeHasTeams()) + { + if (stplyr->ctfteam == 1) + { + v_colmap = V_REDMAP; + } + else if (stplyr->ctfteam == 2) + { + v_colmap = V_BLUEMAP; + } + } // Co-op and Competition, normal life counter if (G_GametypeUsesLives()) @@ -936,12 +933,15 @@ static void ST_drawLivesArea(void) livescount = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives); notgreyedout = true; } + + candrawlives = true; } // Infinity symbol (Race) else if (G_PlatformGametype() && !(gametyperules & GTR_LIVES)) { livescount = INFLIVES; notgreyedout = true; + candrawlives = true; } // Otherwise nothing, sorry. // Special Stages keep not showing lives, @@ -950,8 +950,6 @@ static void ST_drawLivesArea(void) // cannot show up because Special Stages // still have the GTR_LIVES gametype rule // by default. - else - candrawlives = false; // Draw the lives counter here. if (candrawlives) @@ -959,8 +957,10 @@ static void ST_drawLivesArea(void) // x V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex); if (livescount == INFLIVES) + { V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8, '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); + } else { if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)) && !(stplyr->pflags & PF_FINISHED)) @@ -971,6 +971,25 @@ static void ST_drawLivesArea(void) hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount)); } } + else + { + // Draw team name instead of lives, if possible. + if (G_TagGametype() && (stplyr->pflags & PF_TAGIT)) + { + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "IT!"); + } + else if (G_GametypeHasTeams()) + { + if (stplyr->ctfteam == 1) + { + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "RED"); + } + else if (stplyr->ctfteam == 2) + { + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "BLUE"); + } + } + } #undef ST_drawLivesX } From 86b4f9361001ea1b6ba7c2d0966932e4fd11473c Mon Sep 17 00:00:00 2001 From: spherallic Date: Wed, 2 Mar 2022 23:47:15 +0100 Subject: [PATCH 244/478] Allow obtaining ring, time & grade emblems in regular SP gameplay. --- src/d_netcmd.c | 2 +- src/d_player.h | 3 +- src/g_game.c | 354 ++++++++++++++++++++++++++------------------ src/g_game.h | 3 +- src/lua_playerlib.c | 8 + src/m_cond.c | 2 +- src/m_cond.h | 2 +- src/p_saveg.c | 61 ++++++-- src/p_setup.c | 2 +- src/p_user.c | 12 +- 10 files changed, 279 insertions(+), 170 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 90078f062..52790b2ce 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2339,7 +2339,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum) } for (i = 0; i < MAXPLAYERS; i++) - players[i].score = 0; + players[i].score = players[i].recordscore = 0; CONS_Printf(M_GetText("Scores have been reset by the server.\n")); } diff --git a/src/d_player.h b/src/d_player.h index f407c29e9..7ad5b9f81 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -453,7 +453,8 @@ typedef struct player_s INT32 skin; UINT32 availabilities; - UINT32 score; // player score + UINT32 score; // player score (total) + UINT32 recordscore; // player score (per life / map) fixed_t dashspeed; // dashing speed fixed_t normalspeed; // Normal ground diff --git a/src/g_game.c b/src/g_game.c index 571756503..81942f462 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -519,140 +519,154 @@ UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data) } // For easy adding of NiGHTS records -void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare) +void G_AddTempNightsRecords(player_t *player, UINT32 pscore, tic_t ptime, UINT8 mare) { - ntemprecords.score[mare] = pscore; - ntemprecords.grade[mare] = P_GetGrade(pscore, gamemap, mare - 1); - ntemprecords.time[mare] = ptime; + const UINT8 playerID = player - players; + + I_Assert(player != NULL); + + ntemprecords[playerID].score[mare] = pscore; + ntemprecords[playerID].grade[mare] = P_GetGrade(pscore, gamemap, mare - 1); + ntemprecords[playerID].time[mare] = ptime; // Update nummares // Note that mare "0" is overall, mare "1" is the first real mare - if (ntemprecords.nummares < mare) - ntemprecords.nummares = mare; + if (ntemprecords[playerID].nummares < mare) + ntemprecords[playerID].nummares = mare; } // -// G_UpdateRecordReplays +// G_SetMainRecords // // Update replay files/data, etc. for Record Attack // See G_SetNightsRecords for NiGHTS Attack. // -static void G_UpdateRecordReplays(gamedata_t *data) +static void G_SetMainRecords(gamedata_t *data, player_t *player) { - const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; - char *gpath; - char lastdemo[256], bestdemo[256]; UINT8 earnedEmblems; + I_Assert(player != NULL); + // Record new best time if (!data->mainrecords[gamemap-1]) G_AllocMainRecordData(gamemap-1, data); - if (players[consoleplayer].score > data->mainrecords[gamemap-1]->score) - data->mainrecords[gamemap-1]->score = players[consoleplayer].score; + if (player->recordscore > data->mainrecords[gamemap-1]->score) + data->mainrecords[gamemap-1]->score = player->recordscore; - if ((data->mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < data->mainrecords[gamemap-1]->time)) - data->mainrecords[gamemap-1]->time = players[consoleplayer].realtime; + if ((data->mainrecords[gamemap-1]->time == 0) || (player->realtime < data->mainrecords[gamemap-1]->time)) + data->mainrecords[gamemap-1]->time = player->realtime; - if ((UINT16)(players[consoleplayer].rings) > data->mainrecords[gamemap-1]->rings) - data->mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); + if ((UINT16)(player->rings) > data->mainrecords[gamemap-1]->rings) + data->mainrecords[gamemap-1]->rings = (UINT16)(player->rings); - // Save demo! - bestdemo[255] = '\0'; - lastdemo[255] = '\0'; - G_SetDemoTime(players[consoleplayer].realtime, players[consoleplayer].score, (UINT16)(players[consoleplayer].rings)); - G_CheckDemoStatus(); - - I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); - I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); - - if ((gpath = malloc(glen)) == NULL) - I_Error("Out of memory for replay filepath\n"); - - sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); - - if (FIL_FileExists(lastdemo)) + if (modeattacking) { - UINT8 *buf; - size_t len = FIL_ReadFile(lastdemo, &buf); + const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; + char *gpath; + char lastdemo[256], bestdemo[256]; - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name); - if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) - { // Better time, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); + // Save demo! + bestdemo[255] = '\0'; + lastdemo[255] = '\0'; + G_SetDemoTime(player->realtime, player->recordscore, (UINT16)(player->rings)); + G_CheckDemoStatus(); + + I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); + I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); + + if ((gpath = malloc(glen)) == NULL) + I_Error("Out of memory for replay filepath\n"); + + sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); + + if (FIL_FileExists(lastdemo)) + { + UINT8 *buf; + size_t len = FIL_ReadFile(lastdemo, &buf); + + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) + { // Better time, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); + } + + snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) + { // Better score, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo); + } + + snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<2))) + { // Better rings, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW MOST RINGS!"), M_GetText("Saved replay as"), bestdemo); + } + + //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); + + Z_Free(buf); } - - snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); - if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) - { // Better score, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo); - } - - snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1].name); - if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<2))) - { // Better rings, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW MOST RINGS!"), M_GetText("Saved replay as"), bestdemo); - } - - //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); - - Z_Free(buf); + free(gpath); } - free(gpath); // Check emblems when level data is updated if ((earnedEmblems = M_CheckLevelEmblems(data))) + { CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); + } // Update timeattack menu's replay availability. Nextmap_OnChange(); } -void G_SetNightsRecords(gamedata_t *data) +static void G_SetNightsRecords(gamedata_t *data, player_t *player) { - INT32 i; + nightsdata_t *const ntemprecord = &ntemprecords[player - players]; UINT32 totalscore = 0; tic_t totaltime = 0; + INT32 i; + UINT8 earnedEmblems; - const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; - char *gpath; - char lastdemo[256], bestdemo[256]; - - if (!ntemprecords.nummares) + if (!ntemprecord->nummares) + { return; + } // Set overall { UINT8 totalrank = 0, realrank = 0; - for (i = 1; i <= ntemprecords.nummares; ++i) + for (i = 1; i <= ntemprecord->nummares; ++i) { - totalscore += ntemprecords.score[i]; - totalrank += ntemprecords.grade[i]; - totaltime += ntemprecords.time[i]; + totalscore += ntemprecord->score[i]; + totalrank += ntemprecord->grade[i]; + totaltime += ntemprecord->time[i]; } // Determine overall grade - realrank = (UINT8)((FixedDiv((fixed_t)totalrank << FRACBITS, ntemprecords.nummares << FRACBITS) + (FRACUNIT/2)) >> FRACBITS); + realrank = (UINT8)((FixedDiv((fixed_t)totalrank << FRACBITS, ntemprecord->nummares << FRACBITS) + (FRACUNIT/2)) >> FRACBITS); // You need ALL rainbow As to get a rainbow A overall - if (realrank == GRADE_S && (totalrank / ntemprecords.nummares) != GRADE_S) + if (realrank == GRADE_S && (totalrank / ntemprecord->nummares) != GRADE_S) + { realrank = GRADE_A; + } - ntemprecords.score[0] = totalscore; - ntemprecords.grade[0] = realrank; - ntemprecords.time[0] = totaltime; + ntemprecord->score[0] = totalscore; + ntemprecord->grade[0] = realrank; + ntemprecord->time[0] = totaltime; } // Now take all temp records and put them in the actual records @@ -660,71 +674,85 @@ void G_SetNightsRecords(gamedata_t *data) nightsdata_t *maprecords; if (!data->nightsrecords[gamemap-1]) + { G_AllocNightsRecordData(gamemap-1, data); + } + maprecords = data->nightsrecords[gamemap-1]; - if (maprecords->nummares != ntemprecords.nummares) - maprecords->nummares = ntemprecords.nummares; - - for (i = 0; i < ntemprecords.nummares + 1; ++i) + if (maprecords->nummares != ntemprecord->nummares) { - if (maprecords->score[i] < ntemprecords.score[i]) - maprecords->score[i] = ntemprecords.score[i]; - if (maprecords->grade[i] < ntemprecords.grade[i]) - maprecords->grade[i] = ntemprecords.grade[i]; - if (!maprecords->time[i] || maprecords->time[i] > ntemprecords.time[i]) - maprecords->time[i] = ntemprecords.time[i]; + maprecords->nummares = ntemprecord->nummares; + } + + for (i = 0; i < ntemprecord->nummares + 1; ++i) + { + if (maprecords->score[i] < ntemprecord->score[i]) + maprecords->score[i] = ntemprecord->score[i]; + if (maprecords->grade[i] < ntemprecord->grade[i]) + maprecords->grade[i] = ntemprecord->grade[i]; + if (!maprecords->time[i] || maprecords->time[i] > ntemprecord->time[i]) + maprecords->time[i] = ntemprecord->time[i]; } } - memset(&ntemprecords, 0, sizeof(nightsdata_t)); + memset(&ntemprecords[player - players], 0, sizeof(nightsdata_t)); - // Save demo! - bestdemo[255] = '\0'; - lastdemo[255] = '\0'; - G_SetDemoTime(totaltime, totalscore, 0); - G_CheckDemoStatus(); - - I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); - I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); - - if ((gpath = malloc(glen)) == NULL) - I_Error("Out of memory for replay filepath\n"); - - sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); - - if (FIL_FileExists(lastdemo)) + if (modeattacking) { - UINT8 *buf; - size_t len = FIL_ReadFile(lastdemo, &buf); + const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; + char *gpath; + char lastdemo[256], bestdemo[256]; - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);; - if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) - { // Better time, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); + // Save demo! + bestdemo[255] = '\0'; + lastdemo[255] = '\0'; + G_SetDemoTime(totaltime, totalscore, 0); + G_CheckDemoStatus(); + + I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); + I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); + + if ((gpath = malloc(glen)) == NULL) + I_Error("Out of memory for replay filepath\n"); + + sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); + + if (FIL_FileExists(lastdemo)) + { + UINT8 *buf; + size_t len = FIL_ReadFile(lastdemo, &buf); + + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);; + if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) + { // Better time, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); + } + + snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) + { // Better score, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo); + } + + //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); + + Z_Free(buf); } - - snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); - if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) - { // Better score, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo); - } - - //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); - - Z_Free(buf); + free(gpath); } - free(gpath); if ((earnedEmblems = M_CheckLevelEmblems(data))) + { CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for NiGHTS records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); + } // If the mare count changed, this will update the score display Nextmap_OnChange(); @@ -2287,7 +2315,7 @@ void G_Ticker(boolean run) p->lives = startinglivesbalance[0]; p->continues = 1; - p->score = 0; + p->score = p->recordscore = 0; // The latter two should clear by themselves, but just in case p->pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS); @@ -2490,6 +2518,7 @@ static inline void G_PlayerFinishLevel(INT32 player) memset(p->powers, 0, sizeof (p->powers)); p->ringweapons = 0; + p->recordscore = 0; p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility P_FlashPal(p, 0, 0); // Resets @@ -2513,6 +2542,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) { player_t *p; INT32 score; + INT32 recordscore; INT32 lives; INT32 continues; fixed_t camerascale; @@ -3165,6 +3195,7 @@ void G_DoReborn(INT32 playernum) { if (!playeringame[i]) continue; + players[i].recordscore = 0; players[i].starpostscale = 0; players[i].starpostangle = 0; players[i].starposttime = 0; @@ -3844,15 +3875,16 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) // // G_UpdateVisited // -static void G_UpdateVisited(gamedata_t *data, boolean silent) +static void G_UpdateVisited(gamedata_t *data, player_t *player, boolean silent) { - boolean spec = G_IsSpecialStage(gamemap); // Update visitation flags? if (!demoplayback && G_CoopGametype() // Campaign mode && !stagefailed) // Did not fail the stage { UINT8 earnedEmblems; + UINT16 totalrings = 0; + INT32 i; // Update visitation flags data->mapvisited[gamemap-1] |= MV_BEATEN; @@ -3861,36 +3893,62 @@ static void G_UpdateVisited(gamedata_t *data, boolean silent) if (ultimatemode) data->mapvisited[gamemap-1] |= MV_ULTIMATE; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + { + continue; + } + + totalrings += players[i].rings; + } + // may seem incorrect but IS possible in what the main game uses as mp special stages, and nummaprings will be -1 in NiGHTS - if (nummaprings > 0 && players[consoleplayer].rings >= nummaprings) + if (nummaprings > 0 && totalrings >= nummaprings) { data->mapvisited[gamemap-1] |= MV_PERFECT; if (modeattacking) data->mapvisited[gamemap-1] |= MV_PERFECTRA; } - if (!spec) + if (!G_IsSpecialStage(gamemap)) { // not available to special stages because they can only really be done in one order in an unmodified game, so impossible for first six and trivial for seventh if (ALL7EMERALDS(emeralds)) data->mapvisited[gamemap-1] |= MV_ALLEMERALDS; } + if ((earnedEmblems = M_CompletionEmblems(data)) && !silent) + { + CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); + } + if (silent) { - if (modeattacking) - M_CheckLevelEmblems(data); + M_CheckLevelEmblems(data); } else { - if (modeattacking == ATTACKING_RECORD) - G_UpdateRecordReplays(data); - else if (modeattacking == ATTACKING_NIGHTS) - G_SetNightsRecords(data); + if (mapheaderinfo[gamemap-1]->menuflags & LF2_RECORDATTACK) + G_SetMainRecords(data, player); + else if (mapheaderinfo[gamemap-1]->menuflags & LF2_NIGHTSATTACK) + G_SetNightsRecords(data, player); } + } +} - if ((earnedEmblems = M_CompletionEmblems(data)) && !silent) - CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); +static void G_UpdateAllVisited(void) +{ + // Update server + G_UpdateVisited(serverGamedata, &players[serverplayer], true); + + // Update client + G_UpdateVisited(clientGamedata, &players[consoleplayer], false); + + if (splitscreen) + { + // Allow P2 to get emblems too, why not :) + G_UpdateVisited(clientGamedata, &players[secondarydisplayplayer], false); } } @@ -3914,6 +3972,9 @@ static boolean CanSaveLevel(INT32 mapnum) static void G_HandleSaveLevel(void) { + // Update records & emblems + G_UpdateAllVisited(); + // do this before running the intermission or custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c if (nextmap >= 1100-1) { @@ -4092,8 +4153,6 @@ static void G_DoCompleted(void) if ((skipstats && !modeattacking) || (modeattacking && stagefailed) || (intertype == int_none)) { - G_UpdateVisited(serverGamedata, true); - G_UpdateVisited(clientGamedata, false); G_HandleSaveLevel(); G_AfterIntermission(); } @@ -4102,8 +4161,6 @@ static void G_DoCompleted(void) G_SetGamestate(GS_INTERMISSION); Y_StartIntermission(); Y_LoadIntermissionData(); - G_UpdateVisited(serverGamedata, true); - G_UpdateVisited(clientGamedata, false); G_HandleSaveLevel(); } } @@ -4992,6 +5049,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean players[i].playerstate = PST_REBORN; players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0; players[i].starpostx = players[i].starposty = players[i].starpostz = 0; + players[i].recordscore = 0; if (netgame || multiplayer) { diff --git a/src/g_game.h b/src/g_game.h index 6cda7ca9c..a8c285f79 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -260,8 +260,7 @@ UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare, gamedata_t *data); tic_t G_GetBestNightsTime(INT16 map, UINT8 mare, gamedata_t *data); UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data); -void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare); -void G_SetNightsRecords(gamedata_t *data); +void G_AddTempNightsRecords(player_t *player, UINT32 pscore, tic_t ptime, UINT8 mare); FUNCMATH INT32 G_TicsToHours(tic_t tics); FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index c056be463..055acfd80 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -114,6 +114,7 @@ enum player_e player_skin, player_availabilities, player_score, + player_recordscore, player_dashspeed, player_normalspeed, player_runspeed, @@ -260,6 +261,7 @@ static const char *const player_opt[] = { "skin", "availabilities", "score", + "recordscore", "dashspeed", "normalspeed", "runspeed", @@ -495,6 +497,9 @@ static int player_get(lua_State *L) case player_score: lua_pushinteger(L, plr->score); break; + case player_recordscore: + lua_pushinteger(L, plr->recordscore); + break; case player_dashspeed: lua_pushfixed(L, plr->dashspeed); break; @@ -957,6 +962,9 @@ static int player_set(lua_State *L) case player_score: plr->score = (UINT32)luaL_checkinteger(L, 3); break; + case player_recordscore: + plr->recordscore = (UINT32)luaL_checkinteger(L, 3); + break; case player_dashspeed: plr->dashspeed = luaL_checkfixed(L, 3); break; diff --git a/src/m_cond.c b/src/m_cond.c index a54988f67..b21778c69 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -45,7 +45,7 @@ INT32 numemblems = 0; INT32 numextraemblems = 0; // Temporary holding place for nights data for the current map -nightsdata_t ntemprecords; +nightsdata_t ntemprecords[MAXPLAYERS]; // Create a new gamedata_t, for start-up gamedata_t *M_NewGameDataStruct(void) diff --git a/src/m_cond.h b/src/m_cond.h index 95c3e1ebe..2be8d564b 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -181,7 +181,7 @@ typedef struct #define MV_MAX 63 // used in gamedata check, update whenever MV's are added // Temporary holding place for nights data for the current map -extern nightsdata_t ntemprecords; +extern nightsdata_t ntemprecords[MAXPLAYERS]; // GAMEDATA STRUCTURE // Everything that would get saved in gamedata.dat diff --git a/src/p_saveg.c b/src/p_saveg.c index 8eac91105..3565d0125 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -179,6 +179,7 @@ static void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].skin); WRITEUINT32(save_p, players[i].availabilities); WRITEUINT32(save_p, players[i].score); + WRITEUINT32(save_p, players[i].recordscore); WRITEFIXED(save_p, players[i].dashspeed); WRITESINT8(save_p, players[i].lives); WRITESINT8(save_p, players[i].continues); @@ -407,6 +408,7 @@ static void P_NetUnArchivePlayers(void) players[i].skin = READINT32(save_p); players[i].availabilities = READUINT32(save_p); players[i].score = READUINT32(save_p); + players[i].recordscore = READUINT32(save_p); players[i].dashspeed = READFIXED(save_p); // dashing speed players[i].lives = READSINT8(save_p); players[i].continues = READSINT8(save_p); // continues that player has acquired @@ -4342,8 +4344,6 @@ static void P_NetArchiveMisc(boolean resending) WRITEUINT32(save_p, hidetime); - WRITEUINT32(save_p, unlocktriggers); - // Is it paused? if (paused) WRITEUINT8(save_p, 0x2f); @@ -4442,8 +4442,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) hidetime = READUINT32(save_p); - unlocktriggers = READUINT32(save_p); - // Is it paused? if (READUINT8(save_p) == 0x2f) paused = true; @@ -4451,7 +4449,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) return true; } - static inline void P_NetArchiveEmblems(void) { gamedata_t *data = serverGamedata; @@ -4550,6 +4547,27 @@ static inline void P_NetArchiveEmblems(void) WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); } } + + // Mid-map stuff + WRITEUINT32(save_p, unlocktriggers); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!ntemprecords[i].nummares) + { + WRITEUINT8(save_p, 0); + continue; + } + + WRITEUINT8(save_p, ntemprecords[i].nummares); + + for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare) + { + WRITEUINT32(save_p, ntemprecords[i].score[curmare]); + WRITEUINT8(save_p, ntemprecords[i].grade[curmare]); + WRITEUINT32(save_p, ntemprecords[i].time[curmare]); + } + } } static inline void P_NetUnArchiveEmblems(void) @@ -4569,9 +4587,9 @@ static inline void P_NetUnArchiveEmblems(void) savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. if (numemblems != READINT32(save_p)) - I_Error("numemblems mismatch"); + I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)"); if (numextraemblems != READINT32(save_p)) - I_Error("numextraemblems mismatch"); + I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)"); // This shouldn't happen, but if something really fucked up happens and you transfer // the SERVER player's gamedata over your own CLIENT gamedata, @@ -4590,7 +4608,7 @@ static inline void P_NetUnArchiveEmblems(void) // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) - I_Error("Bad $$$.sav dearchiving Emblems"); + I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)"); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) @@ -4634,7 +4652,7 @@ static inline void P_NetUnArchiveEmblems(void) recrings = READUINT16(save_p); if (recrings > 10000 || recscore > MAXSCORE) - I_Error("Bad $$$.sav dearchiving Emblems"); + I_Error("Bad $$$.sav dearchiving Emblems (invalid score)"); if (recscore || rectime || recrings) { @@ -4661,12 +4679,35 @@ static inline void P_NetUnArchiveEmblems(void) if (data->nightsrecords[i]->grade[curmare] > GRADE_S) { - I_Error("Bad $$$.sav dearchiving Emblems"); + I_Error("Bad $$$.sav dearchiving Emblems (invalid grade)"); } } data->nightsrecords[i]->nummares = recmares; } + + // Mid-map stuff + unlocktriggers = READUINT32(save_p); + + for (i = 0; i < MAXPLAYERS; ++i) + { + if ((recmares = READUINT8(save_p)) == 0) + continue; + + for (curmare = 0; curmare < (recmares+1); ++curmare) + { + ntemprecords[i].score[curmare] = READUINT32(save_p); + ntemprecords[i].grade[curmare] = READUINT8(save_p); + ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p); + + if (ntemprecords[i].grade[curmare] > GRADE_S) + { + I_Error("Bad $$$.sav dearchiving Emblems (invalid temp grade)"); + } + } + + ntemprecords[i].nummares = recmares; + } } static inline void P_ArchiveLuabanksAndConsistency(void) diff --git a/src/p_setup.c b/src/p_setup.c index bfb70751d..051853017 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -6985,7 +6985,7 @@ static void P_InitLevelSettings(void) stagefailed = G_IsSpecialStage(gamemap); // Reset temporary record data - memset(&ntemprecords, 0, sizeof(nightsdata_t)); + memset(&ntemprecords, 0, sizeof(ntemprecords)); // earthquake camera memset(&quake,0,sizeof(struct quake)); diff --git a/src/p_user.c b/src/p_user.c index b89552673..a0de50b8f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -882,8 +882,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) } // Add score to leaderboards now - if (!(netgame||multiplayer) && P_IsLocalPlayer(&players[i])) - G_AddTempNightsRecords(players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1); + G_AddTempNightsRecords(player, players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1); // transfer scores anyway players[i].totalmarescore += players[i].marescore; @@ -909,8 +908,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->finishedrings = (INT16)(player->rings); // Add score to temp leaderboards - if (!(netgame||multiplayer) && P_IsLocalPlayer(player)) - G_AddTempNightsRecords(player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1)); + G_AddTempNightsRecords(player, player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1)); // Starting a new mare, transfer scores player->totalmarescore += player->marescore; @@ -1440,6 +1438,10 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) if (player->score > MAXSCORE) player->score = MAXSCORE; + player->recordscore += amount; + if (player->recordscore > MAXSCORE) + player->recordscore = MAXSCORE; + // check for extra lives every 50000 pts if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametyperules & GTR_LIVES)) { @@ -11732,7 +11734,7 @@ void P_PlayerThink(player_t *player) if (player->spectator) { if (!(gametyperules & GTR_CAMPAIGN)) - player->score = 0; + player->score = player->recordscore = 0; } else if ((netgame || multiplayer) && player->lives <= 0 && !G_CoopGametype()) { From 8bddf0f097a2886a5edf642acca3aa9ab304626d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Mon, 24 Jul 2023 17:12:24 +0200 Subject: [PATCH 245/478] fixup! fixup! fixup! Fix build errors when building without SDL --- src/sdl/Srb2SDL-vc10.vcxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index c20265ed1..0b95cd0b2 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -259,7 +259,7 @@ - + @@ -424,7 +424,7 @@ - + @@ -556,4 +556,4 @@ - \ No newline at end of file + From b36ca89e1646a370fd3be933ff066ddbf1fd60b8 Mon Sep 17 00:00:00 2001 From: Jisk Date: Mon, 24 Jul 2023 18:00:31 +0000 Subject: [PATCH 246/478] Port player.ping from SRB2Kart --- src/lua_playerlib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f76ec1689..ae3c06d31 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -222,6 +222,7 @@ enum player_e player_blocked, player_jointime, player_quittime, + player_ping, #ifdef HWRENDER player_fovadd, #endif @@ -368,6 +369,7 @@ static const char *const player_opt[] = { "blocked", "jointime", "quittime", + "ping", #ifdef HWRENDER "fovadd", #endif @@ -819,6 +821,9 @@ static int player_get(lua_State *L) case player_quittime: lua_pushinteger(L, plr->quittime); break; + case player_ping: + lua_pushinteger(L, playerpingtable[plr - players]); + break; #ifdef HWRENDER case player_fovadd: lua_pushfixed(L, plr->fovadd); From 4212035729c11197f2502b6f50f1eb4e7bf17b89 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Mon, 24 Jul 2023 21:44:53 -0500 Subject: [PATCH 247/478] Fix errors due to declaring variables in switch bodies --- src/lua_maplib.c | 2 ++ src/lua_mobjlib.c | 2 ++ src/lua_playerlib.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 568a99b68..3d95cdb75 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2822,6 +2822,7 @@ static int mapheaderinfo_get(lua_State *L) break; // TODO add support for reading numGradedMares and grades default: + { // Read custom vars now // (note: don't include the "LUA." in your lua scripts!) UINT8 j = 0; @@ -2832,6 +2833,7 @@ static int mapheaderinfo_get(lua_State *L) else lua_pushnil(L); } + } return 1; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 404af016a..851c569d2 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1043,11 +1043,13 @@ static int mapthing_set(lua_State *L) mt->z = (INT16)luaL_checkinteger(L, 3); break; case mapthing_extrainfo: + { INT32 extrainfo = luaL_checkinteger(L, 3); if (extrainfo & ~15) return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); mt->extrainfo = (UINT8)extrainfo; break; + } case mapthing_tag: Tag_FSet(&mt->tags, (INT16)luaL_checkinteger(L, 3)); break; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f0fa2ed94..510e481e6 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1297,6 +1297,7 @@ static int player_set(lua_State *L) break; } case player_awayviewtics: + { INT32 tics = (INT32)luaL_checkinteger(L, 3); if (tics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!! P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now. @@ -1308,6 +1309,7 @@ static int player_set(lua_State *L) } plr->awayviewtics = tics; break; + } case player_awayviewaiming: plr->awayviewaiming = luaL_checkangle(L, 3); break; From 1a2f66acd9b14b4c64a6a4f6db049d097ac9c852 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 25 Jul 2023 06:47:32 -0400 Subject: [PATCH 248/478] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cd828dc11..2b4d9d2fb 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,4 @@ Win32_LIB_ASM_Release /make /bin /build -/build.* +/build/* From 77576c3c5d526651074ec6b9f4c664671e0ab273 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 25 Jul 2023 08:40:36 -0400 Subject: [PATCH 249/478] Allow Record Attack in modified games Replays now store & validate the add-on list before loading them. Custom characters can now be allowed in Record Attack. --- src/d_netcmd.c | 19 ++- src/f_finale.c | 1 + src/g_demo.c | 387 ++++++++++++++++++++++++++++++++++++++++++++++--- src/g_demo.h | 22 +++ src/m_menu.c | 93 ++++++++++-- 5 files changed, 487 insertions(+), 35 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 72d020c22..45a394eff 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1643,9 +1643,14 @@ static void Command_Playdemo_f(void) { char name[256]; - if (COM_Argc() != 2) + if (COM_Argc() < 2) { - CONS_Printf(M_GetText("playdemo : playback a demo\n")); + CONS_Printf("playdemo [-addfiles / -force]:\n"); + CONS_Printf(M_GetText( + "Play back a demo file. The full path from your SRB2 directory must be given.\n\n" + + "* With \"-addfiles\", any required files are added from a list contained within the demo file.\n" + "* With \"-force\", the demo is played even if the necessary files have not been added.\n")); return; } @@ -1667,6 +1672,16 @@ static void Command_Playdemo_f(void) CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name); + demofileoverride = DFILE_OVERRIDE_NONE; + if (strcmp(COM_Argv(2), "-addfiles") == 0) + { + demofileoverride = DFILE_OVERRIDE_LOAD; + } + else if (strcmp(COM_Argv(2), "-force") == 0) + { + demofileoverride = DFILE_OVERRIDE_SKIP; + } + // Internal if no extension, external if one exists // If external, convert the file name to a path in SRB2's home directory if (FIL_CheckExtension(name)) diff --git a/src/f_finale.c b/src/f_finale.c index e59b43472..d03795dc4 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -3509,6 +3509,7 @@ void F_TitleScreenTicker(boolean run) } titledemo = true; + demofileoverride = DFILE_OVERRIDE_NONE; G_DoPlayDemo(dname); } } diff --git a/src/g_demo.c b/src/g_demo.c index 0403da16d..230f6da2d 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -39,6 +39,7 @@ #include "v_video.h" #include "lua_hook.h" #include "md5.h" // demo checksums +#include "d_netfil.h" // G_CheckDemoExtraFiles boolean timingdemo; // if true, exit with report on completion boolean nodrawers; // for comparative timing purposes @@ -49,6 +50,7 @@ static char demoname[64]; boolean demorecording; boolean demoplayback; boolean titledemo; // Title Screen demo can be cancelled by any key +demo_file_override_e demofileoverride; static UINT8 *demobuffer = NULL; static UINT8 *demo_p, *demotime_p; static UINT8 *demoend; @@ -95,7 +97,7 @@ demoghost *ghosts = NULL; // DEMO RECORDING // -#define DEMOVERSION 0x000f +#define DEMOVERSION 0x0010 #define DEMOHEADER "\xF0" "SRB2Replay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -1413,6 +1415,10 @@ void G_BeginRecording(void) char name[MAXCOLORNAME+1]; player_t *player = &players[consoleplayer]; + char *filename; + UINT8 totalfiles; + UINT8 *m; + if (demo_p) return; memset(name,0,sizeof(name)); @@ -1435,23 +1441,43 @@ void G_BeginRecording(void) M_Memcpy(demo_p, mapmd5, 16); demo_p += 16; WRITEUINT8(demo_p,demoflags); + + // file list + m = demo_p;/* file count */ + demo_p += 1; + + totalfiles = 0; + for (i = mainwads; ++i < numwadfiles; ) + { + if (wadfiles[i]->important) + { + nameonly(( filename = va("%s", wadfiles[i]->filename) )); + WRITESTRINGL(demo_p, filename, MAX_WADPATH); + WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); + + totalfiles++; + } + } + + WRITEUINT8(m, totalfiles); + switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - WRITEUINT32(demo_p,0); // score - WRITEUINT16(demo_p,0); // rings - break; - case ATTACKING_NIGHTS: // 2 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - WRITEUINT32(demo_p,0); // score - break; - default: // 3 - break; + case ATTACKING_NONE: // 0 + break; + case ATTACKING_RECORD: // 1 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + WRITEUINT32(demo_p,0); // score + WRITEUINT16(demo_p,0); // rings + break; + case ATTACKING_NIGHTS: // 2 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + WRITEUINT32(demo_p,0); // score + break; + default: // 3 + break; } WRITEUINT32(demo_p,P_GetInitSeed()); @@ -1590,6 +1616,177 @@ void G_BeginMetal(void) oldmetal.angle = mo->angle>>24; } +static void G_LoadDemoExtraFiles(UINT8 **pp) +{ + UINT8 totalfiles; + char filename[MAX_WADPATH]; + UINT8 md5sum[16]; + filestatus_t ncs; + boolean toomany = false; + boolean alreadyloaded; + UINT8 i, j; + + totalfiles = READUINT8((*pp)); + for (i = 0; i < totalfiles; ++i) + { + if (toomany) + SKIPSTRING((*pp)); + else + { + strlcpy(filename, (char *)(*pp), sizeof filename); + SKIPSTRING((*pp)); + } + READMEM((*pp), md5sum, 16); + + if (!toomany) + { + alreadyloaded = false; + + for (j = 0; j < numwadfiles; ++j) + { + if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) + { + alreadyloaded = true; + break; + } + } + + if (alreadyloaded) + continue; + + if (numwadfiles >= MAX_WADFILES) + toomany = true; + else + ncs = findfile(filename, md5sum, false); + + if (toomany) + { + CONS_Alert(CONS_WARNING, M_GetText("Too many files loaded to add anymore for demo playback\n")); + if (!CON_Ready()) + M_StartMessage(M_GetText("There are too many files loaded to add this demo's addons.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); + } + else if (ncs != FS_FOUND) + { + if (ncs == FS_NOTFOUND) + CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename); + else if (ncs == FS_MD5SUMBAD) + CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename); + else + CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename); + + if (!CON_Ready()) + M_StartMessage(M_GetText("There were errors trying to add this demo's addons. Check the console for more information.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); + } + else + { + P_AddWadFile(filename); + } + } + } +} + +static void G_SkipDemoExtraFiles(UINT8 **pp) +{ + UINT8 totalfiles; + UINT8 i; + + if (demoversion < 0x0010) + { + // demo has no file list + return; + } + + totalfiles = READUINT8((*pp)); + for (i = 0; i < totalfiles; ++i) + { + SKIPSTRING((*pp));// file name + (*pp) += 16;// md5 + } +} + +// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's. +// Enabling quick prevents filesystem checks to see if needed files are available to load. +static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) +{ + UINT8 totalfiles, filesloaded, nmusfilecount; + char filename[MAX_WADPATH]; + UINT8 md5sum[16]; + boolean toomany = false; + boolean alreadyloaded; + UINT8 i, j; + UINT8 error = DFILE_ERROR_NONE; + + if (demoversion < 0x0010) + { + // demo has no file list + return DFILE_ERROR_NONE; + } + + totalfiles = READUINT8((*pp)); + filesloaded = 0; + for (i = 0; i < totalfiles; ++i) + { + if (toomany) + SKIPSTRING((*pp)); + else + { + strlcpy(filename, (char *)(*pp), sizeof filename); + SKIPSTRING((*pp)); + } + READMEM((*pp), md5sum, 16); + + if (!toomany) + { + alreadyloaded = false; + nmusfilecount = 0; + + for (j = 0; j < numwadfiles; ++j) + { + if (wadfiles[j]->important && j > mainwads) + nmusfilecount++; + else + continue; + + if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) + { + alreadyloaded = true; + + if (i != nmusfilecount-1 && error < DFILE_ERROR_OUTOFORDER) + error |= DFILE_ERROR_OUTOFORDER; + + break; + } + } + + if (alreadyloaded) + { + filesloaded++; + continue; + } + + if (numwadfiles >= MAX_WADFILES) + error = DFILE_ERROR_CANNOTLOAD; + else if (!quick && findfile(filename, md5sum, false) != FS_FOUND) + error = DFILE_ERROR_CANNOTLOAD; + else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) + error |= DFILE_ERROR_NOTLOADED; + } else + error = DFILE_ERROR_CANNOTLOAD; + } + + // Get final file count + nmusfilecount = 0; + + for (j = 0; j < numwadfiles; ++j) + if (wadfiles[j]->important && j > mainwads) + nmusfilecount++; + + if (!error && filesloaded < nmusfilecount) + error = DFILE_ERROR_EXTRAFILES; + + return error; +} + void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings) { if (!demorecording || !demotime_p) @@ -1645,7 +1842,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 2; // gamemap p += 16; // map md5 flags = READUINT8(p); // demoflags - + G_SkipDemoExtraFiles(&p); aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK); I_Assert(aflags); if (flags & DF_RECORDATTACK) @@ -1710,6 +1907,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) p += 2; // gamemap p += 16; // mapmd5 flags = READUINT8(p); + G_SkipDemoExtraFiles(&p); if (!(flags & aflags)) { CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname); @@ -1871,6 +2069,73 @@ void G_DoPlayDemo(char *defdemoname) demo_p += 16; // mapmd5 demoflags = READUINT8(demo_p); + + if (demoversion < 0x0010) + { + ; // Don't do anything with files. + } + else if (titledemo) + { + // Titledemos should always play and ought to always be compatible with whatever wadlist is running. + G_SkipDemoExtraFiles(&demo_p); + } + else if (demofileoverride == DFILE_OVERRIDE_LOAD) + { + G_LoadDemoExtraFiles(&demo_p); + } + else if (demofileoverride == DFILE_OVERRIDE_SKIP) + { + G_SkipDemoExtraFiles(&demo_p); + } + else + { + UINT8 error = G_CheckDemoExtraFiles(&demo_p, false); + + if (error) + { + switch (error) + { + case DFILE_ERROR_NOTLOADED: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"), + pdemoname); + break; + + case DFILE_ERROR_OUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"), + pdemoname); + break; + + case DFILE_ERROR_CANNOTLOAD: + snprintf(msg, 1024, + M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + + case DFILE_ERROR_EXTRAFILES: + snprintf(msg, 1024, + M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + } + + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demoplayback = false; + titledemo = false; + return; + } + } + modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; CON_ToggleOff(); @@ -2026,6 +2291,91 @@ void G_DoPlayDemo(char *defdemoname) demo_start = true; } +// +// Check if a replay can be loaded from the menu +// +UINT8 G_CheckDemoForError(char *defdemoname) +{ + lumpnum_t l; + char *n,*pdemoname; + + n = defdemoname+strlen(defdemoname); + while (*n != '/' && *n != '\\' && n != defdemoname) + n--; + if (n != defdemoname) + n++; + pdemoname = ZZ_Alloc(strlen(n)+1); + strcpy(pdemoname,n); + + // Internal if no extension, external if one exists + if (FIL_CheckExtension(defdemoname)) + { + //FIL_DefaultExtension(defdemoname, ".lmp"); + if (!FIL_ReadFile(defdemoname, &demobuffer)) + { + return DFILE_ERROR_NOTDEMO; + } + demo_p = demobuffer; + } + // load demo resource from WAD + else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) + { + return DFILE_ERROR_NOTDEMO; + } + else // it's an internal demo + { + demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC); + } + + // read demo header + if (memcmp(demo_p, DEMOHEADER, 12)) + { + return DFILE_ERROR_NOTDEMO; + } + demo_p += 12; // DEMOHEADER + + demo_p++; // version + demo_p++; // subversion + demoversion = READUINT16(demo_p); + switch(demoversion) + { + case 0x000d: + case 0x000e: + case 0x000f: + case DEMOVERSION: // latest always supported + break; +#ifdef OLD22DEMOCOMPAT + case 0x000c: + break; +#endif + // too old, cannot support. + default: + return DFILE_ERROR_NOTDEMO; + } + demo_p += 16; // demo checksum + if (memcmp(demo_p, "PLAY", 4)) + { + return DFILE_ERROR_NOTDEMO; + } + demo_p += 4; // "PLAY" + demo_p += 2; // gamemap + demo_p += 16; // mapmd5 + + demo_p++; // demoflags + + // Don't do anything with files. + if (demoversion < 0x0010) + { + return DFILE_ERROR_NONE; + } + else if (titledemo) + { + return DFILE_ERROR_NONE; + } + + return G_CheckDemoExtraFiles(&demo_p, true); +} + void G_AddGhost(char *defdemoname) { INT32 i; @@ -2130,6 +2480,9 @@ void G_AddGhost(char *defdemoname) Z_Free(buffer); return; } + + G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. + switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { case ATTACKING_NONE: // 0 diff --git a/src/g_demo.h b/src/g_demo.h index f25315a58..383d2719b 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -26,6 +26,15 @@ extern boolean demoplayback, titledemo, demorecording, timingdemo; extern tic_t demostarttime; +typedef enum +{ + DFILE_OVERRIDE_NONE = 0, // Show errors normally + DFILE_OVERRIDE_LOAD, // Forcefully load demo, add files beforehand + DFILE_OVERRIDE_SKIP, // Forcefully load demo, skip file list +} demo_file_override_e; + +extern demo_file_override_e demofileoverride; + // Quit after playing a demo from cmdline. extern boolean singledemo; extern boolean demo_start; @@ -53,6 +62,18 @@ typedef enum GHC_RETURNSKIN // ditto } ghostcolor_t; +// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's. +typedef enum +{ + DFILE_ERROR_NONE = 0, // No file error + DFILE_ERROR_NOTLOADED, // Files are not loaded, but can be without a restart. + DFILE_ERROR_OUTOFORDER, // Files are loaded, but out of order. + DFILE_ERROR_INCOMPLETEOUTOFORDER, // Some files are loaded out of order, but others are not. + DFILE_ERROR_CANNOTLOAD, // Files are missing and cannot be loaded. + DFILE_ERROR_EXTRAFILES, // Extra files outside of the replay's file list are loaded. + DFILE_ERROR_NOTDEMO = UINT8_MAX, // This replay isn't even a replay... +} demo_file_error_e; + // Record/playback tics void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum); void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum); @@ -83,5 +104,6 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); void G_StopDemo(void); boolean G_CheckDemoStatus(void); INT32 G_ConvertOldFrameFlags(INT32 frame); +UINT8 G_CheckDemoForError(char *defdemoname); #endif // __G_DEMO__ diff --git a/src/m_menu.c b/src/m_menu.c index 12003f945..828fc1aee 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3500,10 +3500,10 @@ boolean M_Responder(event_t *ev) #ifndef DEVELOP // TODO: Replays are scary, so I left the remaining instances of this alone. // It'd be nice to get rid of this once and for all though! - if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && (modifiedgame && !savemoddata) && !usedCheats) + if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && usedCheats) { S_StartSound(NULL, sfx_skid); - M_StartMessage(M_GetText("This cannot be done in a modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING); + M_StartMessage(M_GetText("This cannot be done in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); return true; } #endif @@ -10449,13 +10449,23 @@ static void M_ChooseTimeAttack(INT32 choice) G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), false, false); } +static char ra_demoname[1024]; + +static void M_StartTimeAttackReplay(INT32 choice) +{ + if (choice == 'y' || choice == KEY_ENTER) + { + M_ClearMenus(true); + modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows + G_DoPlayDemo(ra_demoname); + } +} + // Player has selected the "REPLAY" from the time attack screen static void M_ReplayTimeAttack(INT32 choice) { const char *which; - char *demoname; - M_ClearMenus(true); - modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows + UINT8 error = DFILE_ERROR_NONE; if (currentMenu == &SP_ReplayDef) { @@ -10475,11 +10485,15 @@ static void M_ReplayTimeAttack(INT32 choice) break; case 4: // guest // srb2/replay/main/map01-guest.lmp - G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); - return; + snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); + break; + } + + if (choice != 4) + { + // srb2/replay/main/map01-sonic-time-best.lmp + snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which); } - // srb2/replay/main/map01-sonic-time-best.lmp - G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which)); } else if (currentMenu == &SP_NightsReplayDef) { @@ -10495,19 +10509,66 @@ static void M_ReplayTimeAttack(INT32 choice) which = "last"; break; case 3: // guest - G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); - return; + snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); + break; } - demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which); + if (choice != 3) + { + snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which); #ifdef OLDNREPLAYNAME // Check for old style named NiGHTS replay if a new style replay doesn't exist. - if (!FIL_FileExists(demoname)) - demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which); + if (!FIL_FileExists(ra_demoname)) + { + snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which); + } #endif - - G_DoPlayDemo(demoname); + } } + + demofileoverride = DFILE_OVERRIDE_NONE; + error = G_CheckDemoForError(ra_demoname); + + if (error) + { + S_StartSound(NULL, sfx_skid); + + switch (error) + { + case DFILE_ERROR_NOTDEMO: + M_StartMessage(M_GetText("An error occurred loading this replay.\n\n(Press a key)\n"), NULL, MM_NOTHING); + break; + + case DFILE_ERROR_NOTLOADED: + demofileoverride = DFILE_OVERRIDE_LOAD; + M_StartMessage(M_GetText("Add-ons for this replay\nhave not been loaded.\n\nAttempt to load files?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + break; + + case DFILE_ERROR_OUTOFORDER: + demofileoverride = DFILE_OVERRIDE_SKIP; + M_StartMessage(M_GetText("Add-ons for this replay\nwere loaded out of order.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + break; + + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + demofileoverride = DFILE_OVERRIDE_LOAD; + M_StartMessage(M_GetText("Add-ons for this replay\nhave not been loaded,\nand some are in the wrong order.\n\nAttempt to load files?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + break; + + case DFILE_ERROR_CANNOTLOAD: + demofileoverride = DFILE_OVERRIDE_SKIP; + M_StartMessage(M_GetText("Add-ons for this replay\ncould not be loaded.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + break; + + case DFILE_ERROR_EXTRAFILES: + demofileoverride = DFILE_OVERRIDE_SKIP; + M_StartMessage(M_GetText("You have more files loaded\nthan the replay does.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + break; + } + + return; + } + + M_StartTimeAttackReplay(KEY_ENTER); } static void M_EraseGuest(INT32 choice) From f99cf91d3ddd08ec58ff099f588fd85819c3842f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 25 Jul 2023 09:29:09 -0400 Subject: [PATCH 250/478] Promote file count to UINT16 --- src/g_demo.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index 230f6da2d..8c6064c57 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1416,7 +1416,7 @@ void G_BeginRecording(void) player_t *player = &players[consoleplayer]; char *filename; - UINT8 totalfiles; + UINT16 totalfiles; UINT8 *m; if (demo_p) @@ -1459,7 +1459,7 @@ void G_BeginRecording(void) } } - WRITEUINT8(m, totalfiles); + WRITEUINT16(m, totalfiles); switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) { @@ -1618,15 +1618,15 @@ void G_BeginMetal(void) static void G_LoadDemoExtraFiles(UINT8 **pp) { - UINT8 totalfiles; + UINT16 totalfiles; char filename[MAX_WADPATH]; UINT8 md5sum[16]; filestatus_t ncs; boolean toomany = false; boolean alreadyloaded; - UINT8 i, j; + UINT16 i, j; - totalfiles = READUINT8((*pp)); + totalfiles = READUINT16((*pp)); for (i = 0; i < totalfiles; ++i) { if (toomany) @@ -1687,8 +1687,8 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) static void G_SkipDemoExtraFiles(UINT8 **pp) { - UINT8 totalfiles; - UINT8 i; + UINT16 totalfiles; + UINT16 i; if (demoversion < 0x0010) { @@ -1696,7 +1696,7 @@ static void G_SkipDemoExtraFiles(UINT8 **pp) return; } - totalfiles = READUINT8((*pp)); + totalfiles = READUINT16((*pp)); for (i = 0; i < totalfiles; ++i) { SKIPSTRING((*pp));// file name @@ -1708,12 +1708,12 @@ static void G_SkipDemoExtraFiles(UINT8 **pp) // Enabling quick prevents filesystem checks to see if needed files are available to load. static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) { - UINT8 totalfiles, filesloaded, nmusfilecount; + UINT16 totalfiles, filesloaded, nmusfilecount; char filename[MAX_WADPATH]; UINT8 md5sum[16]; boolean toomany = false; boolean alreadyloaded; - UINT8 i, j; + UINT16 i, j; UINT8 error = DFILE_ERROR_NONE; if (demoversion < 0x0010) @@ -1722,7 +1722,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) return DFILE_ERROR_NONE; } - totalfiles = READUINT8((*pp)); + totalfiles = READUINT16((*pp)); filesloaded = 0; for (i = 0; i < totalfiles; ++i) { From dded3522933aaa068f564c024096c97a174166c0 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 25 Jul 2023 09:34:55 -0400 Subject: [PATCH 251/478] Harsher replay menu Don't allow loading demos with invalid file lists at all. If you insist on doing this, it has to be done from the command line now. --- src/g_demo.c | 2 +- src/m_menu.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/g_demo.c b/src/g_demo.c index 8c6064c57..438d3dfc9 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1444,7 +1444,7 @@ void G_BeginRecording(void) // file list m = demo_p;/* file count */ - demo_p += 1; + demo_p += 2; totalfiles = 0; for (i = mainwads; ++i < numwadfiles; ) diff --git a/src/m_menu.c b/src/m_menu.c index 828fc1aee..21ba98dd2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -10545,23 +10545,35 @@ static void M_ReplayTimeAttack(INT32 choice) break; case DFILE_ERROR_OUTOFORDER: + /* demofileoverride = DFILE_OVERRIDE_SKIP; M_StartMessage(M_GetText("Add-ons for this replay\nwere loaded out of order.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + */ + M_StartMessage(M_GetText("Add-ons for this replay\nwere loaded out of order.\n\n(Press a key)\n"), NULL, MM_NOTHING); break; case DFILE_ERROR_INCOMPLETEOUTOFORDER: + /* demofileoverride = DFILE_OVERRIDE_LOAD; M_StartMessage(M_GetText("Add-ons for this replay\nhave not been loaded,\nand some are in the wrong order.\n\nAttempt to load files?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + */ + M_StartMessage(M_GetText("Add-ons for this replay\nhave not been loaded,\nand some are in the wrong order.\n\n(Press a key)\n"), NULL, MM_NOTHING); break; case DFILE_ERROR_CANNOTLOAD: + /* demofileoverride = DFILE_OVERRIDE_SKIP; M_StartMessage(M_GetText("Add-ons for this replay\ncould not be loaded.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + */ + M_StartMessage(M_GetText("Add-ons for this replay\ncould not be loaded.\n\n(Press a key)\n"), NULL, MM_NOTHING); break; case DFILE_ERROR_EXTRAFILES: + /* demofileoverride = DFILE_OVERRIDE_SKIP; M_StartMessage(M_GetText("You have more files loaded\nthan the replay does.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO); + */ + M_StartMessage(M_GetText("You have more files loaded\nthan the replay does.\n\n(Press a key)\n"), NULL, MM_NOTHING); break; } From 0e2682d5908bf825d6125664144fe70ba20c9b9b Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Fri, 30 Jun 2023 00:09:20 +0200 Subject: [PATCH 252/478] Add "drawonlyforplayer" and "dontdrawforviewmobj" --- src/b_bot.c | 3 +- src/g_game.c | 1 + src/lua_baselib.c | 3 +- src/lua_mobjlib.c | 33 ++++++++++++ src/p_mobj.c | 6 +-- src/p_mobj.h | 2 + src/p_saveg.c | 69 +++++++++++++++--------- src/p_user.c | 130 +++++++++++++++++++++++++++++++++------------- src/r_things.c | 11 ++-- 9 files changed, 188 insertions(+), 70 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index d1465f891..57f762304 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -631,7 +631,8 @@ void B_HandleFlightIndicator(player_t *player) } // otherwise, update its visibility - if (P_IsLocalPlayer(player->botleader)) + tails->hnext->drawonlyforplayer = player->botleader; // Hide it from the other player in splitscreen, and yourself when spectating + if (P_IsLocalPlayer(player->botleader)) // Only display it on your own view. Don't display it for spectators tails->hnext->flags2 &= ~MF2_DONTDRAW; else tails->hnext->flags2 |= MF2_DONTDRAW; diff --git a/src/g_game.c b/src/g_game.c index 15b1e1081..8264fbe6b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1441,6 +1441,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // I assume this is netgame-safe because gunslinger spawns this for only the local player...... *sweats intensely* newtarget = P_SpawnMobj(ticcmd_ztargetfocus[forplayer]->x, ticcmd_ztargetfocus[forplayer]->y, ticcmd_ztargetfocus[forplayer]->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker P_SetTarget(&newtarget->target, ticcmd_ztargetfocus[forplayer]); + newtarget->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating if (player->mo && P_AproxDistance( player->mo->x - ticcmd_ztargetfocus[forplayer]->x, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index ed5736fa7..838e2f53b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -689,11 +689,12 @@ static int lib_pSpawnLockOn(lua_State *L) return LUA_ErrInvalid(L, "player_t"); if (state >= NUMSTATES) return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1); - if (P_IsLocalPlayer(player)) // Only display it on your own view. + if (P_IsLocalPlayer(player)) // Only display it on your own view. Don't display it for spectators { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker P_SetTarget(&visual->target, lockon); visual->flags2 |= MF2_DONTDRAW; + visual->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating P_SetMobjStateNF(visual, state); } return 0; diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 851c569d2..fd8dcec92 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -44,6 +44,8 @@ enum mobj_e { mobj_spritexoffset, mobj_spriteyoffset, mobj_floorspriteslope, + mobj_drawonlyforplayer, + mobj_dontdrawforviewmobj, mobj_touching_sectorlist, mobj_subsector, mobj_floorz, @@ -122,6 +124,8 @@ static const char *const mobj_opt[] = { "spritexoffset", "spriteyoffset", "floorspriteslope", + "drawonlyforplayer", + "dontdrawforviewmobj", "touching_sectorlist", "subsector", "floorz", @@ -262,6 +266,17 @@ static int mobj_get(lua_State *L) case mobj_floorspriteslope: LUA_PushUserdata(L, mo->floorspriteslope, META_SLOPE); break; + case mobj_drawonlyforplayer: + LUA_PushUserdata(L, mo->drawonlyforplayer, META_PLAYER); + break; + case mobj_dontdrawforviewmobj: + if (mo->dontdrawforviewmobj && P_MobjWasRemoved(mo->dontdrawforviewmobj)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->dontdrawforviewmobj, NULL); + return 0; + } + LUA_PushUserdata(L, mo->dontdrawforviewmobj, META_MOBJ); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -551,6 +566,24 @@ static int mobj_set(lua_State *L) break; case mobj_floorspriteslope: return NOSET; + case mobj_drawonlyforplayer: + if (lua_isnil(L, 3)) + mo->drawonlyforplayer = NULL; + else + { + player_t *drawonlyforplayer = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); + mo->drawonlyforplayer = drawonlyforplayer; + } + break; + case mobj_dontdrawforviewmobj: + if (lua_isnil(L, 3)) + P_SetTarget(&mo->dontdrawforviewmobj, NULL); + else + { + mobj_t *dontdrawforviewmobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&mo->dontdrawforviewmobj, dontdrawforviewmobj); + } + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: diff --git a/src/p_mobj.c b/src/p_mobj.c index a25b5643b..4ca59285f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6882,6 +6882,7 @@ void P_RunOverlays(void) mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP); mo->scale = mo->destscale = mo->target->scale; mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir; + P_SetTarget(&mo->dontdrawforviewmobj, mo->target->dontdrawforviewmobj); // Hide the overlay from the view that its target is hidden from - But don't copy drawonlyforplayer! if (!(mo->state->frame & FF_ANIMATE)) zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale); @@ -7951,11 +7952,6 @@ static void P_MobjSceneryThink(mobj_t *mobj) return; } - if (!camera.chase) - mobj->flags2 |= MF2_DONTDRAW; - else - mobj->flags2 &= ~MF2_DONTDRAW; - P_UnsetThingPosition(mobj); { fixed_t radius = FixedMul(10*mobj->info->speed, mobj->target->scale); diff --git a/src/p_mobj.h b/src/p_mobj.h index 6a5ab84c4..9c598f59e 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -334,6 +334,8 @@ typedef struct mobj_s // Player and mobj sprites in multiplayer modes are modified // using an internal color lookup table for re-indexing. UINT16 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation). + struct player_s *drawonlyforplayer; // If set, hides the mobj for everyone except this player and their spectators + struct mobj_s *dontdrawforviewmobj; // If set, hides the mobj if dontdrawforviewmobj is the current camera (first-person player or awayviewmobj) // Interaction info, by BLOCKMAP. // Links in blocks (if needed). diff --git a/src/p_saveg.c b/src/p_saveg.c index 76f1661ac..8f11e63e5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1553,30 +1553,32 @@ typedef enum typedef enum { - MD2_CUSVAL = 1, - MD2_CVMEM = 1<<1, - MD2_SKIN = 1<<2, - MD2_COLOR = 1<<3, - MD2_SCALESPEED = 1<<4, - MD2_EXTVAL1 = 1<<5, - MD2_EXTVAL2 = 1<<6, - MD2_HNEXT = 1<<7, - MD2_HPREV = 1<<8, - MD2_FLOORROVER = 1<<9, - MD2_CEILINGROVER = 1<<10, - MD2_SLOPE = 1<<11, - MD2_COLORIZED = 1<<12, - MD2_MIRRORED = 1<<13, - MD2_SPRITEROLL = 1<<14, - MD2_SHADOWSCALE = 1<<15, - MD2_RENDERFLAGS = 1<<16, - MD2_BLENDMODE = 1<<17, - MD2_SPRITEXSCALE = 1<<18, - MD2_SPRITEYSCALE = 1<<19, - MD2_SPRITEXOFFSET = 1<<20, - MD2_SPRITEYOFFSET = 1<<21, - MD2_FLOORSPRITESLOPE = 1<<22, - MD2_DISPOFFSET = 1<<23 + MD2_CUSVAL = 1, + MD2_CVMEM = 1<<1, + MD2_SKIN = 1<<2, + MD2_COLOR = 1<<3, + MD2_SCALESPEED = 1<<4, + MD2_EXTVAL1 = 1<<5, + MD2_EXTVAL2 = 1<<6, + MD2_HNEXT = 1<<7, + MD2_HPREV = 1<<8, + MD2_FLOORROVER = 1<<9, + MD2_CEILINGROVER = 1<<10, + MD2_SLOPE = 1<<11, + MD2_COLORIZED = 1<<12, + MD2_MIRRORED = 1<<13, + MD2_SPRITEROLL = 1<<14, + MD2_SHADOWSCALE = 1<<15, + MD2_RENDERFLAGS = 1<<16, + MD2_BLENDMODE = 1<<17, + MD2_SPRITEXSCALE = 1<<18, + MD2_SPRITEYSCALE = 1<<19, + MD2_SPRITEXOFFSET = 1<<20, + MD2_SPRITEYOFFSET = 1<<21, + MD2_FLOORSPRITESLOPE = 1<<22, + MD2_DISPOFFSET = 1<<23, + MD2_DRAWONLYFORPLAYER = 1<<24, + MD2_DONTDRAWFORVIEWMOBJ = 1<<25 } mobj_diff2_t; typedef enum @@ -1811,6 +1813,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) || (slope->normal.z != FRACUNIT)) diff2 |= MD2_FLOORSPRITESLOPE; } + if (mobj->drawonlyforplayer) + diff2 |= MD2_DRAWONLYFORPLAYER; + if (mobj->dontdrawforviewmobj) + diff2 |= MD2_DONTDRAWFORVIEWMOBJ; if (mobj->dispoffset != mobj->info->dispoffset) diff2 |= MD2_DISPOFFSET; @@ -1988,6 +1994,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, slope->normal.y); WRITEFIXED(save_p, slope->normal.z); } + if (diff2 & MD2_DRAWONLYFORPLAYER) + WRITEUINT8(save_p, mobj->drawonlyforplayer-players); + if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) + WRITEUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum); if (diff2 & MD2_DISPOFFSET) WRITEINT32(save_p, mobj->dispoffset); @@ -3044,6 +3054,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) slope->normal.y = READFIXED(save_p); slope->normal.z = READFIXED(save_p); } + if (diff2 & MD2_DRAWONLYFORPLAYER) + mobj->drawonlyforplayer = &players[READUINT8(save_p)]; + if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) + mobj->dontdrawforviewmobj = (mobj_t *)(size_t)READUINT32(save_p); if (diff2 & MD2_DISPOFFSET) mobj->dispoffset = READINT32(save_p); else @@ -4063,6 +4077,13 @@ static void P_RelinkPointers(void) if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) continue; + if (mobj->dontdrawforviewmobj) + { + temp = (UINT32)(size_t)mobj->dontdrawforviewmobj; + mobj->dontdrawforviewmobj = NULL; + if (!P_SetTarget(&mobj->dontdrawforviewmobj, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "dontdrawforviewmobj not found on %d\n", mobj->type); + } if (mobj->tracer) { temp = (UINT32)(size_t)mobj->tracer; diff --git a/src/p_user.c b/src/p_user.c index 62dd2fcb2..889e887c1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -398,6 +398,7 @@ void P_GiveFinishFlags(player_t *player) angle += FixedAngle(120*FRACUNIT); P_SetTarget(&flag->target, player->mo); + P_SetTarget(&flag->dontdrawforviewmobj, player->mo); // Hide the flag in first-person } } @@ -1840,6 +1841,7 @@ void P_SpawnShieldOrb(player_t *player) shieldobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, orbtype); shieldobj->flags2 |= MF2_SHIELD; P_SetTarget(&shieldobj->target, player->mo); + P_SetTarget(&shieldobj->dontdrawforviewmobj, player->mo); // Hide the shield in first-person if ((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) { shieldobj->color = SKINCOLOR_PINK; @@ -1964,6 +1966,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) mobj_t *ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST); P_SetTarget(&ghost->target, mobj); + P_SetTarget(&ghost->dontdrawforviewmobj, mobj); // Hide the ghost in first-person P_SetScale(ghost, mobj->scale); ghost->destscale = mobj->scale; @@ -2009,6 +2012,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) mobj_t *ghost2 = P_SpawnGhostMobj(mobj->player->followmobj); P_SetTarget(&ghost2->tracer, ghost); P_SetTarget(&ghost->tracer, ghost2); + P_SetTarget(&ghost2->dontdrawforviewmobj, mobj); // Hide the follow-ghost for the non-follow object ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW); } @@ -3123,39 +3127,41 @@ static void P_DoBubbleBreath(player_t *player) // static void P_DoPlayerHeadSigns(player_t *player) { + mobj_t *sign = NULL; + if (G_TagGametype()) { - // If you're "IT", show a big "IT" over your head for others to see. - if (player->pflags & PF_TAGIT && !P_IsLocalPlayer(player)) + // If you're "IT", show a big "IT" over your head for others to see, including spectators + // (and even yourself if you spectate someone else). + if (player->pflags & PF_TAGIT && (!P_IsLocalPlayer(player) || consoleplayer != displayplayer || splitscreen)) { - mobj_t* it = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TAG); - it->x = player->mo->x; - it->y = player->mo->y; - it->z = player->mo->z; - it->old_x = player->mo->old_x; - it->old_y = player->mo->old_y; - it->old_z = player->mo->old_z; + sign = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TAG); + sign->x = player->mo->x; + sign->y = player->mo->y; + sign->z = player->mo->z; + sign->old_x = player->mo->old_x; + sign->old_y = player->mo->old_y; + sign->old_z = player->mo->old_z; if (!(player->mo->eflags & MFE_VERTICALFLIP)) { - it->z += player->mo->height; - it->old_z += player->mo->height; + sign->z += player->mo->height; + sign->old_z += player->mo->height; } else { - it->z -= mobjinfo[MT_TAG].height; - it->old_z -= mobjinfo[MT_TAG].height; + sign->z -= mobjinfo[MT_TAG].height; + sign->old_z -= mobjinfo[MT_TAG].height; } } } else if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh). { - // Spawn a got-flag message over the head of the player that - // has it (but not on your own screen if you have the flag). - if (splitscreen || player != &players[consoleplayer]) + // Spawn a got-flag message over the head of the player that has it + // (but not on your own screen if you have the flag, unless you're spectating). + if (!P_IsLocalPlayer(player) || consoleplayer != displayplayer || splitscreen) { fixed_t zofs; - mobj_t *sign; boolean player_is_flipped = (player->mo->eflags & MFE_VERTICALFLIP) > 0; zofs = player->mo->momz; @@ -3187,6 +3193,43 @@ static void P_DoPlayerHeadSigns(player_t *player) sign->frame = 2|FF_FULLBRIGHT; } } + + if (!P_MobjWasRemoved(sign) && splitscreen) // Hide the sign from yourself in splitscreen - In single-screen, it wouldn't get spawned if it shouldn't be visible + { + if (player == &players[displayplayer]) + sign->drawonlyforplayer = &players[secondarydisplayplayer]; + else + sign->drawonlyforplayer = &players[displayplayer]; + +#ifdef QUADS + if (splitscreen > 1) // Can be seen by at least two local views, so we need an extra copy of the sign + { + UINT32 signframe = sign->frame; // Copy the flag frame + sign = P_SpawnMobjFromMobj(sign, 0, 0, 0, MT_TAG); + if (P_MobjWasRemoved(sign)) + return; + + sign->frame = signframe; + if (player == &players[displayplayer] || player == &players[secondarydisplayplayer]) + sign->drawonlyforplayer = &players[thirddisplayplayer]; + else + sign->drawonlyforplayer = &players[secondarydisplayplayer]; + + if (splitscreen > 2) // Can be seen by three local views + { + sign = P_SpawnMobjFromMobj(sign, 0, 0, 0, MT_TAG); + if (P_MobjWasRemoved(sign)) + return; + + sign->frame = signframe; + if (player != &players[fourthdisplayplayer]) + sign->drawonlyforplayer = &players[fourthdisplayplayer]; + else + sign->drawonlyforplayer = &players[thirddisplayplayer]; + } + } +#endif + } } // @@ -4707,10 +4750,11 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) mobj_t *lockon = P_LookForEnemies(player, false, true); if (lockon) { - if (P_IsLocalPlayer(player)) // Only display it on your own view. + if (P_IsLocalPlayer(player)) // Only display it on your own view. Don't display it for spectators { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker P_SetTarget(&visual->target, lockon); + visual->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating } } if ((cmd->buttons & BT_SPIN) && !(player->pflags & PF_SPINDOWN)) @@ -5054,7 +5098,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock { if ((lockonshield = P_LookForEnemies(player, false, false))) { - if (P_IsLocalPlayer(player)) // Only display it on your own view. + if (P_IsLocalPlayer(player)) // Only display it on your own view. Don't display it for spectators { boolean dovis = true; if (lockonshield == lockonthok) @@ -5068,6 +5112,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock { visual = P_SpawnMobj(lockonshield->x, lockonshield->y, lockonshield->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker P_SetTarget(&visual->target, lockonshield); + visual->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating P_SetMobjStateNF(visual, visual->info->spawnstate+1); } } @@ -5171,10 +5216,11 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) && (lockonthok = P_LookForEnemies(player, true, false))) { - if (P_IsLocalPlayer(player)) // Only display it on your own view. + if (P_IsLocalPlayer(player)) // Only display it on your own view. Don't display it for spectators { visual = P_SpawnMobj(lockonthok->x, lockonthok->y, lockonthok->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker P_SetTarget(&visual->target, lockonthok); + visual->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating } } @@ -11084,17 +11130,30 @@ static void P_MinecartThink(player_t *player) // Mark interpolation; the old positions need to be relative to the displacement from the minecart _after_ it's moved. // This isn't quite correct (it captures the landing wobble) but it works well enough + // Additionally, hide other players' marks if (detleft) { - detleft->old_x = detleft->x - (minecart->old_x - minecart->old_x2); - detleft->old_y = detleft->y - (minecart->old_y - minecart->old_y2); - detleft->old_z = detleft->z - (minecart->old_z - minecart->old_z2); + if (P_IsLocalPlayer(player)) + { + detleft->old_x = detleft->x - (minecart->old_x - minecart->old_x2); + detleft->old_y = detleft->y - (minecart->old_y - minecart->old_y2); + detleft->old_z = detleft->z - (minecart->old_z - minecart->old_z2); + detleft->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating + } + else // Don't see others' marks when spectating others + P_RemoveMobj(detleft); // Lock-on markers are only spawned client-side, so this SHOULD be safe too... } if (detright) { - detright->old_x = detright->x - (minecart->old_x - minecart->old_x2); - detright->old_y = detright->y - (minecart->old_y - minecart->old_y2); - detright->old_z = detright->z - (minecart->old_z - minecart->old_z2); + if (P_IsLocalPlayer(player)) + { + detright->old_x = detright->x - (minecart->old_x - minecart->old_x2); + detright->old_y = detright->y - (minecart->old_y - minecart->old_y2); + detright->old_z = detright->z - (minecart->old_z - minecart->old_z2); + detright->drawonlyforplayer = player; + } + else + P_RemoveMobj(detleft); } } else @@ -11386,12 +11445,15 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) for (i = -1; i < 2; i += 2) { + mobj_t *bubble; offsetH = i*P_ReturnThrustX(fume, fume->movedir, radiusV); offsetV = i*P_ReturnThrustY(fume, fume->movedir, radiusV); x = mo->x + radiusX + FixedMul(offsetH, factorX); y = mo->y + radiusY + FixedMul(offsetH, factorY); z = mo->z + heightoffset + offsetV; - P_SpawnMobj(x, y, z, MT_SMALLBUBBLE)->scale = mo->scale >> 1; + bubble = P_SpawnMobj(x, y, z, MT_SMALLBUBBLE); + bubble->scale = mo->scale >> 1; + P_SetTarget(&bubble->dontdrawforviewmobj, mo); // Hide the bubble in first-person } fume->movefactor = 0; @@ -11460,7 +11522,11 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) // If dashmode is high enough, spawn a trail if (player->normalspeed >= skins[player->skin].normalspeed*2) - P_SpawnGhostMobj(fume); + { + mobj_t *ghost = P_SpawnGhostMobj(fume); + if (!P_MobjWasRemoved(ghost)) + P_SetTarget(&ghost->dontdrawforviewmobj, mo); // Hide the trail in first-person + } } // @@ -12104,14 +12170,6 @@ void P_PlayerThink(player_t *player) gmobj->tracer->frame |= tr_trans70<flags2 |= MF2_DONTDRAW; } #endif diff --git a/src/r_things.c b/src/r_things.c index 248357e11..eee284d46 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -3322,9 +3322,14 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) boolean R_ThingVisible (mobj_t *thing) { return (!( - thing->sprite == SPR_NULL || - ( thing->flags2 & (MF2_DONTDRAW) ) || - (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing))) + (thing->sprite == SPR_NULL) || // Don't draw null-sprites + (thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects + (thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects + (r_viewmobj && ( + (r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects + (r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj + (r_viewmobj == thing->dontdrawforviewmobj) // Don't draw objects that are hidden for the current view + )) )); } From 10a8f2d05ec81ab1f348b139a9452afb27accc27 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 25 Jul 2023 11:30:55 -0400 Subject: [PATCH 253/478] Fix some minor warnings - Fix `lib_getSkinSprite` overshadowing `sprites` global - Rename terrible result_e `ok` so it stops overshadowing crap - Remove inlining from w_wad.c since it reached the inline limit (remember kids, your compiler knows better than you these days whenever or not to inline something) - Remove unused variable in G_PlayerReborn --- src/g_game.c | 1 - src/lua_skinlib.c | 4 ++-- src/p_floor.c | 8 ++++---- src/p_spec.h | 2 +- src/w_wad.c | 10 +++++----- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 8264fbe6b..b8c434998 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2547,7 +2547,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) { player_t *p; INT32 score; - INT32 recordscore; INT32 lives; INT32 continues; fixed_t camerascale; diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index b7890a6c7..13e0dd987 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -334,13 +334,13 @@ static const char *const sprites_opt[] = { // skin.sprites[i] -> sprites[i] static int lib_getSkinSprite(lua_State *L) { - spritedef_t *sprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES); + spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES); playersprite_t i = luaL_checkinteger(L, 2); if (i < 0 || i >= NUMPLAYERSPRITES*2) return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1); - LUA_PushUserdata(L, &sprites[i], META_SKINSPRITESLIST); + LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST); return 1; } diff --git a/src/p_floor.c b/src/p_floor.c index 9c24f5851..38f0c5a0f 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -155,7 +155,7 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus } } - return ok; + return planeok; } // @@ -1128,7 +1128,7 @@ void T_ThwompSector(thwomp_t *thwomp) thwomp->direction // direction ); - if (res == ok || res == pastdest) + if (res == planeok || res == pastdest) T_MovePlane ( thwomp->sector, // sector @@ -1160,7 +1160,7 @@ void T_ThwompSector(thwomp_t *thwomp) thwomp->direction // direction ); - if (res == ok || res == pastdest) + if (res == planeok || res == pastdest) T_MovePlane ( thwomp->sector, // sector @@ -1465,7 +1465,7 @@ void T_RaiseSector(raise_t *raise) direction // direction ); - if (res == ok || res == pastdest) + if (res == planeok || res == pastdest) T_MovePlane ( raise->sector, // sector diff --git a/src/p_spec.h b/src/p_spec.h index c8701749f..50ab6410f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -895,7 +895,7 @@ typedef struct typedef enum { - ok, + planeok, crushed, pastdest } result_e; diff --git a/src/w_wad.c b/src/w_wad.c index b13dc8cc1..171eab4f3 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -201,7 +201,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) } // Look for all DEHACKED and Lua scripts inside a PK3 archive. -static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile) +static void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile) { UINT16 posStart, posEnd; @@ -241,7 +241,7 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile) } // search for all DEHACKED lump in all wads and load it -static inline void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile) +static void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile) { UINT16 lump; @@ -305,7 +305,7 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile) * \param resblock resulting MD5 checksum * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found */ -static inline INT32 W_MakeFileMD5(const char *filename, void *resblock) +static INT32 W_MakeFileMD5(const char *filename, void *resblock) { #ifdef NOMD5 (void)filename; @@ -1956,7 +1956,7 @@ void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag) // return false. // // no outside code uses the PWAD form, for now -static inline boolean W_IsLumpCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) +static boolean W_IsLumpCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) { void *lcache; @@ -1988,7 +1988,7 @@ boolean W_IsLumpCached(lumpnum_t lumpnum, void *ptr) // return false. // // no outside code uses the PWAD form, for now -static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) +static boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) { void *lcache; From c6c3cc3209833557a70933c87d25564a4ba39014 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 26 Jul 2023 00:06:52 -0300 Subject: [PATCH 254/478] Drawseg clipping optimized, from prboom-plus Co-authored-by: Sally Coolatta --- src/r_things.c | 202 +++++++++++++++++++++++++++++++++++++------------ src/r_things.h | 1 - 2 files changed, 154 insertions(+), 49 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 248357e11..5f0f83c5c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -80,6 +80,33 @@ static spriteframe_t sprtemp[64]; static size_t maxframe; static const char *spritename; +// +// Clipping against drawsegs optimization, from prboom-plus +// +// TODO: This should be done with proper subsector pass through +// sprites which would ideally remove the need to do it at all. +// Unfortunately, SRB2's drawing loop has lots of annoying +// changes from Doom for portals, which make it hard to implement. + +typedef struct drawseg_xrange_item_s +{ + INT16 x1, x2; + drawseg_t *user; +} drawseg_xrange_item_t; + +typedef struct drawsegs_xrange_s +{ + drawseg_xrange_item_t *items; + INT32 count; +} drawsegs_xrange_t; + +#define DS_RANGES_COUNT 3 +static drawsegs_xrange_t drawsegs_xranges[DS_RANGES_COUNT]; + +static drawseg_xrange_item_t *drawsegs_xrange; +static size_t drawsegs_xrange_size = 0; +static INT32 drawsegs_xrange_count = 0; + // ========================================================================== // // Sprite loading routines: support sprites in pwad, dehacked sprite renaming, @@ -3136,7 +3163,7 @@ static void R_HeightSecClip(vissprite_t *spr, INT32 x1, INT32 x2) // R_ClipVisSprite // Clips vissprites without drawing, so that portals can work. -Red -void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal) +static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal) { drawseg_t *ds; INT32 x; @@ -3156,21 +3183,23 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p // Pointer check was originally nonportable // and buggy, by going past LEFT end of array: - // for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code - for (ds = ds_p; ds-- > dsstart;) + // e6y: optimization + if (drawsegs_xrange_size) { - // determine if the drawseg obscures the sprite - if (ds->x1 > x2 || - ds->x2 < x1 || - (!ds->silhouette - && !ds->maskedtexturecol)) - { - // does not cover sprite - continue; - } + const drawseg_xrange_item_t *last = &drawsegs_xrange[drawsegs_xrange_count - 1]; + drawseg_xrange_item_t *curr = &drawsegs_xrange[-1]; - if (ds->portalpass != 66) + while (++curr <= last) { + // determine if the drawseg obscures the sprite + if (curr->x1 > x2 || curr->x2 < x1) + { + // does not cover sprite + continue; + } + + ds = curr->user; + if (ds->portalpass > 0 && ds->portalpass <= portalrender) continue; // is a portal @@ -3195,43 +3224,43 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p // seg is behind sprite continue; } - } - r1 = ds->x1 < x1 ? x1 : ds->x1; - r2 = ds->x2 > x2 ? x2 : ds->x2; + r1 = ds->x1 < x1 ? x1 : ds->x1; + r2 = ds->x2 > x2 ? x2 : ds->x2; - // clip this piece of the sprite - silhouette = ds->silhouette; + // clip this piece of the sprite + silhouette = ds->silhouette; - if (spr->gz >= ds->bsilheight) - silhouette &= ~SIL_BOTTOM; + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; - if (spr->gzt <= ds->tsilheight) - silhouette &= ~SIL_TOP; + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; - if (silhouette == SIL_BOTTOM) - { - // bottom sil - for (x = r1; x <= r2; x++) - if (spr->clipbot[x] == -2) - spr->clipbot[x] = ds->sprbottomclip[x]; - } - else if (silhouette == SIL_TOP) - { - // top sil - for (x = r1; x <= r2; x++) - if (spr->cliptop[x] == -2) - spr->cliptop[x] = ds->sprtopclip[x]; - } - else if (silhouette == (SIL_TOP|SIL_BOTTOM)) - { - // both - for (x = r1; x <= r2; x++) + if (silhouette == SIL_BOTTOM) { - if (spr->clipbot[x] == -2) - spr->clipbot[x] = ds->sprbottomclip[x]; - if (spr->cliptop[x] == -2) - spr->cliptop[x] = ds->sprtopclip[x]; + // bottom sil + for (x = r1; x <= r2; x++) + if (spr->clipbot[x] == -2) + spr->clipbot[x] = ds->sprbottomclip[x]; + } + else if (silhouette == SIL_TOP) + { + // top sil + for (x = r1; x <= r2; x++) + if (spr->cliptop[x] == -2) + spr->cliptop[x] = ds->sprtopclip[x]; + } + else if (silhouette == (SIL_TOP|SIL_BOTTOM)) + { + // both + for (x = r1; x <= r2; x++) + { + if (spr->clipbot[x] == -2) + spr->clipbot[x] = ds->sprbottomclip[x]; + if (spr->cliptop[x] == -2) + spr->cliptop[x] = ds->sprtopclip[x]; + } } } } @@ -3305,16 +3334,93 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) { + const size_t maxdrawsegs = ds_p - drawsegs; + const INT32 cx = viewwidth / 2; + drawseg_t* ds; + INT32 i; + + // e6y + // Reducing of cache misses in the following R_DrawSprite() + // Makes sense for scenes with huge amount of drawsegs. + // ~12% of speed improvement on epic.wad map05 + for (i = 0; i < DS_RANGES_COUNT; i++) + { + drawsegs_xranges[i].count = 0; + } + + if (visspritecount - clippedvissprites <= 0) + { + return; + } + + if (drawsegs_xrange_size < maxdrawsegs) + { + drawsegs_xrange_size = 2 * maxdrawsegs; + + for (i = 0; i < DS_RANGES_COUNT; i++) + { + drawsegs_xranges[i].items = Z_Realloc( + drawsegs_xranges[i].items, + drawsegs_xrange_size * sizeof(drawsegs_xranges[i].items[0]), + PU_STATIC, NULL + ); + } + } + + for (ds = ds_p; ds-- > dsstart;) + { + if (ds->silhouette || ds->maskedtexturecol) + { + drawsegs_xranges[0].items[drawsegs_xranges[0].count].x1 = ds->x1; + drawsegs_xranges[0].items[drawsegs_xranges[0].count].x2 = ds->x2; + drawsegs_xranges[0].items[drawsegs_xranges[0].count].user = ds; + + // e6y: ~13% of speed improvement on sunder.wad map10 + if (ds->x1 < cx) + { + drawsegs_xranges[1].items[drawsegs_xranges[1].count] = + drawsegs_xranges[0].items[drawsegs_xranges[0].count]; + drawsegs_xranges[1].count++; + } + + if (ds->x2 >= cx) + { + drawsegs_xranges[2].items[drawsegs_xranges[2].count] = + drawsegs_xranges[0].items[drawsegs_xranges[0].count]; + drawsegs_xranges[2].count++; + } + + drawsegs_xranges[0].count++; + } + } + for (; clippedvissprites < visspritecount; clippedvissprites++) { vissprite_t *spr = R_GetVisSprite(clippedvissprites); - if (!(spr->cut & SC_BBOX)) // Do not clip bounding boxes + if (spr->cut & SC_BBOX) + continue; + + INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; + INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2; + + if (x2 < cx) { - INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; - INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2; - R_ClipVisSprite(spr, x1, x2, dsstart, portal); + drawsegs_xrange = drawsegs_xranges[1].items; + drawsegs_xrange_count = drawsegs_xranges[1].count; } + else if (x1 >= cx) + { + drawsegs_xrange = drawsegs_xranges[2].items; + drawsegs_xrange_count = drawsegs_xranges[2].count; + } + else + { + drawsegs_xrange = drawsegs_xranges[0].items; + drawsegs_xrange_count = drawsegs_xranges[0].count; + } + + R_ClipVisSprite(spr, x1, x2, portal); } } diff --git a/src/r_things.h b/src/r_things.h index bb8a1e97b..e11005363 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -222,7 +222,6 @@ typedef struct vissprite_s extern UINT32 visspritecount; void R_ClipSprites(drawseg_t* dsstart, portal_t* portal); -void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal); boolean R_SpriteIsFlashing(vissprite_t *vis); From e12288be3f3823e5e51c22adccd0ffbf74b7e944 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Wed, 26 Jul 2023 00:19:55 -0300 Subject: [PATCH 255/478] Move these two lines after calculating the slopes --- src/r_bbox.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_bbox.c b/src/r_bbox.c index 59d0893c4..4302d1b9a 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -129,9 +129,6 @@ draw_bbox_row x1 = a->x; x2 = b->x; - if (x2 >= viewwidth) - x2 = viewwidth - 1; - if (x1 == x2 || x1 >= viewwidth || x2 < 0) return; @@ -159,6 +156,9 @@ draw_bbox_row x1 = 0; } + if (x2 >= viewwidth) + x2 = viewwidth - 1; + while (x1 < x2) { raster_bbox_seg(x1, y1, s1, bb->color); From 29f7ecd46051884e365022bf62ce5291d7c36a06 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 18 Jul 2023 09:01:29 -0400 Subject: [PATCH 256/478] Remove P_RandomFixed call when players are moving "Add some extra randomization" is not how RNG works --- src/p_user.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 889e887c1..dcb84451b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11623,10 +11623,6 @@ void P_PlayerThink(player_t *player) cmd = &player->cmd; - // Add some extra randomization. - if (cmd->forwardmove) - P_RandomFixed(); - #ifdef PARANOIA if (player->playerstate == PST_REBORN) I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); From dc9346a45df2e5f9e7711846cd198c6d150e5537 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 26 Jul 2023 07:50:47 -0400 Subject: [PATCH 257/478] Add forwardmove rng backwards compat with demos --- src/g_demo.c | 3 +++ src/g_demo.h | 1 + src/p_user.c | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/src/g_demo.c b/src/g_demo.c index a7b9098fa..adb8e891d 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -58,6 +58,7 @@ static UINT8 demoflags; static UINT16 demoversion; boolean singledemo; // quit after playing a demo from cmdline boolean demo_start; // don't start playing demo right away +boolean demo_forwardmove_rng; // old demo backwards compatibility boolean demosynced = true; // console warning message boolean metalrecording; // recording as metal sonic @@ -2028,6 +2029,7 @@ void G_DoPlayDemo(char *defdemoname) version = READUINT8(demo_p); subversion = READUINT8(demo_p); demoversion = READUINT16(demo_p); + demo_forwardmove_rng = (demoversion < 0x0010); switch(demoversion) { case 0x000f: @@ -2339,6 +2341,7 @@ UINT8 G_CheckDemoForError(char *defdemoname) demo_p++; // version demo_p++; // subversion demoversion = READUINT16(demo_p); + demo_forwardmove_rng = (demoversion < 0x0010); switch(demoversion) { case 0x000d: diff --git a/src/g_demo.h b/src/g_demo.h index 383d2719b..379c57428 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -38,6 +38,7 @@ extern demo_file_override_e demofileoverride; // Quit after playing a demo from cmdline. extern boolean singledemo; extern boolean demo_start; +extern boolean demo_forwardmove_rng; extern boolean demosynced; extern mobj_t *metalplayback; diff --git a/src/p_user.c b/src/p_user.c index dcb84451b..1c2e4f7c9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11623,6 +11623,13 @@ void P_PlayerThink(player_t *player) cmd = &player->cmd; + if (demoplayback && demo_forwardmove_rng) + { + // Smelly demo backwards compatibility + if (cmd->forwardmove) + P_RandomFixed(); + } + #ifdef PARANOIA if (player->playerstate == PST_REBORN) I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); From 0abe55619731b0c70e05d6aed996366814d04f6f Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 5 Nov 2022 20:50:57 -0500 Subject: [PATCH 258/478] cmake: Enable C++ 17 and C11 --- src/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2f4467a32..7ec229fe0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,8 @@ if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows" AND target_link_options(SRB2SDL2 PRIVATE "-static") endif() +target_compile_features(SRB2SDL2 PRIVATE c_std_11 cxx_std_17) + # Core sources target_sourcefile(c) target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h.in) From 763912700396b9d1eba495cd084317997b1232e1 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 6 Nov 2022 01:08:43 -0600 Subject: [PATCH 259/478] cmake: Add Catch2 unit testing --- CMakeLists.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 915912af5..568789a0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ option( "Link dependencies using CMake's find_package and do not use internal builds" ${SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT} ) +option(SRB2_CONFIG_ENABLE_TESTS "Build the test suite" ON) # This option isn't recommended for distribution builds and probably won't work (yet). cmake_dependent_option( SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES @@ -76,6 +77,25 @@ option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF) option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF) set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.") +if(SRB2_CONFIG_ENABLE_TESTS) + # https://github.com/catchorg/Catch2 + CPMAddPackage( + NAME Catch2 + VERSION 3.1.1 + GITHUB_REPOSITORY catchorg/Catch2 + OPTIONS + "CATCH_INSTALL_DOCS OFF" + ) + list(APPEND CMAKE_MODULE_PATH "${Catch2_SOURCE_DIR}/extras") + include(CTest) + include(Catch) + add_executable(srb2tests) + # To add tests, use target_sources to add individual test files to the target in subdirs. + target_link_libraries(srb2tests PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) + target_compile_features(srb2tests PRIVATE c_std_11 cxx_std_17) + catch_discover_tests(srb2tests) +endif() + # Enable CCache # (Set USE_CCACHE=ON to use, CCACHE_OPTIONS for options) if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL Windows) From 2a8dbed3369afad767c23444fc55a635cd9afa26 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 13 Nov 2022 20:06:15 -0600 Subject: [PATCH 260/478] Redefine boolean for C++ compatibility --- src/CMakeLists.txt | 1 + src/doomtype.h | 58 +++++++++++++++++----------------------- src/tests/CMakeLists.txt | 3 +++ src/tests/boolcompat.cpp | 8 ++++++ 4 files changed, 37 insertions(+), 33 deletions(-) create mode 100644 src/tests/CMakeLists.txt create mode 100644 src/tests/boolcompat.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7ec229fe0..9352d55ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -291,6 +291,7 @@ if(SRB2_CONFIG_PROFILEMODE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") endif() add_subdirectory(sdl) +add_subdirectory(tests) # strip debug symbols into separate file when using gcc. # to be consistent with Makefile, don't generate for OS X. diff --git a/src/doomtype.h b/src/doomtype.h index f6c236e20..f834a3f4f 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -17,6 +17,10 @@ #ifndef __DOOMTYPE__ #define __DOOMTYPE__ +#ifdef __cplusplus +extern "C" { +#endif + #ifdef _WIN32 //#define WIN32_LEAN_AND_MEAN #define RPC_NO_WINDOWS_H @@ -100,24 +104,6 @@ char *strcasestr(const char *in, const char *what); int startswith (const char *base, const char *tag); int endswith (const char *base, const char *tag); -#if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap - #define true 1 - #define false 0 - #define min(x,y) (((x)<(y)) ? (x) : (y)) - #define max(x,y) (((x)>(y)) ? (x) : (y)) - -#ifdef macintosh - #define stricmp strcmp - #define strnicmp strncmp -#endif - - #define boolean INT32 - - #ifndef O_BINARY - #define O_BINARY 0 - #endif -#endif //macintosh - #if defined (_WIN32) || defined (__HAIKU__) #define HAVE_DOSSTR_FUNCS #endif @@ -144,22 +130,24 @@ size_t strlcpy(char *dst, const char *src, size_t siz); /* Boolean type definition */ -// \note __BYTEBOOL__ used to be set above if "macintosh" was defined, -// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now? -#ifndef __BYTEBOOL__ - #define __BYTEBOOL__ +// Note: C++ bool and C99/C11 _Bool are NOT compatible. +// Historically, boolean was win32 BOOL on Windows. For equivalence, it's now +// int32_t. "true" and "false" are only declared for C code; in C++, conversion +// between "bool" and "int32_t" takes over. +#ifndef _WIN32 +typedef int32_t boolean; +#else +#define BOOL boolean +#endif - //faB: clean that up !! - #if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward - #include "stdbool.h" - #elif defined (_WIN32) - #define false FALSE // use windows types - #define true TRUE - #define boolean BOOL - #else - typedef enum {false, true} boolean; - #endif -#endif // __BYTEBOOL__ +#ifndef __cplusplus +#ifndef _WIN32 +enum {false = 0, true = 1}; +#else +#define false FALSE +#define true TRUE +#endif +#endif /* 7.18.2.1 Limits of exact-width integer types */ @@ -387,4 +375,8 @@ unset_bit_array (bitarray_t * const array, const int value) typedef UINT64 precise_t; +#ifdef __cplusplus +} // extern "C" +#endif + #endif //__DOOMTYPE__ diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt new file mode 100644 index 000000000..28c4ce492 --- /dev/null +++ b/src/tests/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(srb2tests PRIVATE + boolcompat.cpp +) diff --git a/src/tests/boolcompat.cpp b/src/tests/boolcompat.cpp new file mode 100644 index 000000000..fee40cd36 --- /dev/null +++ b/src/tests/boolcompat.cpp @@ -0,0 +1,8 @@ +#include + +#include "../doomtype.h" + +TEST_CASE("C++ bool is convertible to doomtype.h boolean") { + REQUIRE(static_cast(true) == 1); + REQUIRE(static_cast(false) == 0); +} From 12b6a7cabfdd298e7c23d1c5030e637d224e2288 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sun, 13 Nov 2022 20:07:36 -0600 Subject: [PATCH 261/478] Don't preproc. define `inline` in C++ --- src/doomtype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doomtype.h b/src/doomtype.h index f834a3f4f..e6da5e50c 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -82,7 +82,9 @@ typedef long ssize_t; #endif #define strncasecmp strnicmp #define strcasecmp stricmp +#ifndef __cplusplus #define inline __inline +#endif #elif defined (__WATCOMC__) #include #include From 101cdea022167a6b5c7aefa2a1faa5e47d9168b4 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 5 Nov 2022 18:31:06 -0500 Subject: [PATCH 262/478] cmake: Add optional clang-tidy integration clang-tidy performs static analysis over the compilation unit, producing more comprehensive compile warnings than are normally generated by the compiler. For example, it will trace branches in a function to find the exact conditions in which a null dereference can occur. Note that this produces an absurd amount of warnings for our existing C code, and significantly slows compile times. It is pretty effective at its job though. I think it would be good to turn on by default for upcoming C++ code. --- CMakeLists.txt | 3 +++ cmake/Modules/clang-tidy-default.cmake | 21 +++++++++++++++++++++ src/CMakeLists.txt | 10 ++++++++++ 3 files changed, 34 insertions(+) create mode 100644 cmake/Modules/clang-tidy-default.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 915912af5..7fc050ea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,9 @@ else() set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT OFF) endif() +# Clang tidy options will be ignored if CMAKE__CLANG_TIDY are set. +option(SRB2_CONFIG_ENABLE_CLANG_TIDY_C "Enable default clang-tidy check configuration for C" OFF) +option(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX "Enable default clang-tidy check configuration for C++" OFF) option( SRB2_CONFIG_SYSTEM_LIBRARIES "Link dependencies using CMake's find_package and do not use internal builds" diff --git a/cmake/Modules/clang-tidy-default.cmake b/cmake/Modules/clang-tidy-default.cmake new file mode 100644 index 000000000..2be3af10d --- /dev/null +++ b/cmake/Modules/clang-tidy-default.cmake @@ -0,0 +1,21 @@ +find_program(CLANG_TIDY clang-tidy) + +# Note: Apple Clang does not ship with clang tools. If you want clang-tidy on +# macOS, it's best to install the Homebrew llvm bottle and set CLANG_TIDY +# in your build directory. The llvm package is keg-only, so it will not +# collide with Apple Clang. + +function(target_set_default_clang_tidy target lang checks) + if("${CLANG_TIDY}" STREQUAL "CLANG_TIDY-NOTFOUND") + return() + endif() + + get_target_property(c_clang_tidy_prop SRB2SDL2 C_CLANG_TIDY) + if(NOT ("${c_clang_tidy_prop}" STREQUAL "c_clang_tidy_prop-NOTFOUND")) + return() + endif() + + set_target_properties("${target}" PROPERTIES + ${lang}_CLANG_TIDY "${CLANG_TIDY};-checks=${checks}" + ) +endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2f4467a32..18c16eeb4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,5 @@ +include(clang-tidy-default) + add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32) if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows" AND NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}") @@ -329,3 +331,11 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND NOT "${SRB2_CONFIG_INTERNAL_LIBRA COMMENT "Copying runtime DLLs" ) endif() + +# Setup clang-tidy +if(SRB2_CONFIG_ENABLE_CLANG_TIDY_C) + target_set_default_clang_tidy(SRB2SDL2 C "-*,clang-analyzer-*,-clang-analyzer-cplusplus-*") +endif() +if(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX) + target_set_default_clang_tidy(SRB2SDL2 CXX "-*,clang-analyzer-*,modernize-*") +endif() From 9253a8cc549e862a9f997b18f060a9ecb1335b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Fri, 2 Jun 2023 18:49:37 +0200 Subject: [PATCH 263/478] Fix use-after-free when calling v.drawString in Lua --- src/lua_hudlib_drawlist.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index 6f83094ac..c518ba525 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -177,9 +177,18 @@ static const char *CopyString(huddrawlist_h list, const char* str) lenstr = strlen(str); if (list->strbuf_capacity <= list->strbuf_len + lenstr + 1) { + const char *old_offset = list->strbuf; + size_t i; if (list->strbuf_capacity == 0) list->strbuf_capacity = 256; else list->strbuf_capacity *= 2; list->strbuf = (char*) Z_Realloc(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL); + + // align the string pointers to make sure old pointers don't point towards invalid addresses + // this is necessary since Z_ReallocAlign might actually move the string buffer in memory + for (i = 0; i < list->items_len; i++) + { + list->items[i].str += list->strbuf - old_offset; + } } const char *result = (const char *) &list->strbuf[list->strbuf_len]; strncpy(&list->strbuf[list->strbuf_len], str, lenstr + 1); From 4bbf4c21c2cd81e402537509e68d05292d931e16 Mon Sep 17 00:00:00 2001 From: katsy <205-katsy@users.noreply.git.do.srb2.org> Date: Wed, 26 Jul 2023 12:14:21 +0000 Subject: [PATCH 264/478] Warn in console instead of hard erroring when attempting to modify a vanilla skincolor (resolves #1046) --- src/lua_infolib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 4d150347d..1144648d0 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1709,7 +1709,7 @@ static int lib_setSkinColor(lua_State *L) else if (i == 6 || (str && fastcmp(str,"accessible"))) { boolean v = lua_toboolean(L, 3); if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible) - return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); + CONS_Alert(CONS_WARNING, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); else info->accessible = v; } @@ -1804,7 +1804,7 @@ static int skincolor_set(lua_State *L) else if (fastcmp(field,"accessible")) { boolean v = lua_toboolean(L, 3); if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible) - return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); + CONS_Alert(CONS_WARNING, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); else info->accessible = v; } else From 9e5a8285089c671f827d52b8a30f9cc903445a0f Mon Sep 17 00:00:00 2001 From: tertu marybig Date: Wed, 26 Jul 2023 14:53:01 +0000 Subject: [PATCH 265/478] New M_Random implementation --- src/android/i_system.c | 22 +++++ src/d_main.c | 12 +-- src/dummy/i_system.c | 5 ++ src/i_system.h | 4 + src/lua_hudlib.c | 9 -- src/m_random.c | 192 ++++++++++++++++++++++++++++++++++++++--- src/m_random.h | 3 + src/sdl/i_system.c | 38 ++++++++ 8 files changed, 259 insertions(+), 26 deletions(-) diff --git a/src/android/i_system.c b/src/android/i_system.c index ff8b88de5..9d798d452 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -278,4 +278,26 @@ char *I_ClipboardPaste(void) void I_RegisterSysCommands(void) {} +// This is identical to the SDL implementation. +size_t I_GetRandomBytes(char *destination, size_t count) +{ + FILE *rndsource; + size_t actual_bytes; + + if (!(rndsource = fopen("/dev/urandom", "r"))) + if (!(rndsource = fopen("/dev/random", "r"))) + actual_bytes = 0; + + if (rndsource) + { + actual_bytes = fread(destination, 1, count, rndsource); + fclose(rndsource); + } + + if (actual_bytes == 0) + I_OutputMsg("I_GetRandomBytes(): couldn't get any random bytes"); + + return actual_bytes; +} + #include "../sdl/dosstr.c" diff --git a/src/d_main.c b/src/d_main.c index 5861f9886..389cdd2db 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -70,6 +70,7 @@ #include "filesrch.h" // refreshdirmenu #include "g_input.h" // tutorial mode control scheming #include "m_perfstats.h" +#include "m_random.h" #ifdef CMAKECONFIG #include "config.h" @@ -1334,11 +1335,12 @@ void D_SRB2Main(void) snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons"); I_mkdir(addonsdir, 0755); - // rand() needs seeded regardless of password - srand((unsigned int)time(NULL)); - rand(); - rand(); - rand(); + // seed M_Random because it is necessary; seed P_Random for scripts that + // might want to use random numbers immediately at start + if (!M_RandomSeedFromOS()) + M_RandomSeed((UINT32)time(NULL)); // less good but serviceable + + P_SetRandSeed(M_RandomizedSeed()); if (M_CheckParm("-password") && M_IsNextParm()) D_SetPassword(M_GetNextParm()); diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index 8556c0248..125d2e8ae 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -180,6 +180,11 @@ const char *I_ClipboardPaste(void) return NULL; } +size_t I_GetRandomBytes(char *destination, size_t amount) +{ + return 0; +} + void I_RegisterSysCommands(void) {} void I_GetCursorPosition(INT32 *x, INT32 *y) diff --git a/src/i_system.h b/src/i_system.h index deea9f8a8..834dd4091 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -49,6 +49,10 @@ size_t I_GetFreeMem(size_t *total); */ precise_t I_GetPreciseTime(void); +/** \brief Fills a buffer with random data, returns amount of data obtained. + */ +size_t I_GetRandomBytes(char *destination, size_t count); + /** \brief Get the precision of precise_t in units per second. Invocations of this function for the program's duration MUST return the same value. */ diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index c7f67e93a..2e3bb9c68 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1256,8 +1256,6 @@ static int libd_RandomKey(lua_State *L) INT32 a = (INT32)luaL_checkinteger(L, 1); HUDONLY - if (a > 65536) - LUA_UsageWarning(L, "v.RandomKey: range > 65536 is undefined behavior"); lua_pushinteger(L, M_RandomKey(a)); return 1; } @@ -1268,13 +1266,6 @@ static int libd_RandomRange(lua_State *L) INT32 b = (INT32)luaL_checkinteger(L, 2); HUDONLY - if (b < a) { - INT32 c = a; - a = b; - b = c; - } - if ((b-a+1) > 65536) - LUA_UsageWarning(L, "v.RandomRange: range > 65536 is undefined behavior"); lua_pushinteger(L, M_RandomRange(a, b)); return 1; } diff --git a/src/m_random.c b/src/m_random.c index 8b5138b9c..536fbfbbd 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -3,6 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 2022-2023 by tertu marybig. // Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the @@ -14,11 +15,122 @@ #include "doomdef.h" #include "doomtype.h" +#include "i_system.h" // I_GetRandomBytes #include "m_random.h" #include "m_fixed.h" -#include "m_cond.h" // totalplaytime +// SFC32 random number generator implementation + +typedef struct rnstate_s { + UINT32 data[3]; + UINT32 counter; +} rnstate_t; + +/** Generate a raw uniform random number using a particular state. + * + * \param state The RNG state to use. + * \return A random UINT32. + */ +static inline UINT32 RandomState_Get32(rnstate_t *state) { + UINT32 result, b, c; + + b = state->data[1]; + c = state->data[2]; + result = state->data[0] + b + state->counter++; + + state->data[0] = b ^ (b >> 9); + state->data[1] = c * 9; + state->data[2] = ((c << 21) | (c >> 11)) + result; + + return result; +} + +/** Seed an SFC32 RNG state with up to 96 bits of seed data. + * + * \param state The RNG state to seed. + * \param seeds A pointer to up to 3 UINT32s to use as seed data. + * \param seed_count The number of seed words. + */ +static inline void RandomState_Seed(rnstate_t *state, UINT32 *seeds, size_t seed_count) +{ + size_t i; + + state->counter = 1; + + for(i = 0; i < 3; i++) + { + UINT32 seed_word; + + if(i < seed_count) + seed_word = seeds[i]; + else + seed_word = 0; + + // For SFC32, seed data should be stored in the state in reverse order. + state->data[2-i] = seed_word; + } + + for(i = 0; i < 16; i++) + RandomState_Get32(state); +} + +/** Gets a uniform number in the range [0, limit). + * Technique is based on a combination of scaling and rejection sampling + * and is adapted from Daniel Lemire. + * + * \note Any UINT32 is a valid argument for limit. + * + * \param state The RNG state to use. + * \param limit The upper limit of the range. + * \return A UINT32 in the range [0, limit). + */ +static inline UINT32 RandomState_GetKey32(rnstate_t *state, const UINT32 limit) +{ + UINT32 raw_random, scaled_lower_word; + UINT64 scaled_random; + + // This algorithm won't work correctly if passed a 0. + if (limit == 0) return 0; + + raw_random = RandomState_Get32(state); + scaled_random = (UINT64)raw_random * (UINT64)limit; + + /*The high bits of scaled_random now contain the number we want, but it is + possible, depending on the number we generated and the value of limit, + that there is bias in the result. The rest of this code is for ensuring + that does not happen. + */ + scaled_lower_word = (UINT32)scaled_random; + + // If we're lucky, we can bail out now and avoid the division + if (scaled_lower_word < limit) + { + // Scale the limit to improve the chance of success. + // After this, the first result might turn out to be good enough. + UINT32 scaled_limit; + // An explanation for this trick: scaled_limit should be + // (UINT32_MAX+1)%range, but if that was computed directly the result + // would need to be computed as a UINT64. This trick allows it to be + // computed using 32-bit arithmetic. + scaled_limit = (-limit) % limit; + + while (scaled_lower_word < scaled_limit) + { + raw_random = RandomState_Get32(state); + scaled_random = (UINT64)raw_random * (UINT64)limit; + scaled_lower_word = (UINT32)scaled_random; + } + } + + return scaled_random >> 32; +} + +// The default seed is the hexadecimal digits of pi, though it will be overwritten. +static rnstate_t m_randomstate = { + .data = {0x4A3B6035U, 0x99555606U, 0x6F603421U}, + .counter = 16 +}; // --------------------------- // RNG functions (not synched) @@ -31,13 +143,7 @@ */ fixed_t M_RandomFixed(void) { -#if RAND_MAX < 65535 - // Compensate for insufficient randomness. - fixed_t rndv = (rand()&1)<<15; - return rand()^rndv; -#else - return (rand() & 0xFFFF); -#endif + return RandomState_Get32(&m_randomstate) >> (32-FRACBITS); } /** Provides a random byte. Distribution is uniform. @@ -47,7 +153,7 @@ fixed_t M_RandomFixed(void) */ UINT8 M_RandomByte(void) { - return (rand() & 0xFF); + return RandomState_Get32(&m_randomstate) >> 24; } /** Provides a random integer for picking random elements from an array. @@ -59,7 +165,22 @@ UINT8 M_RandomByte(void) */ INT32 M_RandomKey(INT32 a) { - return (INT32)((rand()/((float)RAND_MAX+1.0f))*a); + boolean range_is_negative; + INT64 range; + INT32 random_result; + + range = a; + range_is_negative = range < 0; + + if(range_is_negative) + range = -range; + + random_result = RandomState_GetKey32(&m_randomstate, (UINT32)range); + + if(range_is_negative) + random_result = -random_result; + + return random_result; } /** Provides a random integer in a given range. @@ -72,7 +193,46 @@ INT32 M_RandomKey(INT32 a) */ INT32 M_RandomRange(INT32 a, INT32 b) { - return (INT32)((rand()/((float)RAND_MAX+1.0f))*(b-a+1))+a; + if (b < a) + { + INT32 temp; + + temp = a; + a = b; + b = temp; + } + + const UINT32 spread = b-a+1; + return (INT32)((INT64)RandomState_GetKey32(&m_randomstate, spread) + a); +} + +/** Attempts to seed the unsynched RNG from a good random number source + * provided by the operating system. + * \return true on success, false on failure. + */ +boolean M_RandomSeedFromOS(void) +{ + UINT32 complete_word_count; + + union { + UINT32 words[3]; + char bytes[sizeof(UINT32[3])]; + } seed_data; + + complete_word_count = I_GetRandomBytes((char *)&seed_data.bytes, sizeof(seed_data)) / sizeof(UINT32); + + // If we get even 1 word of seed, it's fine, but any less probably is not fine. + if (complete_word_count == 0) + return false; + + RandomState_Seed(&m_randomstate, (UINT32 *)&seed_data.words, complete_word_count); + + return true; +} + +void M_RandomSeed(UINT32 seed) +{ + RandomState_Seed(&m_randomstate, &seed, 1); } @@ -246,10 +406,18 @@ void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed) } /** Gets a randomized seed for setting the random seed. + * This function will never return 0, as the current P_Random implementation + * cannot handle a zero seed. Any other seed is equally likely. * * \sa P_GetRandSeed */ UINT32 M_RandomizedSeed(void) { - return ((serverGamedata->totalplaytime & 0xFFFF) << 16) | M_RandomFixed(); + UINT32 seed; + + do { + seed = RandomState_Get32(&m_randomstate); + } while(seed == 0); + + return seed; } diff --git a/src/m_random.h b/src/m_random.h index 824287e27..a7c07a46b 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -3,6 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 2022-2023 by tertu marybig. // Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the @@ -29,6 +30,8 @@ fixed_t M_RandomFixed(void); UINT8 M_RandomByte(void); INT32 M_RandomKey(INT32 a); INT32 M_RandomRange(INT32 a, INT32 b); +boolean M_RandomSeedFromOS(void); +void M_RandomSeed(UINT32 a); // PRNG functions #ifdef DEBUGRANDOM diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 847ab2646..c21226ac3 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -41,6 +41,12 @@ typedef DWORD (WINAPI *p_timeGetTime) (void); typedef UINT (WINAPI *p_timeEndPeriod) (UINT); typedef HANDLE (WINAPI *p_OpenFileMappingA) (DWORD, BOOL, LPCSTR); typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); + +// This is for RtlGenRandom. +#define SystemFunction036 NTAPI SystemFunction036 +#include +#undef SystemFunction036 + #endif #include #include @@ -2776,6 +2782,38 @@ INT32 I_PutEnv(char *variable) #endif } +size_t I_GetRandomBytes(char *destination, size_t count) +{ +#if defined (__unix__) || defined (UNIXCOMMON) || defined(__APPLE__) + FILE *rndsource; + size_t actual_bytes; + + if (!(rndsource = fopen("/dev/urandom", "r"))) + if (!(rndsource = fopen("/dev/random", "r"))) + actual_bytes = 0; + + if (rndsource) + { + actual_bytes = fread(destination, 1, count, rndsource); + fclose(rndsource); + } + + if (actual_bytes == 0) + I_OutputMsg("I_GetRandomBytes(): couldn't get any random bytes"); + + return actual_bytes; +#elif defined (_WIN32) + if (RtlGenRandom(destination, count)) + return count; + + I_OutputMsg("I_GetRandomBytes(): couldn't get any random bytes"); + return 0; +#else + #warning SDL I_GetRandomBytes is not implemented on this platform. + return 0; +#endif +} + INT32 I_ClipboardCopy(const char *data, size_t size) { char storage[256]; From 42bf107b71f157058ae0a57d40d2d85a0d5c52ae Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 15 Dec 2022 20:54:15 -0500 Subject: [PATCH 266/478] #define BOOL boolean -> #define boolean BOOL --- src/doomtype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomtype.h b/src/doomtype.h index e6da5e50c..c59e17381 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -139,7 +139,7 @@ size_t strlcpy(char *dst, const char *src, size_t siz); #ifndef _WIN32 typedef int32_t boolean; #else -#define BOOL boolean +#define boolean BOOL #endif #ifndef __cplusplus From 91e915b963456c1a26ea6951ba96aa4c54f0780c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 26 Jul 2023 13:44:43 -0400 Subject: [PATCH 267/478] Fix recordscore not including intermission bonuses --- src/y_inter.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/y_inter.c b/src/y_inter.c index 6e7d362a7..1b1f49e0b 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -2065,6 +2065,9 @@ static void Y_AwardCoopBonuses(void) players[i].score += localbonuses[j].points; if (players[i].score > MAXSCORE) players[i].score = MAXSCORE; + players[i].recordscore += localbonuses[j].points; + if (players[i].recordscore > MAXSCORE) + players[i].recordscore = MAXSCORE; } ptlives = min( @@ -2121,6 +2124,10 @@ static void Y_AwardSpecialStageBonus(void) players[i].score += localbonuses[1].points; if (players[i].score > MAXSCORE) players[i].score = MAXSCORE; + players[i].recordscore += localbonuses[0].points; + players[i].recordscore += localbonuses[1].points; + if (players[i].recordscore > MAXSCORE) + players[i].recordscore = MAXSCORE; // grant extra lives right away since tally is faked ptlives = min( From dc103330ac4b9f177307b7a25a178420803d1278 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 30 Dec 2022 20:17:26 -0800 Subject: [PATCH 268/478] Rename strcasestr to nongnu_strcasestr, macro strcasestr ifndef _GNU_SOURCE Fix for GCC C++ compiler, which always defines _GNU_SOURCE. --- src/doomtype.h | 5 ++++- src/strcasestr.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index c59e17381..617fd4d47 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -100,7 +100,10 @@ typedef long ssize_t; #define strnicmp(x,y,n) strncasecmp(x,y,n) #endif -char *strcasestr(const char *in, const char *what); +char *nongnu_strcasestr(const char *in, const char *what); +#ifndef _GNU_SOURCE +#define strcasestr nongnu_strcasestr +#endif #define stristr strcasestr int startswith (const char *base, const char *tag); diff --git a/src/strcasestr.c b/src/strcasestr.c index 2796f11d5..37899a842 100644 --- a/src/strcasestr.c +++ b/src/strcasestr.c @@ -61,7 +61,7 @@ swapp (char ***ppap, char ***ppbp, char **cpap, char **cpbp) } char * -strcasestr (const char *s, const char *q) +nongnu_strcasestr (const char *s, const char *q) { size_t qn; From 34f2594b4826a200ca50ecbf62652d5ffa181617 Mon Sep 17 00:00:00 2001 From: SteelT Date: Wed, 26 Jul 2023 14:09:48 -0400 Subject: [PATCH 269/478] Update Catch2 to latest version This combined with the previous commit fixes building the test suite --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a21d22b34..7d36c1fb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,7 +84,7 @@ if(SRB2_CONFIG_ENABLE_TESTS) # https://github.com/catchorg/Catch2 CPMAddPackage( NAME Catch2 - VERSION 3.1.1 + VERSION 3.4.0 GITHUB_REPOSITORY catchorg/Catch2 OPTIONS "CATCH_INSTALL_DOCS OFF" From 7261db1eee9ee02fceb52c54265c233b0fff3ca5 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 20 Feb 2023 02:15:50 -0800 Subject: [PATCH 270/478] cmake: fix -DSRB2_CONFIG_ENABLE_TESTS=OFF build --- src/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f3ed96f89..b62237374 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -293,7 +293,9 @@ if(SRB2_CONFIG_PROFILEMODE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") endif() add_subdirectory(sdl) -add_subdirectory(tests) +if(SRB2_CONFIG_ENABLE_TESTS) + add_subdirectory(tests) +endif() # strip debug symbols into separate file when using gcc. # to be consistent with Makefile, don't generate for OS X. From d01f25d91dff89f318801962f53b8bd966c13078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Wed, 26 Jul 2023 23:18:07 +0200 Subject: [PATCH 271/478] Fix FreeBSD build errors --- src/Makefile.d/nix.mk | 2 +- src/sdl/i_system.c | 43 ++++++++++--------------------------------- 2 files changed, 11 insertions(+), 34 deletions(-) diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk index 767b64c12..728795771 100644 --- a/src/Makefile.d/nix.mk +++ b/src/Makefile.d/nix.mk @@ -29,7 +29,7 @@ endif # Tested by Steel, as of release 2.2.8. ifdef FREEBSD opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD -libs+=-L/usr/X11R6/lib -lipx -lkvm +libs+=-L/usr/X11R6/lib -lkvm -lexecinfo endif # FIXME: UNTESTED diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index c21226ac3..3616300c1 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -96,7 +96,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif #include -#include +#include #endif #endif @@ -3037,40 +3037,17 @@ static long get_entry(const char* name, const char* buf) size_t I_GetFreeMem(size_t *total) { #ifdef FREEBSD - struct vmmeter sum; - kvm_t *kd; - struct nlist namelist[] = - { -#define X_SUM 0 - {"_cnt"}, - {NULL} - }; - if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) - { - if (total) - *total = 0L; - return 0; - } - if (kvm_nlist(kd, namelist) != 0) - { - kvm_close (kd); - if (total) - *total = 0L; - return 0; - } - if (kvm_read(kd, namelist[X_SUM].n_value, &sum, - sizeof (sum)) != sizeof (sum)) - { - kvm_close(kd); - if (total) - *total = 0L; - return 0; - } - kvm_close(kd); + u_int v_free_count, v_page_size, v_page_count; + size_t size = sizeof(v_free_count); + sysctlbyname("vm.stat.vm.v_free_count", &v_free_count, &size, NULL, 0); + size_t size = sizeof(v_page_size); + sysctlbyname("vm.stat.vm.v_page_size", &v_page_size, &size, NULL, 0); + size_t size = sizeof(v_page_count); + sysctlbyname("vm.stat.vm.v_page_count", &v_page_count, &size, NULL, 0); if (total) - *total = sum.v_page_count * sum.v_page_size; - return sum.v_free_count * sum.v_page_size; + *total = v_page_count * v_page_size; + return v_free_count * v_page_size; #elif defined (SOLARIS) /* Just guess */ if (total) From 97311dc5b00ab232a6e898c085c20d2f6bdbfa3b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Thu, 27 Jul 2023 19:15:35 -0300 Subject: [PATCH 272/478] Use separate table for maskedtexturecol --- src/r_defs.h | 4 +- src/r_main.c | 1 + src/r_plane.c | 6 - src/r_plane.h | 3 - src/r_segs.c | 729 +++++++++++++++++++++++++------------------------- src/r_segs.h | 1 + 6 files changed, 365 insertions(+), 379 deletions(-) diff --git a/src/r_defs.h b/src/r_defs.h index a9b9a4a08..dfd2d6d70 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -757,12 +757,12 @@ typedef struct drawseg_s // Pointers to lists for sprite clipping, all three adjusted so [x1] is first value. INT16 *sprtopclip; INT16 *sprbottomclip; - INT16 *maskedtexturecol; + fixed_t *maskedtexturecol; struct visplane_s *ffloorplanes[MAXFFLOORS]; INT32 numffloorplanes; struct ffloor_s *thicksides[MAXFFLOORS]; - INT16 *thicksidecol; + fixed_t *thicksidecol; INT32 numthicksides; fixed_t frontscale[MAXVIDWIDTH]; diff --git a/src/r_main.c b/src/r_main.c index 55bb9c4ff..952171405 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1479,6 +1479,7 @@ void R_RenderPlayerView(player_t *player) R_ClearClipSegs(); } R_ClearDrawSegs(); + R_ClearSegTables(); R_ClearSprites(); Portal_InitList(); diff --git a/src/r_plane.c b/src/r_plane.c index c568484b6..29ce26b29 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -53,10 +53,6 @@ INT32 numffloors; #define visplane_hash(picnum,lightlevel,height) \ ((unsigned)((picnum)*3+(lightlevel)+(height)*7) & VISPLANEHASHMASK) -//SoM: 3/23/2000: Use boom opening limit removal -size_t maxopenings; -INT16 *openings, *lastopening; /// \todo free leak - // // Clip values are the solid pixel bounding the range. // floorclip starts out SCREENHEIGHT @@ -366,8 +362,6 @@ void R_ClearPlanes(void) freehead = &(*freehead)->next; } - lastopening = openings; - // texture calculation memset(cachedheight, 0, sizeof (cachedheight)); } diff --git a/src/r_plane.h b/src/r_plane.h index 9870a43e2..917e8b041 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -60,9 +60,6 @@ extern visplane_t *floorplane; extern visplane_t *ceilingplane; // Visplane related. -extern INT16 *lastopening, *openings; -extern size_t maxopenings; - extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH]; extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16]; extern fixed_t cachedheight[MAXVIDHEIGHT]; diff --git a/src/r_segs.c b/src/r_segs.c index facab62ab..9ee3bcfec 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -71,9 +71,22 @@ static fixed_t topfrac, topstep; static fixed_t bottomfrac, bottomstep; static lighttable_t **walllights; -static INT16 *maskedtexturecol; +static fixed_t *maskedtexturecol; static fixed_t *maskedtextureheight = NULL; +//SoM: 3/23/2000: Use boom opening limit removal +static size_t numopenings; +static INT16 *openings, *lastopening; + +static size_t texturecolumntablesize; +static fixed_t *texturecolumntable, *curtexturecolumntable; + +void R_ClearSegTables(void) +{ + lastopening = openings; + curtexturecolumntable = texturecolumntable; +} + // ========================================================================== // R_RenderMaskedSegRange // ========================================================================== @@ -350,170 +363,115 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; else dc_texturemid -= (textureheight[texnum])*times; - // calculate lighting - if (maskedtexturecol[dc_x] != INT16_MAX) + + // Check for overflows first + overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) { - // Check for overflows first - overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); - if (overflow_test < 0) overflow_test = -overflow_test; - if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) + // Eh, no, go away, don't waste our time + if (dc_numlights) { - // Eh, no, go away, don't waste our time - if (dc_numlights) + for (i = 0; i < dc_numlights; i++) { - for (i = 0; i < dc_numlights; i++) + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + } + } + spryscale += rw_scalestep; + continue; + } + + // calculate lighting + if (dc_numlights) + { + lighttable_t **xwalllights; + + sprbotscreen = INT32_MAX; + sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); + + realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); + + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + + if ((rlight->flags & FOF_NOSHADE)) + continue; + + if (rlight->lightnum < 0) + xwalllights = scalelight[0]; + else if (rlight->lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[rlight->lightnum]; + + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + + height = rlight->height; + rlight->height += rlight->heightstep; + + if (height <= windowtop) + { + dc_colormap = rlight->rcolormap; + continue; + } + + windowbottom = height; + if (windowbottom >= realbot) + { + windowbottom = realbot; + colfunc_2s(col); + for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; rlight->height += rlight->heightstep; } + + continue; } - spryscale += rw_scalestep; - continue; - } - - if (dc_numlights) - { - lighttable_t **xwalllights; - - sprbotscreen = INT32_MAX; - sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - - realbot = windowbottom = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - - for (i = 0; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - - if ((rlight->flags & FOF_NOSHADE)) - continue; - - if (rlight->lightnum < 0) - xwalllights = scalelight[0]; - else if (rlight->lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[rlight->lightnum]; - - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - - height = rlight->height; - rlight->height += rlight->heightstep; - - if (height <= windowtop) - { - dc_colormap = rlight->rcolormap; - continue; - } - - windowbottom = height; - if (windowbottom >= realbot) - { - windowbottom = realbot; - colfunc_2s(col); - for (i++; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - } - - continue; - } - colfunc_2s(col); - windowtop = windowbottom + 1; - dc_colormap = rlight->rcolormap; - } - windowbottom = realbot; - if (windowtop < windowbottom) - colfunc_2s(col); - - spryscale += rw_scalestep; - continue; - } - - // calculate lighting - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - dc_colormap = walllights[pindex]; - - if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - - sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // draw the texture - col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - -#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red - if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) - { - fixed_t my_topscreen; - fixed_t my_bottomscreen; - fixed_t my_yl, my_yh; - - my_topscreen = sprtopscreen + spryscale*col->topdelta; - my_bottomscreen = sprbotscreen == INT32_MAX ? my_topscreen + spryscale*col->length - : sprbotscreen + spryscale*col->length; - - my_yl = (my_topscreen+FRACUNIT-1)>>FRACBITS; - my_yh = (my_bottomscreen-1)>>FRACBITS; - // CONS_Debug(DBG_RENDER, "my_topscreen: %d\nmy_bottomscreen: %d\nmy_yl: %d\nmy_yh: %d\n", my_topscreen, my_bottomscreen, my_yl, my_yh); - - if (numffloors) - { - INT32 top = my_yl; - INT32 bottom = my_yh; - - for (i = 0; i < numffloors; i++) - { - if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg) - continue; - - if (ffloor[i].height < viewz) - { - INT32 top_w = ffloor[i].plane->top[dc_x]; - - // CONS_Debug(DBG_RENDER, "Leveltime : %d\n", leveltime); - // CONS_Debug(DBG_RENDER, "Top is %d, top_w is %d\n", top, top_w); - if (top_w < top) - { - ffloor[i].plane->top[dc_x] = (INT16)top; - ffloor[i].plane->picnum = 0; - } - // CONS_Debug(DBG_RENDER, "top_w is now %d\n", ffloor[i].plane->top[dc_x]); - } - else if (ffloor[i].height > viewz) - { - INT32 bottom_w = ffloor[i].plane->bottom[dc_x]; - - if (bottom_w > bottom) - { - ffloor[i].plane->bottom[dc_x] = (INT16)bottom; - ffloor[i].plane->picnum = 0; - } - } - } - } - } - else -#endif colfunc_2s(col); + windowtop = windowbottom + 1; + dc_colormap = rlight->rcolormap; + } + windowbottom = realbot; + if (windowtop < windowbottom) + colfunc_2s(col); + + spryscale += rw_scalestep; + continue; } + + // calculate lighting + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + dc_colormap = walllights[pindex]; + + if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // draw the texture + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); + colfunc_2s(col); + spryscale += rw_scalestep; } } @@ -857,183 +815,182 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // draw the columns for (dc_x = x1; dc_x <= x2; dc_x++) { - if (maskedtexturecol[dc_x] != INT16_MAX) + // skew FOF walls + if (ffloortextureslide) { - if (ffloortextureslide) { // skew FOF walls - if (oldx != -1) - dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])< (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; - else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; - else sprtopscreen = windowtop = CLAMPMIN; - if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; - else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; - else sprbotscreen = windowbottom = CLAMPMIN; + // Calculate bounds + // clamp the values if necessary to avoid overflows and rendering glitches caused by them + if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; + else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; + else sprtopscreen = windowtop = CLAMPMIN; + if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; + else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; + else sprbotscreen = windowbottom = CLAMPMIN; - top_frac += top_step; - bottom_frac += bottom_step; + top_frac += top_step; + bottom_frac += bottom_step; - // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) + // SoM: If column is out of range, why bother with it?? + if (windowbottom < topbounds || windowtop > bottombounds) + { + if (dc_numlights) { - if (dc_numlights) + for (i = 0; i < dc_numlights; i++) { - for (i = 0; i < dc_numlights; i++) + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + if (rlight->flags & FOF_CUTLEVEL) + rlight->botheight += rlight->botheightstep; + } + } + spryscale += rw_scalestep; + continue; + } + + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // Get data for the column + col = (column_t *)((UINT8 *)R_GetColumn(texnum, (maskedtexturecol[dc_x] >> FRACBITS)) - 3); + + // SoM: New code does not rely on R_DrawColumnShadowed_8 which + // will (hopefully) put less strain on the stack. + if (dc_numlights) + { + lighttable_t **xwalllights; + fixed_t height; + fixed_t bheight = 0; + INT32 solid = 0; + INT32 lighteffect = 0; + + for (i = 0; i < dc_numlights; i++) + { + // Check if the current light effects the colormap/lightlevel + rlight = &dc_lightlist[i]; + lighteffect = !(dc_lightlist[i].flags & FOF_NOSHADE); + if (lighteffect) + { + lightnum = rlight->lightnum; + + if (lightnum < 0) + xwalllights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + xwalllights = scalelight[LIGHTLEVELS-1]; + else + xwalllights = scalelight[lightnum]; + + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE-1; + + if (pfloor->fofflags & FOF_FOG) + { + if (pfloor->master->frontsector->extra_colormap) + rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + } + else + { + if (rlight->extra_colormap) + rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); + else + rlight->rcolormap = xwalllights[pindex]; + } + } + + solid = 0; // don't carry over solid-cutting flag from the previous light + + // Check if the current light can cut the current 3D floor. + if (rlight->flags & FOF_CUTSOLIDS && !(pfloor->fofflags & FOF_EXTRA)) + solid = 1; + else if (rlight->flags & FOF_CUTEXTRA && pfloor->fofflags & FOF_EXTRA) + { + if (rlight->flags & FOF_EXTRA) + { + // The light is from an extra 3D floor... Check the flags so + // there are no undesired cuts. + if ((rlight->flags & (FOF_FOG|FOF_SWIMMABLE)) == (pfloor->fofflags & (FOF_FOG|FOF_SWIMMABLE))) + solid = 1; + } + else + solid = 1; + } + else + solid = 0; + + height = rlight->height; + rlight->height += rlight->heightstep; + + if (solid) + { + bheight = rlight->botheight - (FRACUNIT >> 1); + rlight->botheight += rlight->botheightstep; + } + + if (height <= windowtop) + { + if (lighteffect) + dc_colormap = rlight->rcolormap; + if (solid && windowtop < bheight) + windowtop = bheight; + continue; + } + + windowbottom = height; + if (windowbottom >= sprbotscreen) + { + windowbottom = sprbotscreen; + // draw the texture + colfunc_2s (col); + for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; rlight->height += rlight->heightstep; if (rlight->flags & FOF_CUTLEVEL) rlight->botheight += rlight->botheightstep; } + continue; } - spryscale += rw_scalestep; - continue; + // draw the texture + colfunc_2s (col); + if (solid) + windowtop = bheight; + else + windowtop = windowbottom + 1; + if (lighteffect) + dc_colormap = rlight->rcolormap; } + windowbottom = sprbotscreen; + // draw the texture, if there is any space left + if (windowtop < windowbottom) + colfunc_2s (col); - dc_iscale = 0xffffffffu / (unsigned)spryscale; - - // Get data for the column - col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); - - // SoM: New code does not rely on R_DrawColumnShadowed_8 which - // will (hopefully) put less strain on the stack. - if (dc_numlights) - { - lighttable_t **xwalllights; - fixed_t height; - fixed_t bheight = 0; - INT32 solid = 0; - INT32 lighteffect = 0; - - for (i = 0; i < dc_numlights; i++) - { - // Check if the current light effects the colormap/lightlevel - rlight = &dc_lightlist[i]; - lighteffect = !(dc_lightlist[i].flags & FOF_NOSHADE); - if (lighteffect) - { - lightnum = rlight->lightnum; - - if (lightnum < 0) - xwalllights = scalelight[0]; - else if (lightnum >= LIGHTLEVELS) - xwalllights = scalelight[LIGHTLEVELS-1]; - else - xwalllights = scalelight[lightnum]; - - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE-1; - - if (pfloor->fofflags & FOF_FOG) - { - if (pfloor->master->frontsector->extra_colormap) - rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } - else - { - if (rlight->extra_colormap) - rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps); - else - rlight->rcolormap = xwalllights[pindex]; - } - } - - solid = 0; // don't carry over solid-cutting flag from the previous light - - // Check if the current light can cut the current 3D floor. - if (rlight->flags & FOF_CUTSOLIDS && !(pfloor->fofflags & FOF_EXTRA)) - solid = 1; - else if (rlight->flags & FOF_CUTEXTRA && pfloor->fofflags & FOF_EXTRA) - { - if (rlight->flags & FOF_EXTRA) - { - // The light is from an extra 3D floor... Check the flags so - // there are no undesired cuts. - if ((rlight->flags & (FOF_FOG|FOF_SWIMMABLE)) == (pfloor->fofflags & (FOF_FOG|FOF_SWIMMABLE))) - solid = 1; - } - else - solid = 1; - } - else - solid = 0; - - height = rlight->height; - rlight->height += rlight->heightstep; - - if (solid) - { - bheight = rlight->botheight - (FRACUNIT >> 1); - rlight->botheight += rlight->botheightstep; - } - - if (height <= windowtop) - { - if (lighteffect) - dc_colormap = rlight->rcolormap; - if (solid && windowtop < bheight) - windowtop = bheight; - continue; - } - - windowbottom = height; - if (windowbottom >= sprbotscreen) - { - windowbottom = sprbotscreen; - // draw the texture - colfunc_2s (col); - for (i++; i < dc_numlights; i++) - { - rlight = &dc_lightlist[i]; - rlight->height += rlight->heightstep; - if (rlight->flags & FOF_CUTLEVEL) - rlight->botheight += rlight->botheightstep; - } - continue; - } - // draw the texture - colfunc_2s (col); - if (solid) - windowtop = bheight; - else - windowtop = windowbottom + 1; - if (lighteffect) - dc_colormap = rlight->rcolormap; - } - windowbottom = sprbotscreen; - // draw the texture, if there is any space left - if (windowtop < windowbottom) - colfunc_2s (col); - - spryscale += rw_scalestep; - continue; - } - - // calculate lighting - pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; - - if (pindex >= MAXLIGHTSCALE) - pindex = MAXLIGHTSCALE - 1; - - dc_colormap = walllights[pindex]; - - if (pfloor->fofflags & FOF_FOG && pfloor->master->frontsector->extra_colormap) - dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - else if (frontsector->extra_colormap) - dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - - // draw the texture - colfunc_2s (col); spryscale += rw_scalestep; + continue; } + + // calculate lighting + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; + + if (pindex >= MAXLIGHTSCALE) + pindex = MAXLIGHTSCALE - 1; + + dc_colormap = walllights[pindex]; + + if (pfloor->fofflags & FOF_FOG && pfloor->master->frontsector->extra_colormap) + dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + else if (frontsector->extra_colormap) + dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); + + // draw the texture + colfunc_2s (col); + spryscale += rw_scalestep; } colfunc = colfuncs[BASEDRAWFUNC]; @@ -1270,7 +1227,7 @@ static void R_RenderSegLoop (void) } oldtexturecolumn = texturecolumn; - texturecolumn >>= FRACBITS; + INT32 itexturecolumn = texturecolumn >> FRACBITS; // texturecolumn and lighting are independent of wall tiers if (segtextured) @@ -1336,7 +1293,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; - dc_source = R_GetColumn(midtexture,texturecolumn + (rw_offset_mid>>FRACBITS)); + dc_source = R_GetColumn(midtexture, itexturecolumn + (rw_offset_mid>>FRACBITS)); dc_texheight = textureheight[midtexture]>>FRACBITS; //profile stuff --------------------------------------------------------- @@ -1397,7 +1354,7 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; - dc_source = R_GetColumn(toptexture,texturecolumn + (rw_offset_top>>FRACBITS)); + dc_source = R_GetColumn(toptexture, itexturecolumn + (rw_offset_top>>FRACBITS)); dc_texheight = textureheight[toptexture]>>FRACBITS; colfunc(); ceilingclip[rw_x] = (INT16)mid; @@ -1433,8 +1390,7 @@ static void R_RenderSegLoop (void) dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; - dc_source = R_GetColumn(bottomtexture, - texturecolumn + (rw_offset_bot>>FRACBITS)); + dc_source = R_GetColumn(bottomtexture, itexturecolumn + (rw_offset_bot>>FRACBITS)); dc_texheight = textureheight[bottomtexture]>>FRACBITS; colfunc(); floorclip[rw_x] = (INT16)mid; @@ -1453,7 +1409,7 @@ static void R_RenderSegLoop (void) { // save texturecol // for backdrawing of masked mid texture - maskedtexturecol[rw_x] = (INT16)(texturecolumn + (rw_offset_mid>>FRACBITS)); + maskedtexturecol[rw_x] = texturecolumn + rw_offset_mid; if (maskedtextureheight != NULL) { maskedtextureheight[rw_x] = (curline->linedef->flags & ML_MIDPEG) ? @@ -1512,6 +1468,67 @@ static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2) } } +//SoM: Code to remove limits on openings. +static void R_AllocClippingTables(size_t range) +{ + size_t pos = lastopening - openings; + size_t need = range * 2; // for both sprtopclip and sprbottomclip + + if (pos + need < numopenings) + return; + + INT16 *oldopenings = openings; + INT16 *oldlast = lastopening; + + if (numopenings == 0) + numopenings = 16384; + + numopenings += need; + openings = Z_Realloc(openings, numopenings * sizeof (*openings), PU_STATIC, NULL); + lastopening = openings + pos; + + // borrowed fix from *cough* zdoom *cough* + // [RH] We also need to adjust the openings pointers that + // were already stored in drawsegs. + for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) + { + // Check if it's in range of the openings + if (ds->sprtopclip + ds->x1 >= oldopenings && ds->sprtopclip + ds->x1 <= oldlast) + ds->sprtopclip = (ds->sprtopclip - oldopenings) + openings; + if (ds->sprbottomclip + ds->x1 >= oldopenings && ds->sprbottomclip + ds->x1 <= oldlast) + ds->sprbottomclip = (ds->sprbottomclip - oldopenings) + openings; + } +} + +static void R_AllocTextureColumnTables(size_t range) +{ + size_t pos = curtexturecolumntable - texturecolumntable; + + // For both tables, we reserve exactly an amount of memory that's equivalent to + // how many columns the seg will take on the entire screen (think about it) + if (pos + range < texturecolumntablesize) + return; + + fixed_t *oldtable = texturecolumntable; + fixed_t *oldlast = curtexturecolumntable; + + if (texturecolumntablesize == 0) + texturecolumntablesize = 16384; + + texturecolumntablesize += range; + texturecolumntable = Z_Realloc(texturecolumntable, texturecolumntablesize * sizeof (*texturecolumntable), PU_STATIC, NULL); + curtexturecolumntable = texturecolumntable + pos; + + for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) + { + // Check if it's in range of the tables + if (ds->maskedtexturecol + ds->x1 >= oldtable && ds->maskedtexturecol + ds->x1 <= oldlast) + ds->maskedtexturecol = (ds->maskedtexturecol - oldtable) + texturecolumntable; + if (ds->thicksidecol + ds->x1 >= oldtable && ds->thicksidecol + ds->x1 <= oldlast) + ds->thicksidecol = (ds->thicksidecol - oldtable) + texturecolumntable; + } +} + // // R_StoreWallRange // A wall segment will be drawn @@ -1580,37 +1597,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->curline = curline; rw_stopx = stop+1; - //SoM: Code to remove limits on openings. - { - size_t pos = lastopening - openings; - size_t need = (rw_stopx - start)*4 + pos; - if (need > maxopenings) - { - drawseg_t *ds; //needed for fix from *cough* zdoom *cough* - INT16 *oldopenings = openings; - INT16 *oldlast = lastopening; - - do - maxopenings = maxopenings ? maxopenings*2 : 16384; - while (need > maxopenings); - openings = Z_Realloc(openings, maxopenings * sizeof (*openings), PU_STATIC, NULL); - lastopening = openings + pos; - - // borrowed fix from *cough* zdoom *cough* - // [RH] We also need to adjust the openings pointers that - // were already stored in drawsegs. - for (ds = drawsegs; ds < ds_p; ds++) - { -#define ADJUST(p) if (ds->p + ds->x1 >= oldopenings && ds->p + ds->x1 <= oldlast) ds->p = ds->p - oldopenings + openings; - ADJUST(maskedtexturecol); - ADJUST(sprtopclip); - ADJUST(sprbottomclip); - ADJUST(thicksidecol); -#undef ADJUST - } - } - } // end of code to remove limits on openings - // calculate scale at both ends and step ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); @@ -2026,6 +2012,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_toptexturemid += sidedef->rowoffset + sidedef->offsety_top; rw_bottomtexturemid += sidedef->rowoffset + sidedef->offsety_bot; + R_AllocTextureColumnTables(rw_stopx - start); + // allocate space for masked texture tables if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) { @@ -2040,8 +2028,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) //markceiling = markfloor = true; maskedtexture = true; - ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; + ds_p->thicksidecol = maskedtexturecol = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; lowcut = max(worldbottom, worldlow) + viewz; highcut = min(worldtop, worldhigh) + viewz; @@ -2224,8 +2212,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) // masked midtexture if (!ds_p->thicksidecol) { - ds_p->maskedtexturecol = maskedtexturecol = lastopening - rw_x; - lastopening += rw_stopx - rw_x; + ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; } else ds_p->maskedtexturecol = ds_p->thicksidecol; @@ -2737,29 +2725,34 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->portalpass = 0; // save sprite clipping info - if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM))) { - M_Memcpy(lastopening, ceilingclip+start, 2*(rw_stopx - start)); - ds_p->sprtopclip = lastopening - start; - lastopening += rw_stopx - start; - } + R_AllocClippingTables(rw_stopx - start); - if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) - { - M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx-start)); - ds_p->sprbottomclip = lastopening - start; - lastopening += rw_stopx - start; + if (((ds_p->silhouette & SIL_TOP) || maskedtexture) && !ds_p->sprtopclip) + { + M_Memcpy(lastopening, ceilingclip + start, 2*(rw_stopx - start)); + ds_p->sprtopclip = lastopening - start; + lastopening += rw_stopx - start; + } + + if (((ds_p->silhouette & SIL_BOTTOM) || maskedtexture) && !ds_p->sprbottomclip) + { + M_Memcpy(lastopening, floorclip + start, 2*(rw_stopx - start)); + ds_p->sprbottomclip = lastopening - start; + lastopening += rw_stopx - start; + } } if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) { ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; + ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN : INT32_MAX; } if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) { ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; + ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX : INT32_MIN; } ds_p++; } diff --git a/src/r_segs.h b/src/r_segs.h index 09c68b27e..cad014674 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -22,5 +22,6 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha); void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_StoreWallRange(INT32 start, INT32 stop); +void R_ClearSegTables(void); #endif From 7634a960314d5a576656cc4300a74caf889f8d7f Mon Sep 17 00:00:00 2001 From: katsy Date: Thu, 27 Jul 2023 23:58:53 -0500 Subject: [PATCH 273/478] delete ASM code, remove NASM --- SRB2.cbp | 18 - SRB2_common.props | 3 - Srb2.dev | 52 +- appveyor.yml | 8 - cmake/Modules/CMakeASM_YASMInformation.cmake | 46 - .../CMakeDetermineASM_YASMCompiler.cmake | 27 - cmake/Modules/CMakeTestASM_YASMCompiler.cmake | 23 - src/Android.mk | 2 +- src/CMakeLists.txt | 35 - src/Makefile | 23 - src/Makefile.d/features.mk | 7 - src/Makefile.d/nix.mk | 5 - src/Makefile.d/platform.mk | 1 - src/Makefile.d/sdl.mk | 7 - src/Makefile.d/win32.mk | 2 - src/Sourcefile | 1 - src/asm_defs.inc | 43 - src/d_netcmd.c | 5 - src/p5prof.h | 278 --- src/r_draw.c | 2 - src/r_draw.h | 12 - src/r_splats.c | 12 - src/screen.c | 27 - src/sdl/CMakeLists.txt | 17 - src/sdl/MakeCYG.cfg | 1 - src/sdl/i_main.c | 34 - src/tmap.nas | 957 ---------- src/tmap.s | 1587 ----------------- src/tmap_asm.s | 322 ---- src/tmap_mmx.nas | 674 ------- src/tmap_vc.nas | 48 - src/v_video.c | 10 - src/vid_copy.s | 61 - tools/anglechk.c | 1 - 34 files changed, 2 insertions(+), 4349 deletions(-) delete mode 100644 cmake/Modules/CMakeASM_YASMInformation.cmake delete mode 100644 cmake/Modules/CMakeDetermineASM_YASMCompiler.cmake delete mode 100644 cmake/Modules/CMakeTestASM_YASMCompiler.cmake delete mode 100644 src/asm_defs.inc delete mode 100644 src/p5prof.h delete mode 100644 src/tmap.nas delete mode 100644 src/tmap.s delete mode 100644 src/tmap_asm.s delete mode 100644 src/tmap_mmx.nas delete mode 100644 src/tmap_vc.nas delete mode 100644 src/vid_copy.s diff --git a/SRB2.cbp b/SRB2.cbp index 2a1eb87b8..9e887bf85 100644 --- a/SRB2.cbp +++ b/SRB2.cbp @@ -1992,24 +1992,6 @@ HW3SOUND for 3D hardware sound support