From 86ad187f05adef9a74290e3d29aff0efa2552aba Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Thu, 22 Oct 2020 00:31:28 +0300 Subject: [PATCH 001/241] NPO2 slope span optimization --- src/CMakeLists.txt | 1 + src/libdivide.h | 2082 ++++++++++++++++++++++++++ src/r_draw.c | 1 + src/r_draw8_npo2.c | 188 ++- src/sdl/Srb2SDL-vc10.vcxproj | 1 + src/sdl/Srb2SDL-vc10.vcxproj.filters | 3 + 6 files changed, 2196 insertions(+), 80 deletions(-) create mode 100644 src/libdivide.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c0e20e8e..416000ac7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,6 +87,7 @@ set(SRB2_CORE_HEADERS i_video.h info.h keys.h + libdivide.h lzf.h m_aatree.h m_anigif.h diff --git a/src/libdivide.h b/src/libdivide.h new file mode 100644 index 000000000..51f9a633b --- /dev/null +++ b/src/libdivide.h @@ -0,0 +1,2082 @@ +// libdivide.h - Optimized integer division +// https://libdivide.com +// +// Copyright (C) 2010 - 2019 ridiculous_fish, +// Copyright (C) 2016 - 2019 Kim Walisch, +// +// libdivide is dual-licensed under the Boost or zlib licenses. +// You may use libdivide under the terms of either of these. +// See LICENSE.txt for more details. + +// NOTICE: This version of libdivide has been modified for use with SRB2. +// Changes made: +// - unused parts commented out (to avoid the need to fix C90 compilation issues with them) +// - C90 compilation issues fixed with used parts +// - use I_Error for errors + +#ifndef LIBDIVIDE_H +#define LIBDIVIDE_H + +#define LIBDIVIDE_VERSION "3.0" +#define LIBDIVIDE_VERSION_MAJOR 3 +#define LIBDIVIDE_VERSION_MINOR 0 + +#include + +#if defined(__cplusplus) + #include + #include + #include +#else + #include + #include +#endif + +#if defined(LIBDIVIDE_AVX512) + #include +#elif defined(LIBDIVIDE_AVX2) + #include +#elif defined(LIBDIVIDE_SSE2) + #include +#endif + +#if defined(_MSC_VER) + #include + // disable warning C4146: unary minus operator applied + // to unsigned type, result still unsigned + #pragma warning(disable: 4146) + #define LIBDIVIDE_VC +#endif + +#if !defined(__has_builtin) + #define __has_builtin(x) 0 +#endif + +#if defined(__SIZEOF_INT128__) + #define HAS_INT128_T + // clang-cl on Windows does not yet support 128-bit division + #if !(defined(__clang__) && defined(LIBDIVIDE_VC)) + #define HAS_INT128_DIV + #endif +#endif + +#if defined(__x86_64__) || defined(_M_X64) + #define LIBDIVIDE_X86_64 +#endif + +#if defined(__i386__) + #define LIBDIVIDE_i386 +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define LIBDIVIDE_GCC_STYLE_ASM +#endif + +#if defined(__cplusplus) || defined(LIBDIVIDE_VC) + #define LIBDIVIDE_FUNCTION __FUNCTION__ +#else + #define LIBDIVIDE_FUNCTION __func__ +#endif + +#define LIBDIVIDE_ERROR(msg) \ + I_Error("libdivide.h:%d: %s(): Error: %s\n", \ + __LINE__, LIBDIVIDE_FUNCTION, msg); + +#if defined(LIBDIVIDE_ASSERTIONS_ON) + #define LIBDIVIDE_ASSERT(x) \ + if (!(x)) { \ + I_Error("libdivide.h:%d: %s(): Assertion failed: %s\n", \ + __LINE__, LIBDIVIDE_FUNCTION, #x); \ + } +#else + #define LIBDIVIDE_ASSERT(x) +#endif + +#ifdef __cplusplus +namespace libdivide { +#endif + +// pack divider structs to prevent compilers from padding. +// This reduces memory usage by up to 43% when using a large +// array of libdivide dividers and improves performance +// by up to 10% because of reduced memory bandwidth. +#pragma pack(push, 1) + +struct libdivide_u32_t { + uint32_t magic; + uint8_t more; +}; + +struct libdivide_s32_t { + int32_t magic; + uint8_t more; +}; + +struct libdivide_u64_t { + uint64_t magic; + uint8_t more; +}; + +struct libdivide_s64_t { + int64_t magic; + uint8_t more; +}; + +struct libdivide_u32_branchfree_t { + uint32_t magic; + uint8_t more; +}; + +struct libdivide_s32_branchfree_t { + int32_t magic; + uint8_t more; +}; + +struct libdivide_u64_branchfree_t { + uint64_t magic; + uint8_t more; +}; + +struct libdivide_s64_branchfree_t { + int64_t magic; + uint8_t more; +}; + +#pragma pack(pop) + +// Explanation of the "more" field: +// +// * Bits 0-5 is the shift value (for shift path or mult path). +// * Bit 6 is the add indicator for mult path. +// * Bit 7 is set if the divisor is negative. We use bit 7 as the negative +// divisor indicator so that we can efficiently use sign extension to +// create a bitmask with all bits set to 1 (if the divisor is negative) +// or 0 (if the divisor is positive). +// +// u32: [0-4] shift value +// [5] ignored +// [6] add indicator +// magic number of 0 indicates shift path +// +// s32: [0-4] shift value +// [5] ignored +// [6] add indicator +// [7] indicates negative divisor +// magic number of 0 indicates shift path +// +// u64: [0-5] shift value +// [6] add indicator +// magic number of 0 indicates shift path +// +// s64: [0-5] shift value +// [6] add indicator +// [7] indicates negative divisor +// magic number of 0 indicates shift path +// +// In s32 and s64 branchfree modes, the magic number is negated according to +// whether the divisor is negated. In branchfree strategy, it is not negated. + +enum { + LIBDIVIDE_32_SHIFT_MASK = 0x1F, + LIBDIVIDE_64_SHIFT_MASK = 0x3F, + LIBDIVIDE_ADD_MARKER = 0x40, + LIBDIVIDE_NEGATIVE_DIVISOR = 0x80 +}; + +//static inline struct libdivide_s32_t libdivide_s32_gen(int32_t d); +static inline struct libdivide_u32_t libdivide_u32_gen(uint32_t d); +//static inline struct libdivide_s64_t libdivide_s64_gen(int64_t d); +//static inline struct libdivide_u64_t libdivide_u64_gen(uint64_t d); + +/*static inline struct libdivide_s32_branchfree_t libdivide_s32_branchfree_gen(int32_t d); +static inline struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t d); +static inline struct libdivide_s64_branchfree_t libdivide_s64_branchfree_gen(int64_t d); +static inline struct libdivide_u64_branchfree_t libdivide_u64_branchfree_gen(uint64_t d);*/ + +//static inline int32_t libdivide_s32_do(int32_t numer, const struct libdivide_s32_t *denom); +static inline uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom); +//static inline int64_t libdivide_s64_do(int64_t numer, const struct libdivide_s64_t *denom); +//static inline uint64_t libdivide_u64_do(uint64_t numer, const struct libdivide_u64_t *denom); + +/*static inline int32_t libdivide_s32_branchfree_do(int32_t numer, const struct libdivide_s32_branchfree_t *denom); +static inline uint32_t libdivide_u32_branchfree_do(uint32_t numer, const struct libdivide_u32_branchfree_t *denom); +static inline int64_t libdivide_s64_branchfree_do(int64_t numer, const struct libdivide_s64_branchfree_t *denom); +static inline uint64_t libdivide_u64_branchfree_do(uint64_t numer, const struct libdivide_u64_branchfree_t *denom);*/ + +/*static inline int32_t libdivide_s32_recover(const struct libdivide_s32_t *denom); +static inline uint32_t libdivide_u32_recover(const struct libdivide_u32_t *denom); +static inline int64_t libdivide_s64_recover(const struct libdivide_s64_t *denom); +static inline uint64_t libdivide_u64_recover(const struct libdivide_u64_t *denom);*/ + +/*static inline int32_t libdivide_s32_branchfree_recover(const struct libdivide_s32_branchfree_t *denom); +static inline uint32_t libdivide_u32_branchfree_recover(const struct libdivide_u32_branchfree_t *denom); +static inline int64_t libdivide_s64_branchfree_recover(const struct libdivide_s64_branchfree_t *denom); +static inline uint64_t libdivide_u64_branchfree_recover(const struct libdivide_u64_branchfree_t *denom);*/ + +//////// Internal Utility Functions + +static inline uint32_t libdivide_mullhi_u32(uint32_t x, uint32_t y) { + uint64_t xl = x, yl = y; + uint64_t rl = xl * yl; + return (uint32_t)(rl >> 32); +} + +static inline int32_t libdivide_mullhi_s32(int32_t x, int32_t y) { + int64_t xl = x, yl = y; + int64_t rl = xl * yl; + // needs to be arithmetic shift + return (int32_t)(rl >> 32); +} + +static inline uint64_t libdivide_mullhi_u64(uint64_t x, uint64_t y) { +#if defined(LIBDIVIDE_VC) && \ + defined(LIBDIVIDE_X86_64) + return __umulh(x, y); +#elif defined(HAS_INT128_T) + __uint128_t xl = x, yl = y; + __uint128_t rl = xl * yl; + return (uint64_t)(rl >> 64); +#else + // full 128 bits are x0 * y0 + (x0 * y1 << 32) + (x1 * y0 << 32) + (x1 * y1 << 64) + uint32_t mask = 0xFFFFFFFF; + uint32_t x0 = (uint32_t)(x & mask); + uint32_t x1 = (uint32_t)(x >> 32); + uint32_t y0 = (uint32_t)(y & mask); + uint32_t y1 = (uint32_t)(y >> 32); + uint32_t x0y0_hi = libdivide_mullhi_u32(x0, y0); + uint64_t x0y1 = x0 * (uint64_t)y1; + uint64_t x1y0 = x1 * (uint64_t)y0; + uint64_t x1y1 = x1 * (uint64_t)y1; + uint64_t temp = x1y0 + x0y0_hi; + uint64_t temp_lo = temp & mask; + uint64_t temp_hi = temp >> 32; + + return x1y1 + temp_hi + ((temp_lo + x0y1) >> 32); +#endif +} + +static inline int64_t libdivide_mullhi_s64(int64_t x, int64_t y) { +#if defined(LIBDIVIDE_VC) && \ + defined(LIBDIVIDE_X86_64) + return __mulh(x, y); +#elif defined(HAS_INT128_T) + __int128_t xl = x, yl = y; + __int128_t rl = xl * yl; + return (int64_t)(rl >> 64); +#else + // full 128 bits are x0 * y0 + (x0 * y1 << 32) + (x1 * y0 << 32) + (x1 * y1 << 64) + uint32_t mask = 0xFFFFFFFF; + uint32_t x0 = (uint32_t)(x & mask); + uint32_t y0 = (uint32_t)(y & mask); + int32_t x1 = (int32_t)(x >> 32); + int32_t y1 = (int32_t)(y >> 32); + uint32_t x0y0_hi = libdivide_mullhi_u32(x0, y0); + int64_t t = x1 * (int64_t)y0 + x0y0_hi; + int64_t w1 = x0 * (int64_t)y1 + (t & mask); + + return x1 * (int64_t)y1 + (t >> 32) + (w1 >> 32); +#endif +} + +static inline int32_t libdivide_count_leading_zeros32(uint32_t val) { +#if defined(__GNUC__) || \ + __has_builtin(__builtin_clz) + // Fast way to count leading zeros + return __builtin_clz(val); +#elif defined(LIBDIVIDE_VC) + unsigned long result; + if (_BitScanReverse(&result, val)) { + return 31 - result; + } + return 0; +#else + if (val == 0) + return 32; + int32_t result = 8; + uint32_t hi = 0xFFU << 24; + while ((val & hi) == 0) { + hi >>= 8; + result += 8; + } + while (val & hi) { + result -= 1; + hi <<= 1; + } + return result; +#endif +} + +static inline int32_t libdivide_count_leading_zeros64(uint64_t val) { +#if defined(__GNUC__) || \ + __has_builtin(__builtin_clzll) + // Fast way to count leading zeros + return __builtin_clzll(val); +#elif defined(LIBDIVIDE_VC) && defined(_WIN64) + unsigned long result; + if (_BitScanReverse64(&result, val)) { + return 63 - result; + } + return 0; +#else + uint32_t hi = val >> 32; + uint32_t lo = val & 0xFFFFFFFF; + if (hi != 0) return libdivide_count_leading_zeros32(hi); + return 32 + libdivide_count_leading_zeros32(lo); +#endif +} + +// libdivide_64_div_32_to_32: divides a 64-bit uint {u1, u0} by a 32-bit +// uint {v}. The result must fit in 32 bits. +// Returns the quotient directly and the remainder in *r +static inline uint32_t libdivide_64_div_32_to_32(uint32_t u1, uint32_t u0, uint32_t v, uint32_t *r) { +#if (defined(LIBDIVIDE_i386) || defined(LIBDIVIDE_X86_64)) && \ + defined(LIBDIVIDE_GCC_STYLE_ASM) + uint32_t result; + __asm__("divl %[v]" + : "=a"(result), "=d"(*r) + : [v] "r"(v), "a"(u0), "d"(u1) + ); + return result; +#else + uint64_t n = ((uint64_t)u1 << 32) | u0; + uint32_t result = (uint32_t)(n / v); + *r = (uint32_t)(n - result * (uint64_t)v); + return result; +#endif +} + +// libdivide_128_div_64_to_64: divides a 128-bit uint {u1, u0} by a 64-bit +// uint {v}. The result must fit in 64 bits. +// Returns the quotient directly and the remainder in *r +/*static uint64_t libdivide_128_div_64_to_64(uint64_t u1, uint64_t u0, uint64_t v, uint64_t *r) { +#if defined(LIBDIVIDE_X86_64) && \ + defined(LIBDIVIDE_GCC_STYLE_ASM) + uint64_t result; + __asm__("divq %[v]" + : "=a"(result), "=d"(*r) + : [v] "r"(v), "a"(u0), "d"(u1) + ); + return result; +#elif defined(HAS_INT128_T) && \ + defined(HAS_INT128_DIV) + __uint128_t n = ((__uint128_t)u1 << 64) | u0; + uint64_t result = (uint64_t)(n / v); + *r = (uint64_t)(n - result * (__uint128_t)v); + return result; +#else + // Code taken from Hacker's Delight: + // http://www.hackersdelight.org/HDcode/divlu.c. + // License permits inclusion here per: + // http://www.hackersdelight.org/permissions.htm + + const uint64_t b = (1ULL << 32); // Number base (32 bits) + uint64_t un1, un0; // Norm. dividend LSD's + uint64_t vn1, vn0; // Norm. divisor digits + uint64_t q1, q0; // Quotient digits + uint64_t un64, un21, un10; // Dividend digit pairs + uint64_t rhat; // A remainder + int32_t s; // Shift amount for norm + + // If overflow, set rem. to an impossible value, + // and return the largest possible quotient + if (u1 >= v) { + *r = (uint64_t) -1; + return (uint64_t) -1; + } + + // count leading zeros + s = libdivide_count_leading_zeros64(v); + if (s > 0) { + // Normalize divisor + v = v << s; + un64 = (u1 << s) | (u0 >> (64 - s)); + un10 = u0 << s; // Shift dividend left + } else { + // Avoid undefined behavior of (u0 >> 64). + // The behavior is undefined if the right operand is + // negative, or greater than or equal to the length + // in bits of the promoted left operand. + un64 = u1; + un10 = u0; + } + + // Break divisor up into two 32-bit digits + vn1 = v >> 32; + vn0 = v & 0xFFFFFFFF; + + // Break right half of dividend into two digits + un1 = un10 >> 32; + un0 = un10 & 0xFFFFFFFF; + + // Compute the first quotient digit, q1 + q1 = un64 / vn1; + rhat = un64 - q1 * vn1; + + while (q1 >= b || q1 * vn0 > b * rhat + un1) { + q1 = q1 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + // Multiply and subtract + un21 = un64 * b + un1 - q1 * v; + + // Compute the second quotient digit + q0 = un21 / vn1; + rhat = un21 - q0 * vn1; + + while (q0 >= b || q0 * vn0 > b * rhat + un0) { + q0 = q0 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + *r = (un21 * b + un0 - q0 * v) >> s; + return q1 * b + q0; +#endif +}*/ + +// Bitshift a u128 in place, left (signed_shift > 0) or right (signed_shift < 0) +static inline void libdivide_u128_shift(uint64_t *u1, uint64_t *u0, int32_t signed_shift) { + if (signed_shift > 0) { + uint32_t shift = signed_shift; + *u1 <<= shift; + *u1 |= *u0 >> (64 - shift); + *u0 <<= shift; + } + else if (signed_shift < 0) { + uint32_t shift = -signed_shift; + *u0 >>= shift; + *u0 |= *u1 << (64 - shift); + *u1 >>= shift; + } +} + +// Computes a 128 / 128 -> 64 bit division, with a 128 bit remainder. +/*static uint64_t libdivide_128_div_128_to_64(uint64_t u_hi, uint64_t u_lo, uint64_t v_hi, uint64_t v_lo, uint64_t *r_hi, uint64_t *r_lo) { +#if defined(HAS_INT128_T) && \ + defined(HAS_INT128_DIV) + __uint128_t ufull = u_hi; + __uint128_t vfull = v_hi; + ufull = (ufull << 64) | u_lo; + vfull = (vfull << 64) | v_lo; + uint64_t res = (uint64_t)(ufull / vfull); + __uint128_t remainder = ufull - (vfull * res); + *r_lo = (uint64_t)remainder; + *r_hi = (uint64_t)(remainder >> 64); + return res; +#else + // Adapted from "Unsigned Doubleword Division" in Hacker's Delight + // We want to compute u / v + typedef struct { uint64_t hi; uint64_t lo; } u128_t; + u128_t u = {u_hi, u_lo}; + u128_t v = {v_hi, v_lo}; + + if (v.hi == 0) { + // divisor v is a 64 bit value, so we just need one 128/64 division + // Note that we are simpler than Hacker's Delight here, because we know + // the quotient fits in 64 bits whereas Hacker's Delight demands a full + // 128 bit quotient + *r_hi = 0; + return libdivide_128_div_64_to_64(u.hi, u.lo, v.lo, r_lo); + } + // Here v >= 2**64 + // We know that v.hi != 0, so count leading zeros is OK + // We have 0 <= n <= 63 + uint32_t n = libdivide_count_leading_zeros64(v.hi); + + // Normalize the divisor so its MSB is 1 + u128_t v1t = v; + libdivide_u128_shift(&v1t.hi, &v1t.lo, n); + uint64_t v1 = v1t.hi; // i.e. v1 = v1t >> 64 + + // To ensure no overflow + u128_t u1 = u; + libdivide_u128_shift(&u1.hi, &u1.lo, -1); + + // Get quotient from divide unsigned insn. + uint64_t rem_ignored; + uint64_t q1 = libdivide_128_div_64_to_64(u1.hi, u1.lo, v1, &rem_ignored); + + // Undo normalization and division of u by 2. + u128_t q0 = {0, q1}; + libdivide_u128_shift(&q0.hi, &q0.lo, n); + libdivide_u128_shift(&q0.hi, &q0.lo, -63); + + // Make q0 correct or too small by 1 + // Equivalent to `if (q0 != 0) q0 = q0 - 1;` + if (q0.hi != 0 || q0.lo != 0) { + q0.hi -= (q0.lo == 0); // borrow + q0.lo -= 1; + } + + // Now q0 is correct. + // Compute q0 * v as q0v + // = (q0.hi << 64 + q0.lo) * (v.hi << 64 + v.lo) + // = (q0.hi * v.hi << 128) + (q0.hi * v.lo << 64) + + // (q0.lo * v.hi << 64) + q0.lo * v.lo) + // Each term is 128 bit + // High half of full product (upper 128 bits!) are dropped + u128_t q0v = {0, 0}; + q0v.hi = q0.hi*v.lo + q0.lo*v.hi + libdivide_mullhi_u64(q0.lo, v.lo); + q0v.lo = q0.lo*v.lo; + + // Compute u - q0v as u_q0v + // This is the remainder + u128_t u_q0v = u; + u_q0v.hi -= q0v.hi + (u.lo < q0v.lo); // second term is borrow + u_q0v.lo -= q0v.lo; + + // Check if u_q0v >= v + // This checks if our remainder is larger than the divisor + if ((u_q0v.hi > v.hi) || + (u_q0v.hi == v.hi && u_q0v.lo >= v.lo)) { + // Increment q0 + q0.lo += 1; + q0.hi += (q0.lo == 0); // carry + + // Subtract v from remainder + u_q0v.hi -= v.hi + (u_q0v.lo < v.lo); + u_q0v.lo -= v.lo; + } + + *r_hi = u_q0v.hi; + *r_lo = u_q0v.lo; + + LIBDIVIDE_ASSERT(q0.hi == 0); + return q0.lo; +#endif +}*/ + +////////// UINT32 + +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; + + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + floor_log_2_d = 31 - libdivide_count_leading_zeros32(d); + + // Power of 2 + if ((d & (d - 1)) == 0) { + // We need to subtract 1 from the shift value in case of an unsigned + // branchfree divider because there is a hardcoded right shift by 1 + // in its division algorithm. Because of this we also need to add back + // 1 in its recovery algorithm. + result.magic = 0; + result.more = (uint8_t)(floor_log_2_d - (branchfree != 0)); + } else { + uint8_t more; + uint32_t rem, proposed_m; + uint32_t e; + proposed_m = libdivide_64_div_32_to_32(1U << floor_log_2_d, 0, d, &rem); + + LIBDIVIDE_ASSERT(rem > 0 && rem < d); + e = d - rem; + + // This power works if e < 2**floor_log_2_d. + if (!branchfree && (e < (1U << floor_log_2_d))) { + // This power works + more = floor_log_2_d; + } else { + // We have to use the general 33-bit algorithm. We need to compute + // (2**power) / d. However, we already have (2**(power-1))/d and + // its remainder. By doubling both, and then correcting the + // remainder, we can compute the larger division. + // don't care about overflow here - in fact, we expect it + const uint32_t twice_rem = rem + rem; + proposed_m += proposed_m; + if (twice_rem >= d || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + result.magic = 1 + proposed_m; + result.more = more; + // result.more's shift should in general be ceil_log_2_d. But if we + // used the smaller power, we subtract one from the shift because we're + // using the smaller power. If we're using the larger power, we + // subtract one from the shift because it's taken care of by the add + // indicator. So floor_log_2_d happens to be correct in both cases. + } + return result; +} + +struct libdivide_u32_t libdivide_u32_gen(uint32_t d) { + return libdivide_internal_u32_gen(d, 0); +} + +/*struct libdivide_u32_branchfree_t libdivide_u32_branchfree_gen(uint32_t d) { + if (d == 1) { + LIBDIVIDE_ERROR("branchfree divider must be != 1"); + } + struct libdivide_u32_t tmp = libdivide_internal_u32_gen(d, 1); + struct libdivide_u32_branchfree_t ret = {tmp.magic, (uint8_t)(tmp.more & LIBDIVIDE_32_SHIFT_MASK)}; + return ret; +}*/ + +uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return numer >> more; + } + else { + uint32_t q = libdivide_mullhi_u32(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + uint32_t t = ((numer - q) >> 1) + q; + return t >> (more & LIBDIVIDE_32_SHIFT_MASK); + } + else { + // All upper bits are 0, + // don't need to mask them off. + return q >> more; + } + } +} + +/*uint32_t libdivide_u32_branchfree_do(uint32_t numer, const struct libdivide_u32_branchfree_t *denom) { + uint32_t q = libdivide_mullhi_u32(denom->magic, numer); + uint32_t t = ((numer - q) >> 1) + q; + return t >> denom->more; +} + +uint32_t libdivide_u32_recover(const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + return 1U << shift; + } else if (!(more & LIBDIVIDE_ADD_MARKER)) { + // We compute q = n/d = n*m / 2^(32 + shift) + // Therefore we have d = 2^(32 + shift) / m + // We need to ceil it. + // We know d is not a power of 2, so m is not a power of 2, + // so we can just add 1 to the floor + uint32_t hi_dividend = 1U << shift; + uint32_t rem_ignored; + return 1 + libdivide_64_div_32_to_32(hi_dividend, 0, denom->magic, &rem_ignored); + } else { + // Here we wish to compute d = 2^(32+shift+1)/(m+2^32). + // Notice (m + 2^32) is a 33 bit number. Use 64 bit division for now + // Also note that shift may be as high as 31, so shift + 1 will + // overflow. So we have to compute it as 2^(32+shift)/(m+2^32), and + // then double the quotient and remainder. + uint64_t half_n = 1ULL << (32 + shift); + uint64_t d = (1ULL << 32) | denom->magic; + // Note that the quotient is guaranteed <= 32 bits, but the remainder + // may need 33! + uint32_t half_q = (uint32_t)(half_n / d); + uint64_t rem = half_n % d; + // We computed 2^(32+shift)/(m+2^32) + // Need to double it, and then add 1 to the quotient if doubling th + // remainder would increase the quotient. + // Note that rem<<1 cannot overflow, since rem < d and d is 33 bits + uint32_t full_q = half_q + half_q + ((rem<<1) >= d); + + // We rounded down in gen (hence +1) + return full_q + 1; + } +} + +uint32_t libdivide_u32_branchfree_recover(const struct libdivide_u32_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + return 1U << (shift + 1); + } else { + // Here we wish to compute d = 2^(32+shift+1)/(m+2^32). + // Notice (m + 2^32) is a 33 bit number. Use 64 bit division for now + // Also note that shift may be as high as 31, so shift + 1 will + // overflow. So we have to compute it as 2^(32+shift)/(m+2^32), and + // then double the quotient and remainder. + uint64_t half_n = 1ULL << (32 + shift); + uint64_t d = (1ULL << 32) | denom->magic; + // Note that the quotient is guaranteed <= 32 bits, but the remainder + // may need 33! + uint32_t half_q = (uint32_t)(half_n / d); + uint64_t rem = half_n % d; + // We computed 2^(32+shift)/(m+2^32) + // Need to double it, and then add 1 to the quotient if doubling th + // remainder would increase the quotient. + // Note that rem<<1 cannot overflow, since rem < d and d is 33 bits + uint32_t full_q = half_q + half_q + ((rem<<1) >= d); + + // We rounded down in gen (hence +1) + return full_q + 1; + } +}*/ + +/////////// UINT64 + +/*static inline struct libdivide_u64_t libdivide_internal_u64_gen(uint64_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_u64_t result; + uint32_t floor_log_2_d = 63 - libdivide_count_leading_zeros64(d); + + // Power of 2 + if ((d & (d - 1)) == 0) { + // We need to subtract 1 from the shift value in case of an unsigned + // branchfree divider because there is a hardcoded right shift by 1 + // in its division algorithm. Because of this we also need to add back + // 1 in its recovery algorithm. + result.magic = 0; + result.more = (uint8_t)(floor_log_2_d - (branchfree != 0)); + } else { + uint64_t proposed_m, rem; + uint8_t more; + // (1 << (64 + floor_log_2_d)) / d + proposed_m = libdivide_128_div_64_to_64(1ULL << floor_log_2_d, 0, d, &rem); + + LIBDIVIDE_ASSERT(rem > 0 && rem < d); + const uint64_t e = d - rem; + + // This power works if e < 2**floor_log_2_d. + if (!branchfree && e < (1ULL << floor_log_2_d)) { + // This power works + more = floor_log_2_d; + } else { + // We have to use the general 65-bit algorithm. We need to compute + // (2**power) / d. However, we already have (2**(power-1))/d and + // its remainder. By doubling both, and then correcting the + // remainder, we can compute the larger division. + // don't care about overflow here - in fact, we expect it + proposed_m += proposed_m; + const uint64_t twice_rem = rem + rem; + if (twice_rem >= d || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + result.magic = 1 + proposed_m; + result.more = more; + // result.more's shift should in general be ceil_log_2_d. But if we + // used the smaller power, we subtract one from the shift because we're + // using the smaller power. If we're using the larger power, we + // subtract one from the shift because it's taken care of by the add + // indicator. So floor_log_2_d happens to be correct in both cases, + // which is why we do it outside of the if statement. + } + return result; +} + +struct libdivide_u64_t libdivide_u64_gen(uint64_t d) { + return libdivide_internal_u64_gen(d, 0); +} + +struct libdivide_u64_branchfree_t libdivide_u64_branchfree_gen(uint64_t d) { + if (d == 1) { + LIBDIVIDE_ERROR("branchfree divider must be != 1"); + } + struct libdivide_u64_t tmp = libdivide_internal_u64_gen(d, 1); + struct libdivide_u64_branchfree_t ret = {tmp.magic, (uint8_t)(tmp.more & LIBDIVIDE_64_SHIFT_MASK)}; + return ret; +} + +uint64_t libdivide_u64_do(uint64_t numer, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return numer >> more; + } + else { + uint64_t q = libdivide_mullhi_u64(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + uint64_t t = ((numer - q) >> 1) + q; + return t >> (more & LIBDIVIDE_64_SHIFT_MASK); + } + else { + // All upper bits are 0, + // don't need to mask them off. + return q >> more; + } + } +} + +uint64_t libdivide_u64_branchfree_do(uint64_t numer, const struct libdivide_u64_branchfree_t *denom) { + uint64_t q = libdivide_mullhi_u64(denom->magic, numer); + uint64_t t = ((numer - q) >> 1) + q; + return t >> denom->more; +} + +uint64_t libdivide_u64_recover(const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { + return 1ULL << shift; + } else if (!(more & LIBDIVIDE_ADD_MARKER)) { + // We compute q = n/d = n*m / 2^(64 + shift) + // Therefore we have d = 2^(64 + shift) / m + // We need to ceil it. + // We know d is not a power of 2, so m is not a power of 2, + // so we can just add 1 to the floor + uint64_t hi_dividend = 1ULL << shift; + uint64_t rem_ignored; + return 1 + libdivide_128_div_64_to_64(hi_dividend, 0, denom->magic, &rem_ignored); + } else { + // Here we wish to compute d = 2^(64+shift+1)/(m+2^64). + // Notice (m + 2^64) is a 65 bit number. This gets hairy. See + // libdivide_u32_recover for more on what we do here. + // TODO: do something better than 128 bit math + + // Full n is a (potentially) 129 bit value + // half_n is a 128 bit value + // Compute the hi half of half_n. Low half is 0. + uint64_t half_n_hi = 1ULL << shift, half_n_lo = 0; + // d is a 65 bit value. The high bit is always set to 1. + const uint64_t d_hi = 1, d_lo = denom->magic; + // Note that the quotient is guaranteed <= 64 bits, + // but the remainder may need 65! + uint64_t r_hi, r_lo; + uint64_t half_q = libdivide_128_div_128_to_64(half_n_hi, half_n_lo, d_hi, d_lo, &r_hi, &r_lo); + // We computed 2^(64+shift)/(m+2^64) + // Double the remainder ('dr') and check if that is larger than d + // Note that d is a 65 bit value, so r1 is small and so r1 + r1 + // cannot overflow + uint64_t dr_lo = r_lo + r_lo; + uint64_t dr_hi = r_hi + r_hi + (dr_lo < r_lo); // last term is carry + int dr_exceeds_d = (dr_hi > d_hi) || (dr_hi == d_hi && dr_lo >= d_lo); + uint64_t full_q = half_q + half_q + (dr_exceeds_d ? 1 : 0); + return full_q + 1; + } +} + +uint64_t libdivide_u64_branchfree_recover(const struct libdivide_u64_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { + return 1ULL << (shift + 1); + } else { + // Here we wish to compute d = 2^(64+shift+1)/(m+2^64). + // Notice (m + 2^64) is a 65 bit number. This gets hairy. See + // libdivide_u32_recover for more on what we do here. + // TODO: do something better than 128 bit math + + // Full n is a (potentially) 129 bit value + // half_n is a 128 bit value + // Compute the hi half of half_n. Low half is 0. + uint64_t half_n_hi = 1ULL << shift, half_n_lo = 0; + // d is a 65 bit value. The high bit is always set to 1. + const uint64_t d_hi = 1, d_lo = denom->magic; + // Note that the quotient is guaranteed <= 64 bits, + // but the remainder may need 65! + uint64_t r_hi, r_lo; + uint64_t half_q = libdivide_128_div_128_to_64(half_n_hi, half_n_lo, d_hi, d_lo, &r_hi, &r_lo); + // We computed 2^(64+shift)/(m+2^64) + // Double the remainder ('dr') and check if that is larger than d + // Note that d is a 65 bit value, so r1 is small and so r1 + r1 + // cannot overflow + uint64_t dr_lo = r_lo + r_lo; + uint64_t dr_hi = r_hi + r_hi + (dr_lo < r_lo); // last term is carry + int dr_exceeds_d = (dr_hi > d_hi) || (dr_hi == d_hi && dr_lo >= d_lo); + uint64_t full_q = half_q + half_q + (dr_exceeds_d ? 1 : 0); + return full_q + 1; + } +}*/ + +/////////// SINT32 + +/*static inline struct libdivide_s32_t libdivide_internal_s32_gen(int32_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_s32_t result; + + // If d is a power of 2, or negative a power of 2, we have to use a shift. + // This is especially important because the magic algorithm fails for -1. + // To check if d is a power of 2 or its inverse, it suffices to check + // whether its absolute value has exactly one bit set. This works even for + // INT_MIN, because abs(INT_MIN) == INT_MIN, and INT_MIN has one bit set + // and is a power of 2. + uint32_t ud = (uint32_t)d; + uint32_t absD = (d < 0) ? -ud : ud; + uint32_t floor_log_2_d = 31 - libdivide_count_leading_zeros32(absD); + // check if exactly one bit is set, + // don't care if absD is 0 since that's divide by zero + if ((absD & (absD - 1)) == 0) { + // Branchfree and normal paths are exactly the same + result.magic = 0; + result.more = floor_log_2_d | (d < 0 ? LIBDIVIDE_NEGATIVE_DIVISOR : 0); + } else { + LIBDIVIDE_ASSERT(floor_log_2_d >= 1); + + uint8_t more; + // the dividend here is 2**(floor_log_2_d + 31), so the low 32 bit word + // is 0 and the high word is floor_log_2_d - 1 + uint32_t rem, proposed_m; + proposed_m = libdivide_64_div_32_to_32(1U << (floor_log_2_d - 1), 0, absD, &rem); + const uint32_t e = absD - rem; + + // We are going to start with a power of floor_log_2_d - 1. + // This works if works if e < 2**floor_log_2_d. + if (!branchfree && e < (1U << floor_log_2_d)) { + // This power works + more = floor_log_2_d - 1; + } else { + // We need to go one higher. This should not make proposed_m + // overflow, but it will make it negative when interpreted as an + // int32_t. + proposed_m += proposed_m; + const uint32_t twice_rem = rem + rem; + if (twice_rem >= absD || twice_rem < rem) proposed_m += 1; + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + + proposed_m += 1; + int32_t magic = (int32_t)proposed_m; + + // Mark if we are negative. Note we only negate the magic number in the + // branchfull case. + if (d < 0) { + more |= LIBDIVIDE_NEGATIVE_DIVISOR; + if (!branchfree) { + magic = -magic; + } + } + + result.more = more; + result.magic = magic; + } + return result; +} + +struct libdivide_s32_t libdivide_s32_gen(int32_t d) { + return libdivide_internal_s32_gen(d, 0); +} + +struct libdivide_s32_branchfree_t libdivide_s32_branchfree_gen(int32_t d) { + struct libdivide_s32_t tmp = libdivide_internal_s32_gen(d, 1); + struct libdivide_s32_branchfree_t result = {tmp.magic, tmp.more}; + return result; +} + +int32_t libdivide_s32_do(int32_t numer, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + + if (!denom->magic) { + uint32_t sign = (int8_t)more >> 7; + uint32_t mask = (1U << shift) - 1; + uint32_t uq = numer + ((numer >> 31) & mask); + int32_t q = (int32_t)uq; + q >>= shift; + q = (q ^ sign) - sign; + return q; + } else { + uint32_t uq = (uint32_t)libdivide_mullhi_s32(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift and then sign extend + int32_t sign = (int8_t)more >> 7; + // q += (more < 0 ? -numer : numer) + // cast required to avoid UB + uq += ((uint32_t)numer ^ sign) - sign; + } + int32_t q = (int32_t)uq; + q >>= shift; + q += (q < 0); + return q; + } +} + +int32_t libdivide_s32_branchfree_do(int32_t numer, const struct libdivide_s32_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift and then sign extend + int32_t sign = (int8_t)more >> 7; + int32_t magic = denom->magic; + int32_t q = libdivide_mullhi_s32(magic, numer); + q += numer; + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is a power of + // 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + uint32_t q_sign = (uint32_t)(q >> 31); + q += q_sign & ((1U << shift) - is_power_of_2); + + // Now arithmetic right shift + q >>= shift; + // Negate if needed + q = (q ^ sign) - sign; + + return q; +} + +int32_t libdivide_s32_recover(const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + if (!denom->magic) { + uint32_t absD = 1U << shift; + if (more & LIBDIVIDE_NEGATIVE_DIVISOR) { + absD = -absD; + } + return (int32_t)absD; + } else { + // Unsigned math is much easier + // We negate the magic number only in the branchfull case, and we don't + // know which case we're in. However we have enough information to + // determine the correct sign of the magic number. The divisor was + // negative if LIBDIVIDE_NEGATIVE_DIVISOR is set. If ADD_MARKER is set, + // the magic number's sign is opposite that of the divisor. + // We want to compute the positive magic number. + int negative_divisor = (more & LIBDIVIDE_NEGATIVE_DIVISOR); + int magic_was_negated = (more & LIBDIVIDE_ADD_MARKER) + ? denom->magic > 0 : denom->magic < 0; + + // Handle the power of 2 case (including branchfree) + if (denom->magic == 0) { + int32_t result = 1U << shift; + return negative_divisor ? -result : result; + } + + uint32_t d = (uint32_t)(magic_was_negated ? -denom->magic : denom->magic); + uint64_t n = 1ULL << (32 + shift); // this shift cannot exceed 30 + uint32_t q = (uint32_t)(n / d); + int32_t result = (int32_t)q; + result += 1; + return negative_divisor ? -result : result; + } +} + +int32_t libdivide_s32_branchfree_recover(const struct libdivide_s32_branchfree_t *denom) { + return libdivide_s32_recover((const struct libdivide_s32_t *)denom); +}*/ + +///////////// SINT64 + +/*static inline struct libdivide_s64_t libdivide_internal_s64_gen(int64_t d, int branchfree) { + if (d == 0) { + LIBDIVIDE_ERROR("divider must be != 0"); + } + + struct libdivide_s64_t result; + + // If d is a power of 2, or negative a power of 2, we have to use a shift. + // This is especially important because the magic algorithm fails for -1. + // To check if d is a power of 2 or its inverse, it suffices to check + // whether its absolute value has exactly one bit set. This works even for + // INT_MIN, because abs(INT_MIN) == INT_MIN, and INT_MIN has one bit set + // and is a power of 2. + uint64_t ud = (uint64_t)d; + uint64_t absD = (d < 0) ? -ud : ud; + uint32_t floor_log_2_d = 63 - libdivide_count_leading_zeros64(absD); + // check if exactly one bit is set, + // don't care if absD is 0 since that's divide by zero + if ((absD & (absD - 1)) == 0) { + // Branchfree and non-branchfree cases are the same + result.magic = 0; + result.more = floor_log_2_d | (d < 0 ? LIBDIVIDE_NEGATIVE_DIVISOR : 0); + } else { + // the dividend here is 2**(floor_log_2_d + 63), so the low 64 bit word + // is 0 and the high word is floor_log_2_d - 1 + uint8_t more; + uint64_t rem, proposed_m; + proposed_m = libdivide_128_div_64_to_64(1ULL << (floor_log_2_d - 1), 0, absD, &rem); + const uint64_t e = absD - rem; + + // We are going to start with a power of floor_log_2_d - 1. + // This works if works if e < 2**floor_log_2_d. + if (!branchfree && e < (1ULL << floor_log_2_d)) { + // This power works + more = floor_log_2_d - 1; + } else { + // We need to go one higher. This should not make proposed_m + // overflow, but it will make it negative when interpreted as an + // int32_t. + proposed_m += proposed_m; + const uint64_t twice_rem = rem + rem; + if (twice_rem >= absD || twice_rem < rem) proposed_m += 1; + // note that we only set the LIBDIVIDE_NEGATIVE_DIVISOR bit if we + // also set ADD_MARKER this is an annoying optimization that + // enables algorithm #4 to avoid the mask. However we always set it + // in the branchfree case + more = floor_log_2_d | LIBDIVIDE_ADD_MARKER; + } + proposed_m += 1; + int64_t magic = (int64_t)proposed_m; + + // Mark if we are negative + if (d < 0) { + more |= LIBDIVIDE_NEGATIVE_DIVISOR; + if (!branchfree) { + magic = -magic; + } + } + + result.more = more; + result.magic = magic; + } + return result; +} + +struct libdivide_s64_t libdivide_s64_gen(int64_t d) { + return libdivide_internal_s64_gen(d, 0); +} + +struct libdivide_s64_branchfree_t libdivide_s64_branchfree_gen(int64_t d) { + struct libdivide_s64_t tmp = libdivide_internal_s64_gen(d, 1); + struct libdivide_s64_branchfree_t ret = {tmp.magic, tmp.more}; + return ret; +} + +int64_t libdivide_s64_do(int64_t numer, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + + if (!denom->magic) { // shift path + uint64_t mask = (1ULL << shift) - 1; + uint64_t uq = numer + ((numer >> 63) & mask); + int64_t q = (int64_t)uq; + q >>= shift; + // must be arithmetic shift and then sign-extend + int64_t sign = (int8_t)more >> 7; + q = (q ^ sign) - sign; + return q; + } else { + uint64_t uq = (uint64_t)libdivide_mullhi_s64(denom->magic, numer); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift and then sign extend + int64_t sign = (int8_t)more >> 7; + // q += (more < 0 ? -numer : numer) + // cast required to avoid UB + uq += ((uint64_t)numer ^ sign) - sign; + } + int64_t q = (int64_t)uq; + q >>= shift; + q += (q < 0); + return q; + } +} + +int64_t libdivide_s64_branchfree_do(int64_t numer, const struct libdivide_s64_branchfree_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift and then sign extend + int64_t sign = (int8_t)more >> 7; + int64_t magic = denom->magic; + int64_t q = libdivide_mullhi_s64(magic, numer); + q += numer; + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is a power of + // 2, or (2**shift) if it is not a power of 2. + uint64_t is_power_of_2 = (magic == 0); + uint64_t q_sign = (uint64_t)(q >> 63); + q += q_sign & ((1ULL << shift) - is_power_of_2); + + // Arithmetic right shift + q >>= shift; + // Negate if needed + q = (q ^ sign) - sign; + + return q; +} + +int64_t libdivide_s64_recover(const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + if (denom->magic == 0) { // shift path + uint64_t absD = 1ULL << shift; + if (more & LIBDIVIDE_NEGATIVE_DIVISOR) { + absD = -absD; + } + return (int64_t)absD; + } else { + // Unsigned math is much easier + int negative_divisor = (more & LIBDIVIDE_NEGATIVE_DIVISOR); + int magic_was_negated = (more & LIBDIVIDE_ADD_MARKER) + ? denom->magic > 0 : denom->magic < 0; + + uint64_t d = (uint64_t)(magic_was_negated ? -denom->magic : denom->magic); + uint64_t n_hi = 1ULL << shift, n_lo = 0; + uint64_t rem_ignored; + uint64_t q = libdivide_128_div_64_to_64(n_hi, n_lo, d, &rem_ignored); + int64_t result = (int64_t)(q + 1); + if (negative_divisor) { + result = -result; + } + return result; + } +} + +int64_t libdivide_s64_branchfree_recover(const struct libdivide_s64_branchfree_t *denom) { + return libdivide_s64_recover((const struct libdivide_s64_t *)denom); +}*/ + +#if defined(LIBDIVIDE_AVX512) + +static inline __m512i libdivide_u32_do_vector(__m512i numers, const struct libdivide_u32_t *denom); +static inline __m512i libdivide_s32_do_vector(__m512i numers, const struct libdivide_s32_t *denom); +static inline __m512i libdivide_u64_do_vector(__m512i numers, const struct libdivide_u64_t *denom); +static inline __m512i libdivide_s64_do_vector(__m512i numers, const struct libdivide_s64_t *denom); + +static inline __m512i libdivide_u32_branchfree_do_vector(__m512i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m512i libdivide_s32_branchfree_do_vector(__m512i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m512i libdivide_u64_branchfree_do_vector(__m512i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m512i libdivide_s64_branchfree_do_vector(__m512i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +static inline __m512i libdivide_s64_signbits(__m512i v) {; + return _mm512_srai_epi64(v, 63); +} + +static inline __m512i libdivide_s64_shift_right_vector(__m512i v, int amt) { + return _mm512_srai_epi64(v, amt); +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m512i libdivide_mullhi_u32_vector(__m512i a, __m512i b) { + __m512i hi_product_0Z2Z = _mm512_srli_epi64(_mm512_mul_epu32(a, b), 32); + __m512i a1X3X = _mm512_srli_epi64(a, 32); + __m512i mask = _mm512_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0); + __m512i hi_product_Z1Z3 = _mm512_and_si512(_mm512_mul_epu32(a1X3X, b), mask); + return _mm512_or_si512(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// b is one 32-bit value repeated. +static inline __m512i libdivide_mullhi_s32_vector(__m512i a, __m512i b) { + __m512i hi_product_0Z2Z = _mm512_srli_epi64(_mm512_mul_epi32(a, b), 32); + __m512i a1X3X = _mm512_srli_epi64(a, 32); + __m512i mask = _mm512_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0); + __m512i hi_product_Z1Z3 = _mm512_and_si512(_mm512_mul_epi32(a1X3X, b), mask); + return _mm512_or_si512(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m512i libdivide_mullhi_u64_vector(__m512i x, __m512i y) { + __m512i lomask = _mm512_set1_epi64(0xffffffff); + __m512i xh = _mm512_shuffle_epi32(x, (_MM_PERM_ENUM) 0xB1); + __m512i yh = _mm512_shuffle_epi32(y, (_MM_PERM_ENUM) 0xB1); + __m512i w0 = _mm512_mul_epu32(x, y); + __m512i w1 = _mm512_mul_epu32(x, yh); + __m512i w2 = _mm512_mul_epu32(xh, y); + __m512i w3 = _mm512_mul_epu32(xh, yh); + __m512i w0h = _mm512_srli_epi64(w0, 32); + __m512i s1 = _mm512_add_epi64(w1, w0h); + __m512i s1l = _mm512_and_si512(s1, lomask); + __m512i s1h = _mm512_srli_epi64(s1, 32); + __m512i s2 = _mm512_add_epi64(w2, s1l); + __m512i s2h = _mm512_srli_epi64(s2, 32); + __m512i hi = _mm512_add_epi64(w3, s1h); + hi = _mm512_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m512i libdivide_mullhi_s64_vector(__m512i x, __m512i y) { + __m512i p = libdivide_mullhi_u64_vector(x, y); + __m512i t1 = _mm512_and_si512(libdivide_s64_signbits(x), y); + __m512i t2 = _mm512_and_si512(libdivide_s64_signbits(y), x); + p = _mm512_sub_epi64(p, t1); + p = _mm512_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m512i libdivide_u32_do_vector(__m512i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm512_srli_epi32(numers, more); + } + else { + __m512i q = libdivide_mullhi_u32_vector(numers, _mm512_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m512i t = _mm512_add_epi32(_mm512_srli_epi32(_mm512_sub_epi32(numers, q), 1), q); + return _mm512_srli_epi32(t, shift); + } + else { + return _mm512_srli_epi32(q, more); + } + } +} + +__m512i libdivide_u32_branchfree_do_vector(__m512i numers, const struct libdivide_u32_branchfree_t *denom) { + __m512i q = libdivide_mullhi_u32_vector(numers, _mm512_set1_epi32(denom->magic)); + __m512i t = _mm512_add_epi32(_mm512_srli_epi32(_mm512_sub_epi32(numers, q), 1), q); + return _mm512_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m512i libdivide_u64_do_vector(__m512i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm512_srli_epi64(numers, more); + } + else { + __m512i q = libdivide_mullhi_u64_vector(numers, _mm512_set1_epi64(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m512i t = _mm512_add_epi64(_mm512_srli_epi64(_mm512_sub_epi64(numers, q), 1), q); + return _mm512_srli_epi64(t, shift); + } + else { + return _mm512_srli_epi64(q, more); + } + } +} + +__m512i libdivide_u64_branchfree_do_vector(__m512i numers, const struct libdivide_u64_branchfree_t *denom) { + __m512i q = libdivide_mullhi_u64_vector(numers, _mm512_set1_epi64(denom->magic)); + __m512i t = _mm512_add_epi64(_mm512_srli_epi64(_mm512_sub_epi64(numers, q), 1), q); + return _mm512_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m512i libdivide_s32_do_vector(__m512i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m512i roundToZeroTweak = _mm512_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m512i q = _mm512_add_epi32(numers, _mm512_and_si512(_mm512_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm512_srai_epi32(q, shift); + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm512_sub_epi32(_mm512_xor_si512(q, sign), sign); + return q; + } + else { + __m512i q = libdivide_mullhi_s32_vector(numers, _mm512_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm512_add_epi32(q, _mm512_sub_epi32(_mm512_xor_si512(numers, sign), sign)); + } + // q >>= shift + q = _mm512_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm512_add_epi32(q, _mm512_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m512i libdivide_s32_branchfree_do_vector(__m512i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + __m512i q = libdivide_mullhi_s32_vector(numers, _mm512_set1_epi32(magic)); + q = _mm512_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m512i q_sign = _mm512_srai_epi32(q, 31); // q_sign = q >> 31 + __m512i mask = _mm512_set1_epi32((1U << shift) - is_power_of_2); + q = _mm512_add_epi32(q, _mm512_and_si512(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm512_srai_epi32(q, shift); // q >>= shift + q = _mm512_sub_epi32(_mm512_xor_si512(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m512i libdivide_s64_do_vector(__m512i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m512i roundToZeroTweak = _mm512_set1_epi64(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m512i q = _mm512_add_epi64(numers, _mm512_and_si512(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm512_sub_epi64(_mm512_xor_si512(q, sign), sign); + return q; + } + else { + __m512i q = libdivide_mullhi_s64_vector(numers, _mm512_set1_epi64(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm512_add_epi64(q, _mm512_sub_epi64(_mm512_xor_si512(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm512_add_epi64(q, _mm512_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m512i libdivide_s64_branchfree_do_vector(__m512i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m512i sign = _mm512_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m512i q = libdivide_mullhi_s64_vector(numers, _mm512_set1_epi64(magic)); + q = _mm512_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m512i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m512i mask = _mm512_set1_epi64((1ULL << shift) - is_power_of_2); + q = _mm512_add_epi64(q, _mm512_and_si512(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm512_sub_epi64(_mm512_xor_si512(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#elif defined(LIBDIVIDE_AVX2) + +static inline __m256i libdivide_u32_do_vector(__m256i numers, const struct libdivide_u32_t *denom); +static inline __m256i libdivide_s32_do_vector(__m256i numers, const struct libdivide_s32_t *denom); +static inline __m256i libdivide_u64_do_vector(__m256i numers, const struct libdivide_u64_t *denom); +static inline __m256i libdivide_s64_do_vector(__m256i numers, const struct libdivide_s64_t *denom); + +static inline __m256i libdivide_u32_branchfree_do_vector(__m256i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m256i libdivide_s32_branchfree_do_vector(__m256i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m256i libdivide_u64_branchfree_do_vector(__m256i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m256i libdivide_s64_branchfree_do_vector(__m256i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +// Implementation of _mm256_srai_epi64(v, 63) (from AVX512). +static inline __m256i libdivide_s64_signbits(__m256i v) { + __m256i hiBitsDuped = _mm256_shuffle_epi32(v, _MM_SHUFFLE(3, 3, 1, 1)); + __m256i signBits = _mm256_srai_epi32(hiBitsDuped, 31); + return signBits; +} + +// Implementation of _mm256_srai_epi64 (from AVX512). +static inline __m256i libdivide_s64_shift_right_vector(__m256i v, int amt) { + const int b = 64 - amt; + __m256i m = _mm256_set1_epi64x(1ULL << (b - 1)); + __m256i x = _mm256_srli_epi64(v, amt); + __m256i result = _mm256_sub_epi64(_mm256_xor_si256(x, m), m); + return result; +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m256i libdivide_mullhi_u32_vector(__m256i a, __m256i b) { + __m256i hi_product_0Z2Z = _mm256_srli_epi64(_mm256_mul_epu32(a, b), 32); + __m256i a1X3X = _mm256_srli_epi64(a, 32); + __m256i mask = _mm256_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0); + __m256i hi_product_Z1Z3 = _mm256_and_si256(_mm256_mul_epu32(a1X3X, b), mask); + return _mm256_or_si256(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// b is one 32-bit value repeated. +static inline __m256i libdivide_mullhi_s32_vector(__m256i a, __m256i b) { + __m256i hi_product_0Z2Z = _mm256_srli_epi64(_mm256_mul_epi32(a, b), 32); + __m256i a1X3X = _mm256_srli_epi64(a, 32); + __m256i mask = _mm256_set_epi32(-1, 0, -1, 0, -1, 0, -1, 0); + __m256i hi_product_Z1Z3 = _mm256_and_si256(_mm256_mul_epi32(a1X3X, b), mask); + return _mm256_or_si256(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m256i libdivide_mullhi_u64_vector(__m256i x, __m256i y) { + __m256i lomask = _mm256_set1_epi64x(0xffffffff); + __m256i xh = _mm256_shuffle_epi32(x, 0xB1); // x0l, x0h, x1l, x1h + __m256i yh = _mm256_shuffle_epi32(y, 0xB1); // y0l, y0h, y1l, y1h + __m256i w0 = _mm256_mul_epu32(x, y); // x0l*y0l, x1l*y1l + __m256i w1 = _mm256_mul_epu32(x, yh); // x0l*y0h, x1l*y1h + __m256i w2 = _mm256_mul_epu32(xh, y); // x0h*y0l, x1h*y0l + __m256i w3 = _mm256_mul_epu32(xh, yh); // x0h*y0h, x1h*y1h + __m256i w0h = _mm256_srli_epi64(w0, 32); + __m256i s1 = _mm256_add_epi64(w1, w0h); + __m256i s1l = _mm256_and_si256(s1, lomask); + __m256i s1h = _mm256_srli_epi64(s1, 32); + __m256i s2 = _mm256_add_epi64(w2, s1l); + __m256i s2h = _mm256_srli_epi64(s2, 32); + __m256i hi = _mm256_add_epi64(w3, s1h); + hi = _mm256_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m256i libdivide_mullhi_s64_vector(__m256i x, __m256i y) { + __m256i p = libdivide_mullhi_u64_vector(x, y); + __m256i t1 = _mm256_and_si256(libdivide_s64_signbits(x), y); + __m256i t2 = _mm256_and_si256(libdivide_s64_signbits(y), x); + p = _mm256_sub_epi64(p, t1); + p = _mm256_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m256i libdivide_u32_do_vector(__m256i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm256_srli_epi32(numers, more); + } + else { + __m256i q = libdivide_mullhi_u32_vector(numers, _mm256_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m256i t = _mm256_add_epi32(_mm256_srli_epi32(_mm256_sub_epi32(numers, q), 1), q); + return _mm256_srli_epi32(t, shift); + } + else { + return _mm256_srli_epi32(q, more); + } + } +} + +__m256i libdivide_u32_branchfree_do_vector(__m256i numers, const struct libdivide_u32_branchfree_t *denom) { + __m256i q = libdivide_mullhi_u32_vector(numers, _mm256_set1_epi32(denom->magic)); + __m256i t = _mm256_add_epi32(_mm256_srli_epi32(_mm256_sub_epi32(numers, q), 1), q); + return _mm256_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m256i libdivide_u64_do_vector(__m256i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm256_srli_epi64(numers, more); + } + else { + __m256i q = libdivide_mullhi_u64_vector(numers, _mm256_set1_epi64x(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m256i t = _mm256_add_epi64(_mm256_srli_epi64(_mm256_sub_epi64(numers, q), 1), q); + return _mm256_srli_epi64(t, shift); + } + else { + return _mm256_srli_epi64(q, more); + } + } +} + +__m256i libdivide_u64_branchfree_do_vector(__m256i numers, const struct libdivide_u64_branchfree_t *denom) { + __m256i q = libdivide_mullhi_u64_vector(numers, _mm256_set1_epi64x(denom->magic)); + __m256i t = _mm256_add_epi64(_mm256_srli_epi64(_mm256_sub_epi64(numers, q), 1), q); + return _mm256_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m256i libdivide_s32_do_vector(__m256i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m256i roundToZeroTweak = _mm256_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m256i q = _mm256_add_epi32(numers, _mm256_and_si256(_mm256_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm256_srai_epi32(q, shift); + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm256_sub_epi32(_mm256_xor_si256(q, sign), sign); + return q; + } + else { + __m256i q = libdivide_mullhi_s32_vector(numers, _mm256_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm256_add_epi32(q, _mm256_sub_epi32(_mm256_xor_si256(numers, sign), sign)); + } + // q >>= shift + q = _mm256_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm256_add_epi32(q, _mm256_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m256i libdivide_s32_branchfree_do_vector(__m256i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + __m256i q = libdivide_mullhi_s32_vector(numers, _mm256_set1_epi32(magic)); + q = _mm256_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m256i q_sign = _mm256_srai_epi32(q, 31); // q_sign = q >> 31 + __m256i mask = _mm256_set1_epi32((1U << shift) - is_power_of_2); + q = _mm256_add_epi32(q, _mm256_and_si256(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm256_srai_epi32(q, shift); // q >>= shift + q = _mm256_sub_epi32(_mm256_xor_si256(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m256i libdivide_s64_do_vector(__m256i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m256i roundToZeroTweak = _mm256_set1_epi64x(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m256i q = _mm256_add_epi64(numers, _mm256_and_si256(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm256_sub_epi64(_mm256_xor_si256(q, sign), sign); + return q; + } + else { + __m256i q = libdivide_mullhi_s64_vector(numers, _mm256_set1_epi64x(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm256_add_epi64(q, _mm256_sub_epi64(_mm256_xor_si256(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm256_add_epi64(q, _mm256_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m256i libdivide_s64_branchfree_do_vector(__m256i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m256i sign = _mm256_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m256i q = libdivide_mullhi_s64_vector(numers, _mm256_set1_epi64x(magic)); + q = _mm256_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m256i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m256i mask = _mm256_set1_epi64x((1ULL << shift) - is_power_of_2); + q = _mm256_add_epi64(q, _mm256_and_si256(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm256_sub_epi64(_mm256_xor_si256(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#elif defined(LIBDIVIDE_SSE2) + +static inline __m128i libdivide_u32_do_vector(__m128i numers, const struct libdivide_u32_t *denom); +static inline __m128i libdivide_s32_do_vector(__m128i numers, const struct libdivide_s32_t *denom); +static inline __m128i libdivide_u64_do_vector(__m128i numers, const struct libdivide_u64_t *denom); +static inline __m128i libdivide_s64_do_vector(__m128i numers, const struct libdivide_s64_t *denom); + +static inline __m128i libdivide_u32_branchfree_do_vector(__m128i numers, const struct libdivide_u32_branchfree_t *denom); +static inline __m128i libdivide_s32_branchfree_do_vector(__m128i numers, const struct libdivide_s32_branchfree_t *denom); +static inline __m128i libdivide_u64_branchfree_do_vector(__m128i numers, const struct libdivide_u64_branchfree_t *denom); +static inline __m128i libdivide_s64_branchfree_do_vector(__m128i numers, const struct libdivide_s64_branchfree_t *denom); + +//////// Internal Utility Functions + +// Implementation of _mm_srai_epi64(v, 63) (from AVX512). +static inline __m128i libdivide_s64_signbits(__m128i v) { + __m128i hiBitsDuped = _mm_shuffle_epi32(v, _MM_SHUFFLE(3, 3, 1, 1)); + __m128i signBits = _mm_srai_epi32(hiBitsDuped, 31); + return signBits; +} + +// Implementation of _mm_srai_epi64 (from AVX512). +static inline __m128i libdivide_s64_shift_right_vector(__m128i v, int amt) { + const int b = 64 - amt; + __m128i m = _mm_set1_epi64x(1ULL << (b - 1)); + __m128i x = _mm_srli_epi64(v, amt); + __m128i result = _mm_sub_epi64(_mm_xor_si128(x, m), m); + return result; +} + +// Here, b is assumed to contain one 32-bit value repeated. +static inline __m128i libdivide_mullhi_u32_vector(__m128i a, __m128i b) { + __m128i hi_product_0Z2Z = _mm_srli_epi64(_mm_mul_epu32(a, b), 32); + __m128i a1X3X = _mm_srli_epi64(a, 32); + __m128i mask = _mm_set_epi32(-1, 0, -1, 0); + __m128i hi_product_Z1Z3 = _mm_and_si128(_mm_mul_epu32(a1X3X, b), mask); + return _mm_or_si128(hi_product_0Z2Z, hi_product_Z1Z3); +} + +// SSE2 does not have a signed multiplication instruction, but we can convert +// unsigned to signed pretty efficiently. Again, b is just a 32 bit value +// repeated four times. +static inline __m128i libdivide_mullhi_s32_vector(__m128i a, __m128i b) { + __m128i p = libdivide_mullhi_u32_vector(a, b); + // t1 = (a >> 31) & y, arithmetic shift + __m128i t1 = _mm_and_si128(_mm_srai_epi32(a, 31), b); + __m128i t2 = _mm_and_si128(_mm_srai_epi32(b, 31), a); + p = _mm_sub_epi32(p, t1); + p = _mm_sub_epi32(p, t2); + return p; +} + +// Here, y is assumed to contain one 64-bit value repeated. +// https://stackoverflow.com/a/28827013 +static inline __m128i libdivide_mullhi_u64_vector(__m128i x, __m128i y) { + __m128i lomask = _mm_set1_epi64x(0xffffffff); + __m128i xh = _mm_shuffle_epi32(x, 0xB1); // x0l, x0h, x1l, x1h + __m128i yh = _mm_shuffle_epi32(y, 0xB1); // y0l, y0h, y1l, y1h + __m128i w0 = _mm_mul_epu32(x, y); // x0l*y0l, x1l*y1l + __m128i w1 = _mm_mul_epu32(x, yh); // x0l*y0h, x1l*y1h + __m128i w2 = _mm_mul_epu32(xh, y); // x0h*y0l, x1h*y0l + __m128i w3 = _mm_mul_epu32(xh, yh); // x0h*y0h, x1h*y1h + __m128i w0h = _mm_srli_epi64(w0, 32); + __m128i s1 = _mm_add_epi64(w1, w0h); + __m128i s1l = _mm_and_si128(s1, lomask); + __m128i s1h = _mm_srli_epi64(s1, 32); + __m128i s2 = _mm_add_epi64(w2, s1l); + __m128i s2h = _mm_srli_epi64(s2, 32); + __m128i hi = _mm_add_epi64(w3, s1h); + hi = _mm_add_epi64(hi, s2h); + + return hi; +} + +// y is one 64-bit value repeated. +static inline __m128i libdivide_mullhi_s64_vector(__m128i x, __m128i y) { + __m128i p = libdivide_mullhi_u64_vector(x, y); + __m128i t1 = _mm_and_si128(libdivide_s64_signbits(x), y); + __m128i t2 = _mm_and_si128(libdivide_s64_signbits(y), x); + p = _mm_sub_epi64(p, t1); + p = _mm_sub_epi64(p, t2); + return p; +} + +////////// UINT32 + +__m128i libdivide_u32_do_vector(__m128i numers, const struct libdivide_u32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm_srli_epi32(numers, more); + } + else { + __m128i q = libdivide_mullhi_u32_vector(numers, _mm_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + __m128i t = _mm_add_epi32(_mm_srli_epi32(_mm_sub_epi32(numers, q), 1), q); + return _mm_srli_epi32(t, shift); + } + else { + return _mm_srli_epi32(q, more); + } + } +} + +__m128i libdivide_u32_branchfree_do_vector(__m128i numers, const struct libdivide_u32_branchfree_t *denom) { + __m128i q = libdivide_mullhi_u32_vector(numers, _mm_set1_epi32(denom->magic)); + __m128i t = _mm_add_epi32(_mm_srli_epi32(_mm_sub_epi32(numers, q), 1), q); + return _mm_srli_epi32(t, denom->more); +} + +////////// UINT64 + +__m128i libdivide_u64_do_vector(__m128i numers, const struct libdivide_u64_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + return _mm_srli_epi64(numers, more); + } + else { + __m128i q = libdivide_mullhi_u64_vector(numers, _mm_set1_epi64x(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // uint32_t t = ((numer - q) >> 1) + q; + // return t >> denom->shift; + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + __m128i t = _mm_add_epi64(_mm_srli_epi64(_mm_sub_epi64(numers, q), 1), q); + return _mm_srli_epi64(t, shift); + } + else { + return _mm_srli_epi64(q, more); + } + } +} + +__m128i libdivide_u64_branchfree_do_vector(__m128i numers, const struct libdivide_u64_branchfree_t *denom) { + __m128i q = libdivide_mullhi_u64_vector(numers, _mm_set1_epi64x(denom->magic)); + __m128i t = _mm_add_epi64(_mm_srli_epi64(_mm_sub_epi64(numers, q), 1), q); + return _mm_srli_epi64(t, denom->more); +} + +////////// SINT32 + +__m128i libdivide_s32_do_vector(__m128i numers, const struct libdivide_s32_t *denom) { + uint8_t more = denom->more; + if (!denom->magic) { + uint32_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + uint32_t mask = (1U << shift) - 1; + __m128i roundToZeroTweak = _mm_set1_epi32(mask); + // q = numer + ((numer >> 31) & roundToZeroTweak); + __m128i q = _mm_add_epi32(numers, _mm_and_si128(_mm_srai_epi32(numers, 31), roundToZeroTweak)); + q = _mm_srai_epi32(q, shift); + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm_sub_epi32(_mm_xor_si128(q, sign), sign); + return q; + } + else { + __m128i q = libdivide_mullhi_s32_vector(numers, _mm_set1_epi32(denom->magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm_add_epi32(q, _mm_sub_epi32(_mm_xor_si128(numers, sign), sign)); + } + // q >>= shift + q = _mm_srai_epi32(q, more & LIBDIVIDE_32_SHIFT_MASK); + q = _mm_add_epi32(q, _mm_srli_epi32(q, 31)); // q += (q < 0) + return q; + } +} + +__m128i libdivide_s32_branchfree_do_vector(__m128i numers, const struct libdivide_s32_branchfree_t *denom) { + int32_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_32_SHIFT_MASK; + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + __m128i q = libdivide_mullhi_s32_vector(numers, _mm_set1_epi32(magic)); + q = _mm_add_epi32(q, numers); // q += numers + + // If q is non-negative, we have nothing to do + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2 + uint32_t is_power_of_2 = (magic == 0); + __m128i q_sign = _mm_srai_epi32(q, 31); // q_sign = q >> 31 + __m128i mask = _mm_set1_epi32((1U << shift) - is_power_of_2); + q = _mm_add_epi32(q, _mm_and_si128(q_sign, mask)); // q = q + (q_sign & mask) + q = _mm_srai_epi32(q, shift); // q >>= shift + q = _mm_sub_epi32(_mm_xor_si128(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +////////// SINT64 + +__m128i libdivide_s64_do_vector(__m128i numers, const struct libdivide_s64_t *denom) { + uint8_t more = denom->more; + int64_t magic = denom->magic; + if (magic == 0) { // shift path + uint32_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + uint64_t mask = (1ULL << shift) - 1; + __m128i roundToZeroTweak = _mm_set1_epi64x(mask); + // q = numer + ((numer >> 63) & roundToZeroTweak); + __m128i q = _mm_add_epi64(numers, _mm_and_si128(libdivide_s64_signbits(numers), roundToZeroTweak)); + q = libdivide_s64_shift_right_vector(q, shift); + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q = (q ^ sign) - sign; + q = _mm_sub_epi64(_mm_xor_si128(q, sign), sign); + return q; + } + else { + __m128i q = libdivide_mullhi_s64_vector(numers, _mm_set1_epi64x(magic)); + if (more & LIBDIVIDE_ADD_MARKER) { + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + // q += ((numer ^ sign) - sign); + q = _mm_add_epi64(q, _mm_sub_epi64(_mm_xor_si128(numers, sign), sign)); + } + // q >>= denom->mult_path.shift + q = libdivide_s64_shift_right_vector(q, more & LIBDIVIDE_64_SHIFT_MASK); + q = _mm_add_epi64(q, _mm_srli_epi64(q, 63)); // q += (q < 0) + return q; + } +} + +__m128i libdivide_s64_branchfree_do_vector(__m128i numers, const struct libdivide_s64_branchfree_t *denom) { + int64_t magic = denom->magic; + uint8_t more = denom->more; + uint8_t shift = more & LIBDIVIDE_64_SHIFT_MASK; + // must be arithmetic shift + __m128i sign = _mm_set1_epi32((int8_t)more >> 7); + + // libdivide_mullhi_s64(numers, magic); + __m128i q = libdivide_mullhi_s64_vector(numers, _mm_set1_epi64x(magic)); + q = _mm_add_epi64(q, numers); // q += numers + + // If q is non-negative, we have nothing to do. + // If q is negative, we want to add either (2**shift)-1 if d is + // a power of 2, or (2**shift) if it is not a power of 2. + uint32_t is_power_of_2 = (magic == 0); + __m128i q_sign = libdivide_s64_signbits(q); // q_sign = q >> 63 + __m128i mask = _mm_set1_epi64x((1ULL << shift) - is_power_of_2); + q = _mm_add_epi64(q, _mm_and_si128(q_sign, mask)); // q = q + (q_sign & mask) + q = libdivide_s64_shift_right_vector(q, shift); // q >>= shift + q = _mm_sub_epi64(_mm_xor_si128(q, sign), sign); // q = (q ^ sign) - sign + return q; +} + +#endif + +/////////// C++ stuff + +#ifdef __cplusplus + +// The C++ divider class is templated on both an integer type +// (like uint64_t) and an algorithm type. +// * BRANCHFULL is the default algorithm type. +// * BRANCHFREE is the branchfree algorithm type. +enum { + BRANCHFULL, + BRANCHFREE +}; + +#if defined(LIBDIVIDE_AVX512) + #define LIBDIVIDE_VECTOR_TYPE __m512i +#elif defined(LIBDIVIDE_AVX2) + #define LIBDIVIDE_VECTOR_TYPE __m256i +#elif defined(LIBDIVIDE_SSE2) + #define LIBDIVIDE_VECTOR_TYPE __m128i +#endif + +#if !defined(LIBDIVIDE_VECTOR_TYPE) + #define LIBDIVIDE_DIVIDE_VECTOR(ALGO) +#else + #define LIBDIVIDE_DIVIDE_VECTOR(ALGO) \ + LIBDIVIDE_VECTOR_TYPE divide(LIBDIVIDE_VECTOR_TYPE n) const { \ + return libdivide_##ALGO##_do_vector(n, &denom); \ + } +#endif + +// The DISPATCHER_GEN() macro generates C++ methods (for the given integer +// and algorithm types) that redirect to libdivide's C API. +#define DISPATCHER_GEN(T, ALGO) \ + libdivide_##ALGO##_t denom; \ + dispatcher() { } \ + dispatcher(T d) \ + : denom(libdivide_##ALGO##_gen(d)) \ + { } \ + T divide(T n) const { \ + return libdivide_##ALGO##_do(n, &denom); \ + } \ + LIBDIVIDE_DIVIDE_VECTOR(ALGO) \ + T recover() const { \ + return libdivide_##ALGO##_recover(&denom); \ + } + +// The dispatcher selects a specific division algorithm for a given +// type and ALGO using partial template specialization. +template struct dispatcher { }; + +template<> struct dispatcher { DISPATCHER_GEN(int32_t, s32) }; +template<> struct dispatcher { DISPATCHER_GEN(int32_t, s32_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(uint32_t, u32) }; +template<> struct dispatcher { DISPATCHER_GEN(uint32_t, u32_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(int64_t, s64) }; +template<> struct dispatcher { DISPATCHER_GEN(int64_t, s64_branchfree) }; +template<> struct dispatcher { DISPATCHER_GEN(uint64_t, u64) }; +template<> struct dispatcher { DISPATCHER_GEN(uint64_t, u64_branchfree) }; + +// This is the main divider class for use by the user (C++ API). +// The actual division algorithm is selected using the dispatcher struct +// based on the integer and algorithm template parameters. +template +class divider { +public: + // We leave the default constructor empty so that creating + // an array of dividers and then initializing them + // later doesn't slow us down. + divider() { } + + // Constructor that takes the divisor as a parameter + divider(T d) : div(d) { } + + // Divides n by the divisor + T divide(T n) const { + return div.divide(n); + } + + // Recovers the divisor, returns the value that was + // used to initialize this divider object. + T recover() const { + return div.recover(); + } + + bool operator==(const divider& other) const { + return div.denom.magic == other.denom.magic && + div.denom.more == other.denom.more; + } + + bool operator!=(const divider& other) const { + return !(*this == other); + } + +#if defined(LIBDIVIDE_VECTOR_TYPE) + // Treats the vector as packed integer values with the same type as + // the divider (e.g. s32, u32, s64, u64) and divides each of + // them by the divider, returning the packed quotients. + LIBDIVIDE_VECTOR_TYPE divide(LIBDIVIDE_VECTOR_TYPE n) const { + return div.divide(n); + } +#endif + +private: + // Storage for the actual divisor + dispatcher::value, + std::is_signed::value, sizeof(T), ALGO> div; +}; + +// Overload of operator / for scalar division +template +T operator/(T n, const divider& div) { + return div.divide(n); +} + +// Overload of operator /= for scalar division +template +T& operator/=(T& n, const divider& div) { + n = div.divide(n); + return n; +} + +#if defined(LIBDIVIDE_VECTOR_TYPE) + // Overload of operator / for vector division + template + LIBDIVIDE_VECTOR_TYPE operator/(LIBDIVIDE_VECTOR_TYPE n, const divider& div) { + return div.divide(n); + } + // Overload of operator /= for vector division + template + LIBDIVIDE_VECTOR_TYPE& operator/=(LIBDIVIDE_VECTOR_TYPE& n, const divider& div) { + n = div.divide(n); + return n; + } +#endif + +// libdivdie::branchfree_divider +template +using branchfree_divider = divider; + +} // namespace libdivide + +#endif // __cplusplus + +#endif // LIBDIVIDE_H diff --git a/src/r_draw.c b/src/r_draw.c index 2b798c3bf..cb8187521 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -25,6 +25,7 @@ #include "w_wad.h" #include "z_zone.h" #include "console.h" // Until buffering gets finished +#include "libdivide.h" // used by NPO2 tilted span functions #ifdef HWRENDER #include "hardware/hw_main.h" diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 020155694..b280cbd49 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -83,6 +83,9 @@ void R_DrawTiltedSpan_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -122,12 +125,13 @@ void R_DrawTiltedSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -174,12 +178,13 @@ void R_DrawTiltedSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -205,12 +210,13 @@ void R_DrawTiltedSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -241,12 +247,13 @@ void R_DrawTiltedSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = colormap[source[((y * ds_flatwidth) + x)]]; } @@ -279,6 +286,9 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -317,12 +327,13 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -369,12 +380,13 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -400,12 +412,13 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -436,12 +449,13 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); } @@ -473,6 +487,9 @@ void R_DrawTiltedSplat_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -512,12 +529,13 @@ void R_DrawTiltedSplat_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -568,12 +586,13 @@ void R_DrawTiltedSplat_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -601,12 +620,13 @@ void R_DrawTiltedSplat_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -640,12 +660,13 @@ void R_DrawTiltedSplat_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; val = source[((y * ds_flatwidth) + x)]; } @@ -864,6 +885,9 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) double endz, endu, endv; UINT32 stepu, stepv; + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end @@ -903,12 +927,13 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } @@ -955,12 +980,13 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } @@ -986,12 +1012,13 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } @@ -1022,12 +1049,13 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) // Carefully align all of my Friends. if (x < 0) - x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; if (y < 0) - y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); - - x %= ds_flatwidth; - y %= ds_flatheight; + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); } diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index c2d6456e4..9b3214067 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -244,6 +244,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 438746ac7..425bbfcc0 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -402,6 +402,9 @@ P_Play + + R_Rend + R_Rend From 724d126015db83170329f606572491f1f191b9c9 Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Sat, 31 Oct 2020 16:39:05 +0200 Subject: [PATCH 002/241] Clarify licensing-related text in libdivide.h --- src/libdivide.h | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/libdivide.h b/src/libdivide.h index 51f9a633b..915da0070 100644 --- a/src/libdivide.h +++ b/src/libdivide.h @@ -8,8 +8,37 @@ // You may use libdivide under the terms of either of these. // See LICENSE.txt for more details. -// NOTICE: This version of libdivide has been modified for use with SRB2. -// Changes made: + +// NOTICE: This is an altered source version of libdivide. +// Libdivide is used here under the terms of the zlib license. +// Here is the zlib license text from https://github.com/ridiculousfish/libdivide/blob/master/LICENSE.txt +/* + zlib License + ------------ + + Copyright (C) 2010 - 2019 ridiculous_fish, + Copyright (C) 2016 - 2019 Kim Walisch, + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +// This version of libdivide has been modified for use with SRB2. +// Changes made include: // - unused parts commented out (to avoid the need to fix C90 compilation issues with them) // - C90 compilation issues fixed with used parts // - use I_Error for errors From cc8bd7ef5928b01729dfe6b20bc94b0e43dad16f Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Sat, 7 Nov 2020 00:19:43 +0200 Subject: [PATCH 003/241] Clarify license file mention in libdivide.h --- src/libdivide.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libdivide.h b/src/libdivide.h index 915da0070..1a589c7e5 100644 --- a/src/libdivide.h +++ b/src/libdivide.h @@ -6,7 +6,7 @@ // // libdivide is dual-licensed under the Boost or zlib licenses. // You may use libdivide under the terms of either of these. -// See LICENSE.txt for more details. +// See LICENSE.txt in the libdivide source code repository for more details. // NOTICE: This is an altered source version of libdivide. From b2544395926ed4c5f7ec02a91e486feb6ba5b78d Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Wed, 2 Dec 2020 00:17:57 -0500 Subject: [PATCH 004/241] Update hw_light.c --- src/hardware/hw_light.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 987d70c69..76fecd7aa 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -340,6 +340,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_BMCH &lspr[NOLIGHT], // SPR_SMCE &lspr[NOLIGHT], // SPR_BMCE + &lspr[NOLIGHT], // SPR_BSPB &lspr[NOLIGHT], // SPR_YSPB &lspr[NOLIGHT], // SPR_RSPB &lspr[REDBALL_L], // SPR_SFBR From c98108df2764e1cdcd8537655d3b479be1b3b4ea Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Thu, 3 Dec 2020 00:46:28 +0000 Subject: [PATCH 005/241] Revert "Update hw_light.c" This reverts commit b2544395926ed4c5f7ec02a91e486feb6ba5b78d --- src/hardware/hw_light.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 76fecd7aa..987d70c69 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -340,7 +340,6 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_BMCH &lspr[NOLIGHT], // SPR_SMCE &lspr[NOLIGHT], // SPR_BMCE - &lspr[NOLIGHT], // SPR_BSPB &lspr[NOLIGHT], // SPR_YSPB &lspr[NOLIGHT], // SPR_RSPB &lspr[REDBALL_L], // SPR_SFBR From 8d382e49fb3411cad1a3ef5ee1e546030c3a9d93 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 17 Nov 2020 04:14:45 -0800 Subject: [PATCH 006/241] Big Large Lua Hooklib Refactor * Hooks are no longer a mess of lua boiler plate. Helper functions reduce hooks to, at the most basic level, only two calls. * Lua tables (the array part) are used to index hooks. Such tables contain only hooks of the same type. * Hook types are defined in one place so you no longer need to sync up the enum and name array. --- src/b_bot.c | 6 +- src/d_clisrv.c | 12 +- src/d_netcmd.c | 10 +- src/doomtype.h | 2 + src/g_demo.c | 2 +- src/g_game.c | 10 +- src/hu_stuff.c | 2 +- src/lua_hook.h | 191 ++-- src/lua_hooklib.c | 2630 +++++++++++++++------------------------------ src/lua_script.c | 4 +- src/lua_script.h | 2 +- src/m_menu.c | 4 +- src/p_enemy.c | 2 +- src/p_inter.c | 16 +- src/p_map.c | 8 +- src/p_mobj.c | 22 +- src/p_setup.c | 4 +- src/p_spec.c | 4 +- src/p_tick.c | 12 +- src/p_user.c | 40 +- src/s_sound.c | 12 +- src/s_sound.h | 10 + src/sdl/i_video.c | 2 +- src/y_inter.c | 2 +- 24 files changed, 1055 insertions(+), 1954 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index d3635f32c..93a853dee 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -75,7 +75,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) return; // Lua can handle it! - if (LUAh_BotAI(sonic, tails, cmd)) + if (LUA_HookBotAI(sonic, tails, cmd)) return; if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC) @@ -363,7 +363,7 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) CV_SetValue(&cv_analog[1], false); // Let Lua scripts build ticcmds - if (LUAh_BotTiccmd(player, cmd)) + if (LUA_HookTiccmd(player, cmd, Hook(BotTiccmd))) return; // We don't have any main character AI, sorry. D: @@ -461,7 +461,7 @@ boolean B_CheckRespawn(player_t *player) // B_RespawnBot doesn't do anything if the condition above this isn't met { - UINT8 shouldForce = LUAh_BotRespawn(sonic, tails); + UINT8 shouldForce = LUA_Hook2Mobj(sonic, tails, Mobj_Hook(BotRespawn)); if (P_MobjWasRemoved(sonic) || P_MobjWasRemoved(tails)) return (shouldForce == 1); // mobj was removed diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 14fc1aea5..91918ed35 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2537,14 +2537,14 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason) } } - LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting + LUA_HookPlayerQuit(&players[playernum], reason); // Lua hook for player quitting // don't look through someone's view who isn't there if (playernum == displayplayer) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); + LUA_HookViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -3025,7 +3025,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (pnum == consoleplayer) { if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); #ifdef DUMPCONSISTENCY if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); #endif @@ -3445,7 +3445,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); if (!rejoined) - LUAh_PlayerJoin(newplayernum); + LUA_HookInt(newplayernum, Hook(PlayerJoin)); } static boolean SV_AddWaitingPlayers(const char *name, const char *name2) @@ -3726,7 +3726,7 @@ static void HandleShutdown(SINT8 node) { (void)node; if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -3742,7 +3742,7 @@ static void HandleTimeout(SINT8 node) { (void)node; if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); D_QuitNetGame(); CL_Reset(); D_StartTitle(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 31c10f58a..baad9bcdf 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2103,7 +2103,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) } mapnumber = M_MapNumber(mapname[3], mapname[4]); - LUAh_MapChange(mapnumber); + LUA_HookInt(mapnumber, Hook(MapChange)); G_InitNew(ultimatemode, mapname, resetplayer, skipprecutscene, FLS); if (demoplayback && !timingdemo) @@ -2688,7 +2688,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } // Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh - if (!LUAh_TeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) + if (!LUA_HookTeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) return; //no status changes after hidetime @@ -2849,7 +2849,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. if (displayplayer != consoleplayer) // You're already viewing yourself. No big deal. - LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); + LUA_HookViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -3607,7 +3607,7 @@ static void Command_Playintro_f(void) FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void) { if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); I_Quit(); } @@ -4270,7 +4270,7 @@ void Command_ExitGame_f(void) INT32 i; if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); D_QuitNetGame(); CL_Reset(); diff --git a/src/doomtype.h b/src/doomtype.h index 4e13ba96d..8bfedbe92 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -367,6 +367,8 @@ typedef UINT32 tic_t; #define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24) #endif +#define TOSTR(x) #x + /* preprocessor dumb and needs second macro to expand input */ #define WSTRING2(s) L ## s #define WSTRING(s) WSTRING2 (s) diff --git a/src/g_demo.c b/src/g_demo.c index 593fd7723..e4af7086c 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1956,7 +1956,7 @@ void G_DoPlayDemo(char *defdemoname) // Set skin SetPlayerSkin(0, skin); - LUAh_MapChange(gamemap); + LUA_HookInt(gamemap, Hook(MapChange)); displayplayer = consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); playeringame[0] = true; diff --git a/src/g_game.c b/src/g_game.c index 283113bbe..c0aaf6af7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1689,7 +1689,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->angleturn = orighookangle; - LUAh_PlayerCmd(player, cmd); + LUA_HookTiccmd(player, cmd, Hook(PlayerCmd)); extra = cmd->angleturn - orighookangle; cmd->angleturn = origangle + extra; @@ -1703,7 +1703,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -2076,7 +2076,7 @@ boolean G_Responder(event_t *ev) continue; // Call ViewpointSwitch hooks here. - canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); + canSwitchView = LUA_HookViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); if (canSwitchView == 1) // Set viewpoint to this player break; else if (canSwitchView == 2) // Skip this player @@ -2713,7 +2713,7 @@ void G_SpawnPlayer(INT32 playernum) P_SpawnPlayer(playernum); G_MovePlayerToSpawnOrStarpost(playernum); - LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) + LUA_HookPlayer(&players[playernum], Hook(PlayerSpawn)); // Lua hook for player spawning :) } void G_MovePlayerToSpawnOrStarpost(INT32 playernum) @@ -3092,7 +3092,7 @@ void G_DoReborn(INT32 playernum) } else { - LUAh_MapChange(gamemap); + LUA_HookInt(gamemap, Hook(MapChange)); titlecardforreload = true; G_DoLoadLevel(true); titlecardforreload = false; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7e9144f98..9516b466b 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -684,7 +684,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. - if (LUAh_PlayerMsg(playernum, target, flags, msg)) + if (LUA_HookPlayerMsg(playernum, target, flags, msg)) return; if (spam_eatmsg) diff --git a/src/lua_hook.h b/src/lua_hook.h index 796f3a9d2..f44a2e305 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -12,111 +12,100 @@ #include "r_defs.h" #include "d_player.h" +#include "s_sound.h" -enum hook { - hook_NetVars=0, - hook_MapChange, - hook_MapLoad, - hook_PlayerJoin, - hook_PreThinkFrame, - hook_ThinkFrame, - hook_PostThinkFrame, - hook_MobjSpawn, - hook_MobjCollide, - hook_MobjLineCollide, - hook_MobjMoveCollide, - hook_TouchSpecial, - hook_MobjFuse, - hook_MobjThinker, - hook_BossThinker, - hook_ShouldDamage, - hook_MobjDamage, - hook_MobjDeath, - hook_BossDeath, - hook_MobjRemoved, - hook_JumpSpecial, - hook_AbilitySpecial, - hook_SpinSpecial, - hook_JumpSpinSpecial, - hook_BotTiccmd, - hook_BotAI, - hook_BotRespawn, - hook_LinedefExecute, - hook_PlayerMsg, - hook_HurtMsg, - hook_PlayerSpawn, - hook_ShieldSpawn, - hook_ShieldSpecial, - hook_MobjMoveBlocked, - hook_MapThingSpawn, - hook_FollowMobj, - hook_PlayerCanDamage, - hook_PlayerQuit, - hook_IntermissionThinker, - hook_TeamSwitch, - hook_ViewpointSwitch, - hook_SeenPlayer, - hook_PlayerThink, - hook_ShouldJingleContinue, - hook_GameQuit, - hook_PlayerCmd, - hook_MusicChange, +#define Mobj_Hook_List(X) \ + X (MobjSpawn),/* P_SpawnMobj */\ + X (MobjCollide),/* PIT_CheckThing */\ + X (MobjLineCollide),/* ditto */\ + X (MobjMoveCollide),/* tritto */\ + X (TouchSpecial),/* P_TouchSpecialThing */\ + X (MobjFuse),/* when mobj->fuse runs out */\ + X (MobjThinker),/* P_MobjThinker, P_SceneryThinker */\ + X (BossThinker),/* P_GenericBossThinker */\ + X (ShouldDamage),/* P_DamageMobj (Should mobj take damage?) */\ + X (MobjDamage),/* P_DamageMobj (Mobj actually takes damage!) */\ + X (MobjDeath),/* P_KillMobj */\ + X (BossDeath),/* A_BossDeath */\ + X (MobjRemoved),/* P_RemoveMobj */\ + X (BotRespawn),/* B_CheckRespawn */\ + X (MobjMoveBlocked),/* P_XYMovement (when movement is blocked) */\ + X (MapThingSpawn),/* P_SpawnMapThing */\ + X (FollowMobj),/* P_PlayerAfterThink Smiles mobj-following */\ - hook_MAX // last hook -}; -extern const char *const hookNames[]; +#define Hook_List(X) \ + X (NetVars),/* add to archive table (netsave) */\ + X (MapChange),/* (before map load) */\ + X (MapLoad),\ + X (PlayerJoin),/* Got_AddPlayer */\ + X (PreThinkFrame)/* frame (before mobj and player thinkers) */,\ + X (ThinkFrame),/* frame (after mobj and player thinkers) */\ + X (PostThinkFrame),/* frame (at end of tick, ie after overlays, precipitation, specials) */\ + X (JumpSpecial),/* P_DoJumpStuff (Any-jumping) */\ + X (AbilitySpecial),/* P_DoJumpStuff (Double-jumping) */\ + X (SpinSpecial),/* P_DoSpinAbility (Spin button effect) */\ + X (JumpSpinSpecial),/* P_DoJumpStuff (Spin button effect (mid-air)) */\ + X (BotTiccmd),/* B_BuildTiccmd */\ + X (PlayerMsg),/* chat messages */\ + X (HurtMsg),/* imhurttin */\ + X (PlayerSpawn),/* G_SpawnPlayer */\ + X (ShieldSpawn),/* P_SpawnShieldOrb */\ + X (ShieldSpecial),/* shield abilities */\ + X (PlayerCanDamage),/* P_PlayerCanDamage */\ + X (PlayerQuit),\ + X (IntermissionThinker),/* Y_Ticker */\ + X (TeamSwitch),/* team switching in... uh... *what* speak, spit it the fuck out */\ + X (ViewpointSwitch),/* spy mode (no trickstabs) */\ + X (SeenPlayer),/* MT_NAMECHECK */\ + X (PlayerThink),/* P_PlayerThink */\ + X (GameQuit),\ + X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ + X (MusicChange),\ + +#define String_Hook_List(X) \ + X (BotAI),/* B_BuildTailsTiccmd by skin name */\ + X (LinedefExecute),\ + X (ShouldJingleContinue),/* should jingle of the given music continue playing */\ + +#define Mobj_Hook(name) mobjhook_ ## name +#define Hook(name) hook_ ## name +#define String_Hook(name) stringhook_ ## name + +enum { Mobj_Hook_List (Mobj_Hook) Mobj_Hook(MAX) }; +enum { Hook_List (Hook) Hook(MAX) }; +enum { String_Hook_List (String_Hook) String_Hook(MAX) }; extern boolean hook_cmd_running; -void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load) -void LUAh_MapLoad(void); // Hook for map load -void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer -void LUAh_PreThinkFrame(void); // Hook for frame (before mobj and player thinkers) -void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers) -void LUAh_PostThinkFrame(void); // Hook for frame (at end of tick, ie after overlays, precipitation, specials) -boolean LUAh_MobjHook(mobj_t *mo, enum hook which); -boolean LUAh_PlayerHook(player_t *plr, enum hook which); -#define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type -UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which); -UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which); -#define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type -#define LUAh_MobjLineCollide(thing, line) LUAh_MobjLineCollideHook(thing, line, hook_MobjLineCollide) // Hook for PIT_CheckThing by (thing) mobj type -#define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type -boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type -#define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type -boolean LUAh_MobjThinker(mobj_t *mo); // Hook for P_MobjThinker or P_SceneryThinker by mobj type -#define LUAh_BossThinker(mo) LUAh_MobjHook(mo, hook_BossThinker) // Hook for P_GenericBossThinker by mobj type -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Should mobj take damage?) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for P_KillMobj by mobj type -#define LUAh_BossDeath(mo) LUAh_MobjHook(mo, hook_BossDeath) // Hook for A_BossDeath by mobj type -#define LUAh_MobjRemoved(mo) LUAh_MobjHook(mo, hook_MobjRemoved) // Hook for P_RemoveMobj by mobj type -#define LUAh_JumpSpecial(player) LUAh_PlayerHook(player, hook_JumpSpecial) // Hook for P_DoJumpStuff (Any-jumping) -#define LUAh_AbilitySpecial(player) LUAh_PlayerHook(player, hook_AbilitySpecial) // Hook for P_DoJumpStuff (Double-jumping) -#define LUAh_SpinSpecial(player) LUAh_PlayerHook(player, hook_SpinSpecial) // Hook for P_DoSpinAbility (Spin button effect) -#define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air)) -boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd -boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name -boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails); // Hook for B_CheckRespawn -boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for hurt messages -#define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer -#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb -#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities -#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) -boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type -boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following -UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage -void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting -void LUAh_IntermissionThinker(void); // Hook for Y_Ticker -boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... -UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode +/* dead simple, LUA_Hook(GameQuit) */ +void LUA_Hook(int hook); +#define LUA_Hook(type) LUA_Hook(Hook(type)) + +int LUA_HookMobj(mobj_t *, int hook); +int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); +void LUA_HookInt(INT32 integer, int hook); +int LUA_HookPlayer(player_t *, int hook); +int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); + +void LUA_HookThinkFrame(void); +int LUA_HookMobjLineCollide(mobj_t *, line_t *); +int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher); +int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); +int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); +int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); +int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); +void LUA_HookLinedefExecute(line_t *, mobj_t *, sector_t *); +int LUA_HookPlayerMsg(int source, int target, int flags, char *msg); +int LUA_HookHurtMsg(player_t *, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); +int LUA_HookMapThingSpawn(mobj_t *, mapthing_t *); +int LUA_HookFollowMobj(player_t *, mobj_t *); +int LUA_HookPlayerCanDamage(player_t *, mobj_t *); +void LUA_HookPlayerQuit(player_t *, kickreason_t); +int LUA_HookTeamSwitch(player_t *, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); +int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); #ifdef SEENAMES -boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK +int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend); #endif -#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink -boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing -void LUAh_GameQuit(void); // Hook for game quitting -boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart) -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes \ No newline at end of file +int LUA_HookShouldJingleContinue(player_t *, const char *musname); +int LUA_HookPlayerCmd(player_t *, ticcmd_t *); +int LUA_HookMusicChange(const char *oldname, struct MusicChange *); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 117aa48a3..dce67cef7 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -27,1948 +27,1038 @@ #include "d_netcmd.h" // for cv_perfstats #include "i_system.h" // I_GetTimeMicros -static UINT8 hooksAvailable[(hook_MAX/8)+1]; +#undef LUA_Hook -const char *const hookNames[hook_MAX+1] = { - "NetVars", - "MapChange", - "MapLoad", - "PlayerJoin", - "PreThinkFrame", - "ThinkFrame", - "PostThinkFrame", - "MobjSpawn", - "MobjCollide", - "MobjLineCollide", - "MobjMoveCollide", - "TouchSpecial", - "MobjFuse", - "MobjThinker", - "BossThinker", - "ShouldDamage", - "MobjDamage", - "MobjDeath", - "BossDeath", - "MobjRemoved", - "JumpSpecial", - "AbilitySpecial", - "SpinSpecial", - "JumpSpinSpecial", - "BotTiccmd", - "BotAI", - "BotRespawn", - "LinedefExecute", - "PlayerMsg", - "HurtMsg", - "PlayerSpawn", - "ShieldSpawn", - "ShieldSpecial", - "MobjMoveBlocked", - "MapThingSpawn", - "FollowMobj", - "PlayerCanDamage", - "PlayerQuit", - "IntermissionThinker", - "TeamSwitch", - "ViewpointSwitch", - "SeenPlayer", - "PlayerThink", - "ShouldJingleContinue", - "GameQuit", - "PlayerCmd", - "MusicChange", - NULL +/* ========================================================================= + ABSTRACTION + ========================================================================= */ + +static const char * const mobjHookNames[] = { Mobj_Hook_List (TOSTR) NULL }; +static const char * const hookNames[] = { Hook_List (TOSTR) NULL }; + +static const char * const stringHookNames[] = { + String_Hook_List (TOSTR) NULL }; -// Hook metadata -struct hook_s +/* TODO: remove when doomtype version is merged */ + +#define BIT_ARRAY_LENGTH(n) (((n) + 7) >> 3) + +static inline void set_bit_array (UINT8 *array, const int n) { + array[n >> 3] |= 1 << (n & 7); +} + +static inline int in_bit_array (const UINT8 *array, const int n) { + return array[n >> 3] & (1 << (n & 7)); +} + +typedef struct { + int numGeneric; + int ref; +} stringhook_t; + +static int hookRefs[Hook(MAX)]; +static int mobjHookRefs[NUMMOBJTYPES][Mobj_Hook(MAX)]; + +static stringhook_t stringHooks[String_Hook(MAX)]; + +static int hookReg; + +// After a hook errors once, don't print the error again. +static UINT8 * hooksErrored; + +static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) { - struct hook_s *next; - enum hook type; - UINT16 id; - union { - mobjtype_t mt; - char *str; - } s; - boolean error; -}; -typedef struct hook_s* hook_p; + return + ( + mobjHookRefs [MT_NULL] [hook_type] > 0 || + mobjHookRefs[mobj_type][hook_type] > 0 + ); +} -#define FMT_HOOKID "hook_%d" +static int hook_in_list +( + const char * const name, + const char * const * const list +){ + int type; -// For each mobj type, a linked list to its thinker and collision hooks. -// That way, we don't have to iterate through all the hooks. -// We could do that with all other mobj hooks, but it would probably just be -// a waste of memory since they are only called occasionally. Probably... -static hook_p mobjthinkerhooks[NUMMOBJTYPES]; -static hook_p mobjcollidehooks[NUMMOBJTYPES]; + for (type = 0; list[type] != NULL; ++type) + { + if (strcmp(name, list[type]) == 0) + break; + } -// For each mobj type, a linked list for other mobj hooks -static hook_p mobjhooks[NUMMOBJTYPES]; + return type; +} -// A linked list for player hooks -static hook_p playerhooks; - -// A linked list for linedef executor hooks -static hook_p linedefexecutorhooks; - -// For other hooks, a unique linked list -hook_p roothook; - -static void PushHook(lua_State *L, hook_p hookp) +static void get_table(lua_State *L) { - lua_pushfstring(L, FMT_HOOKID, hookp->id); - lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, -1); + lua_rawget(L, -3); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_createtable(L, 1, 0); + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, -5); + } + + lua_remove(L, -2); +} + +static void new_hook_table(lua_State *L, int *ref) +{ + if (*ref > 0) + lua_getref(L, *ref); + else + { + lua_newtable(L); + lua_pushvalue(L, -1); + *ref = luaL_ref(L, LUA_REGISTRYINDEX); + } +} + +static void add_hook(lua_State *L, int id) +{ + lua_pushnumber(L, 1 + id); + lua_rawseti(L, -2, 1 + lua_objlen(L, -2)); +} + +static void add_mobj_hook(lua_State *L, int hook_type, int id) +{ + mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL); + + luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t"); + + new_hook_table(L, &mobjHookRefs[mobj_type][hook_type]); + add_hook(L, id); +} + +static void add_string_hook(lua_State *L, int type, int id) +{ + stringhook_t * hook = &stringHooks[type]; + + char * string = NULL; + + switch (type) + { + case String_Hook(BotAI): + case String_Hook(ShouldJingleContinue): + if (lua_isstring(L, 3)) + { // lowercase copy + string = Z_StrDup(lua_tostring(L, 3)); + strlwr(string); + } + break; + + case String_Hook(LinedefExecute): + string = Z_StrDup(luaL_checkstring(L, 3)); + strupr(string); + break; + } + + new_hook_table(L, &hook->ref); + + if (string) + { + lua_pushstring(L, string); + get_table(L); + add_hook(L, id); + } + else + { + lua_pushnumber(L, 1 + id); + lua_rawseti(L, -2, ++hook->numGeneric); + } } // Takes hook, function, and additional arguments (mobj type to act on, etc.) static int lib_addHook(lua_State *L) { - static struct hook_s hook = {NULL, 0, 0, {0}, false}; - static UINT32 nextid; - hook_p hookp, *lastp; + static int nextid; - hook.type = luaL_checkoption(L, 1, NULL, hookNames); - lua_remove(L, 1); - - luaL_checktype(L, 1, LUA_TFUNCTION); + const char * name; + int type; if (!lua_lumploading) return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); - switch(hook.type) + name = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + + /* this is a very special case */ + if (( type = hook_in_list(name, stringHookNames) ) < String_Hook(MAX)) { - // Take a mobjtype enum which this hook is specifically for. - case hook_MobjSpawn: - case hook_MobjCollide: - case hook_MobjLineCollide: - case hook_MobjMoveCollide: - case hook_TouchSpecial: - case hook_MobjFuse: - case hook_MobjThinker: - case hook_BossThinker: - case hook_ShouldDamage: - case hook_MobjDamage: - case hook_MobjDeath: - case hook_BossDeath: - case hook_MobjRemoved: - case hook_HurtMsg: - case hook_MobjMoveBlocked: - case hook_MapThingSpawn: - case hook_FollowMobj: - hook.s.mt = MT_NULL; - if (lua_isnumber(L, 2)) - hook.s.mt = lua_tonumber(L, 2); - luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t"); - break; - case hook_BotAI: - case hook_ShouldJingleContinue: - hook.s.str = NULL; - if (lua_isstring(L, 2)) - { // lowercase copy - hook.s.str = Z_StrDup(lua_tostring(L, 2)); - strlwr(hook.s.str); - } - break; - case hook_LinedefExecute: // Linedef executor functions - hook.s.str = Z_StrDup(luaL_checkstring(L, 2)); - strupr(hook.s.str); - break; - default: - break; + add_string_hook(L, type, nextid); } - lua_settop(L, 1); // lua stack contains only the function now. - - hooksAvailable[hook.type/8] |= 1<<(hook.type%8); - - // set hook.id to the highest id + 1 - hook.id = nextid++; - - // Special cases for some hook types (see the comments above mobjthinkerhooks declaration) - switch(hook.type) + else if (( type = hook_in_list(name, mobjHookNames) ) < Mobj_Hook(MAX)) { - case hook_MobjThinker: - lastp = &mobjthinkerhooks[hook.s.mt]; - break; - case hook_MobjCollide: - case hook_MobjLineCollide: - case hook_MobjMoveCollide: - lastp = &mobjcollidehooks[hook.s.mt]; - break; - case hook_MobjSpawn: - case hook_TouchSpecial: - case hook_MobjFuse: - case hook_BossThinker: - case hook_ShouldDamage: - case hook_MobjDamage: - case hook_MobjDeath: - case hook_BossDeath: - case hook_MobjRemoved: - case hook_MobjMoveBlocked: - case hook_MapThingSpawn: - case hook_FollowMobj: - lastp = &mobjhooks[hook.s.mt]; - break; - case hook_JumpSpecial: - case hook_AbilitySpecial: - case hook_SpinSpecial: - case hook_JumpSpinSpecial: - case hook_PlayerSpawn: - case hook_PlayerCanDamage: - case hook_TeamSwitch: - case hook_ViewpointSwitch: - case hook_SeenPlayer: - case hook_ShieldSpawn: - case hook_ShieldSpecial: - case hook_PlayerThink: - lastp = &playerhooks; - break; - case hook_LinedefExecute: - lastp = &linedefexecutorhooks; - break; - default: - lastp = &roothook; - break; + add_mobj_hook(L, type, nextid); + } + else if (( type = hook_in_list(name, hookNames) ) < Hook(MAX)) + { + new_hook_table(L, &hookRefs[type]); + add_hook(L, nextid); + } + else + { + return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name)); } - // iterate the hook metadata structs - // set lastp to the last hook struct's "next" pointer. - for (hookp = *lastp; hookp; hookp = hookp->next) - lastp = &hookp->next; - // allocate a permanent memory struct to stuff hook. - hookp = ZZ_Alloc(sizeof(struct hook_s)); - memcpy(hookp, &hook, sizeof(struct hook_s)); - // tack it onto the end of the linked list. - *lastp = hookp; + if (!(nextid & 7)) + { + Z_Realloc(hooksErrored, + BIT_ARRAY_LENGTH (nextid + 1) * sizeof *hooksErrored, + PU_STATIC, &hooksErrored); + hooksErrored[nextid >> 3] = 0; + } // set the hook function in the registry. - lua_pushfstring(L, FMT_HOOKID, hook.id); - lua_pushvalue(L, 1); - lua_settable(L, LUA_REGISTRYINDEX); + lua_getref(L, hookReg); + lua_pushvalue(L, 2);/* the function */ + lua_rawseti(L, -2, ++nextid); + return 0; } int LUA_HookLib(lua_State *L) { - memset(hooksAvailable,0,sizeof(UINT8[(hook_MAX/8)+1])); - roothook = NULL; + new_hook_table(L, &hookReg); lua_register(L, "addHook", lib_addHook); return 0; } -boolean LUAh_MobjHook(mobj_t *mo, enum hook which) +typedef struct Hook_State Hook_State; +typedef void (*Hook_Callback)(Hook_State *); + +struct Hook_State { + int status;/* return status to calling function */ + void * userdata; + int ref;/* ref for primary hook table */ + int hook_type;/* Hook or Hook(MAX) + Mobj_Hook */ + mobjtype_t mobj_type; + const char * string;/* used to fetch table, ran first if set */ + int top;/* index of last argument passed to hook */ + int id;/* id to fetch function from registry */ + int values;/* num arguments passed to hook */ + int results;/* num values returned by hook */ + Hook_Callback results_handler;/* callback when hook successfully returns */ +}; + +enum { + HINDEX = 1,/* hook registry */ + EINDEX = 2,/* error handler */ + SINDEX = 3,/* string itself is pushed in case of string hook */ +}; + +static void push_error_handler(void) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return false; - - I_Assert(mo->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type])) - return false; - - lua_settop(gL, 0); lua_pushcfunction(gL, LUA_GetErrorMessage); +} - // Look for all generic mobj hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) +/* repush hook string */ +static void push_string(void) +{ + lua_pushvalue(gL, SINDEX); +} + +static boolean start_hook_stack(void) +{ + lua_settop(gL, 0); + lua_getref(gL, hookReg); + push_error_handler(); + return true; +} + +static boolean init_hook_type +( + Hook_State * hook, + int status, + int hook_type, + mobjtype_t mobj_type, + const char * string, + int ref +){ + boolean ready; + + hook->status = status; + + if (mobj_type > 0) + ready = mobj_hook_available(hook_type, mobj_type); + else + ready = ref > 0; + + if (ready) { - if (hookp->type != which) - continue; + hook->ref = ref; + hook->hook_type = hook_type; + hook->mobj_type = mobj_type; + hook->string = string; + return start_hook_stack(); + } + else + return false; +} - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; +static boolean prepare_hook +( + Hook_State * hook, + int default_status, + int hook_type +){ + return init_hook_type(hook, default_status, + hook_type, 0, NULL, + hookRefs[hook_type]); +} + +static boolean prepare_mobj_hook +( + Hook_State * hook, + int default_status, + int hook_type, + mobjtype_t mobj_type +){ + return init_hook_type(hook, default_status, + hook_type, mobj_type, NULL, + mobjHookRefs[mobj_type][hook_type]); +} + +static boolean prepare_string_hook +( + Hook_State * hook, + int default_status, + int hook_type, + const char * string +){ + if (init_hook_type(hook, default_status, + hook_type, 0, string, + stringHooks[hook_type].ref)) + { + lua_pushstring(gL, string); + return true; + } + else + return false; +} + +static void init_hook_call +( + Hook_State * hook, + int values, + int results, + Hook_Callback results_handler +){ + hook->top = lua_gettop(gL); + hook->values = values; + hook->results = results; + hook->results_handler = results_handler; +} + +static void get_hook_table(Hook_State *hook) +{ + lua_getref(gL, hook->ref); +} + +static void get_hook(Hook_State *hook, int n) +{ + lua_rawgeti(gL, -1, n); + hook->id = lua_tonumber(gL, -1) - 1; + lua_rawget(gL, HINDEX); +} + +static int call_single_hook_no_copy(Hook_State *hook) +{ + if (lua_pcall(gL, hook->values, hook->results, EINDEX) == 0) + { + if (hook->results > 0) + { + (*hook->results_handler)(hook); + lua_pop(gL, hook->results); + } + } + else + { + /* print the error message once */ + if (cv_debug & DBG_LUA || !in_bit_array(hooksErrored, hook->id)) + { + CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(gL, -1)); + set_bit_array(hooksErrored, hook->id); } - if (lua_toboolean(gL, -1)) - hooked = true; lua_pop(gL, 1); } - for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; + return 1; +} - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } +static int call_single_hook(Hook_State *hook) +{ + int i; + + for (i = -(hook->values) + 1; i <= 0; ++i) + lua_pushvalue(gL, hook->top + i); + + return call_single_hook_no_copy(hook); +} + +static int call_hook_table_for(Hook_State *hook, int n) +{ + int k; + + for (k = 1; k <= n; ++k) + { + get_hook(hook, k); + call_single_hook(hook); + } + + return n; +} + +static int call_hook_table(Hook_State *hook) +{ + return call_hook_table_for(hook, lua_objlen(gL, -1)); +} + +static int call_ref(Hook_State *hook, int ref) +{ + int calls; + + if (ref > 0) + { + lua_getref(gL, ref); + calls = call_hook_table(hook); + + return calls; + } + else + return 0; +} + +static int call_string_hooks(Hook_State *hook) +{ + const int numGeneric = stringHooks[hook->hook_type].numGeneric; + + int calls = 0; + + get_hook_table(hook); + + /* call generic string hooks first */ + calls += call_hook_table_for(hook, numGeneric); + + push_string(); + lua_rawget(gL, -2); + calls += call_hook_table(hook); + + return calls; +} + +static int call_generic_mobj_hooks(Hook_State *hook) +{ + const int ref = mobjHookRefs[MT_NULL][hook->hook_type]; + return call_ref(hook, ref); +} + +static int call_hooks +( + Hook_State * hook, + int values, + int results, + Hook_Callback results_handler +){ + int calls = 0; + + init_hook_call(hook, values, results, results_handler); + + if (hook->string) + { + calls += call_string_hooks(hook); + } + else + { + if (hook->mobj_type > 0) + calls += call_generic_mobj_hooks(hook); + + calls += call_ref(hook, hook->ref); + + if (hook->mobj_type > 0) + ps_lua_mobjhooks += calls; + } + + lua_settop(gL, 0); + + return calls; +} + +/* ========================================================================= + COMMON RESULT HANDLERS + ========================================================================= */ + +#define res_none NULL + +static void res_true(Hook_State *hook) +{ + if (lua_toboolean(gL, -1)) + hook->status = true; +} + +static void res_false(Hook_State *hook) +{ + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + hook->status = false; +} + +static void res_force(Hook_State *hook) +{ + if (!lua_isnil(gL, -1)) + { if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + hook->status = 1; // Force yes + else + hook->status = 2; // Force no } - - lua_settop(gL, 0); - return hooked; } -boolean LUAh_PlayerHook(player_t *plr, enum hook which) +/* ========================================================================= + GENERALISED HOOKS + ========================================================================= */ + +int LUA_HookMobj(mobj_t *mobj, int hook_type) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, false, hook_type, mobj->type)) { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, plr, META_PLAYER); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, mobj, META_MOBJ); + call_hooks(&hook, 1, 1, res_true); } - - lua_settop(gL, 0); - return hooked; + return hook.status; } -// Hook for map change (before load) -void LUAh_MapChange(INT16 mapnumber) +int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_MapChange/8] & (1<<(hook_MapChange%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - lua_pushinteger(gL, mapnumber); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, hook_type, t1->type)) { - if (hookp->type != hook_MapChange) - continue; - - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + LUA_PushUserdata(gL, t1, META_MOBJ); + LUA_PushUserdata(gL, t2, META_MOBJ); + call_hooks(&hook, 2, 1, res_force); } - - lua_settop(gL, 0); + return hook.status; } -// Hook for map load -void LUAh_MapLoad(void) +void LUA_Hook(int type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_MapLoad/8] & (1<<(hook_MapLoad%8)))) - return; + Hook_State hook; + if (prepare_hook(&hook, 0, type)) + call_hooks(&hook, 0, 0, res_none); +} - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - lua_pushinteger(gL, gamemap); - - for (hookp = roothook; hookp; hookp = hookp->next) +void LUA_HookInt(INT32 number, int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, hook_type)) { - if (hookp->type != hook_MapLoad) - continue; - - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + lua_pushinteger(gL, number); + call_hooks(&hook, 1, 0, res_none); } - - lua_settop(gL, 0); } -// Hook for Got_AddPlayer -void LUAh_PlayerJoin(int playernum) +int LUA_HookPlayer(player_t *player, int hook_type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PlayerJoin/8] & (1<<(hook_PlayerJoin%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - lua_pushinteger(gL, playernum); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, false, hook_type)) { - if (hookp->type != hook_PlayerJoin) - continue; - - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, 1, res_true); } - - lua_settop(gL, 0); + return hook.status; } -// Hook for frame (before mobj and player thinkers) -void LUAh_PreThinkFrame(void) +int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PreThinkFrame/8] & (1<<(hook_PreThinkFrame%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, false, hook_type)) { - if (hookp->type != hook_PreThinkFrame) - continue; + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, cmd, META_TICCMD); - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } + if (hook_type == Hook(PlayerCmd)) + hook_cmd_running = true; + + call_hooks(&hook, 2, 1, res_true); + + if (hook_type == Hook(PlayerCmd)) + hook_cmd_running = false; } - - lua_pop(gL, 1); // Pop error handler + return hook.status; } -// Hook for frame (after mobj and player thinkers) -void LUAh_ThinkFrame(void) +/* ========================================================================= + SPECIALIZED HOOKS + ========================================================================= */ + +void LUA_HookThinkFrame(void) { - hook_p hookp; // variables used by perf stats int hook_index = 0; int time_taken = 0; - if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8)))) - return; - lua_pushcfunction(gL, LUA_GetErrorMessage); + Hook_State hook; - for (hookp = roothook; hookp; hookp = hookp->next) + int n; + int k; + + if (prepare_hook(&hook, 0, Hook(ThinkFrame))) { - if (hookp->type != hook_ThinkFrame) - continue; + init_hook_call(&hook, 0, 0, res_none); - if (cv_perfstats.value == 3) - time_taken = I_GetTimeMicros(); - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - if (cv_perfstats.value == 3) + get_hook_table(&hook); + n = lua_objlen(gL, -1); + + for (k = 1; k <= n; ++k) { - lua_Debug ar; - time_taken = I_GetTimeMicros() - time_taken; - // we need the function, let's just retrieve it again - PushHook(gL, hookp); - lua_getinfo(gL, ">S", &ar); - PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); - hook_index++; - } - } + get_hook(&hook, k); - lua_pop(gL, 1); // Pop error handler -} - -// Hook for frame (at end of tick, ie after overlays, precipitation, specials) -void LUAh_PostThinkFrame(void) -{ - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PostThinkFrame/8] & (1<<(hook_PostThinkFrame%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PostThinkFrame) - continue; - - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - } - - lua_pop(gL, 1); // Pop error handler -} - -// Hook for mobj collisions -UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) -{ - hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return 0; - - I_Assert(thing1->type < NUMMOBJTYPES); - - if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing1->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj collision hooks - for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldCollide; -} - -UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which) -{ - hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return 0; - - I_Assert(thing->type < NUMMOBJTYPES); - - if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj collision hooks - for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing, META_MOBJ); - LUA_PushUserdata(gL, line, META_LINE); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjcollidehooks[thing->type]; hookp; hookp = hookp->next) - { - if (hookp->type != which) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, thing, META_MOBJ); - LUA_PushUserdata(gL, line, META_LINE); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldCollide; -} - -// Hook for mobj thinkers -boolean LUAh_MobjThinker(mobj_t *mo) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8)))) - return false; - - I_Assert(mo->type < NUMMOBJTYPES); - - if (!(mobjthinkerhooks[MT_NULL] || mobjthinkerhooks[mo->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj thinker hooks - for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next) - { - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next) - { - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - LUA_PushUserdata(gL, mo, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_TouchSpecialThing by mobj type -boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8)))) - return false; - - I_Assert(special->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[special->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic touch special hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_TouchSpecial) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[special->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_TouchSpecial) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_DamageMobj by mobj type (Should mobj take damage?) -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8)))) - return 0; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic should damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_ShouldDamage) - continue; - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} - -// Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8)))) - return false; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_KillMobj by mobj type -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8)))) - return false; - - I_Assert(target->type < NUMMOBJTYPES); - - if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj death hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDeath) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MobjDeath) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_BuildTiccmd -boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotTiccmd) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, bot, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_BuildTailsTiccmd by skin name -boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotAI - || (hookp->s.str && strcmp(hookp->s.str, ((skin_t*)tails->skin)->name))) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, sonic, META_MOBJ); - LUA_PushUserdata(gL, tails, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 8, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - - // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. - if (lua_istable(gL, 2+1)) { - boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false; -#define CHECKFIELD(field) \ - lua_getfield(gL, 2+1, #field);\ - if (lua_toboolean(gL, -1))\ - field = true;\ - lua_pop(gL, 1); - - CHECKFIELD(forward) - CHECKFIELD(backward) - CHECKFIELD(left) - CHECKFIELD(right) - CHECKFIELD(strafeleft) - CHECKFIELD(straferight) - CHECKFIELD(jump) - CHECKFIELD(spin) -#undef CHECKFIELD - B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin); - } else - B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8)); - - lua_pop(gL, 8); - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_CheckRespawn -boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails) -{ - hook_p hookp; - UINT8 shouldRespawn = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_BotRespawn/8] & (1<<(hook_BotRespawn%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_BotRespawn) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, sonic, META_MOBJ); - LUA_PushUserdata(gL, tails, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldRespawn = 1; // Force yes - else - shouldRespawn = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldRespawn; -} - -// Hook for linedef executors -boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) - { - if (strcmp(hookp->s.str, line->stringargs[0])) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, line, META_LINE); - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, sector, META_SECTOR); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -} - - -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_PlayerMsg) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player - if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c - lua_pushinteger(gL, 3); // type - lua_pushnil(gL); // target - } else if (target == -1) { // sayteam - lua_pushinteger(gL, 1); // type - lua_pushnil(gL); // target - } else if (target == 0) { // say - lua_pushinteger(gL, 0); // type - lua_pushnil(gL); // target - } else { // sayto - lua_pushinteger(gL, 2); // type - LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target + if (cv_perfstats.value == 3) + { + lua_pushvalue(gL, -1);/* need the function again */ + time_taken = I_GetTimeMicros(); } - lua_pushstring(gL, msg); // msg - } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - lua_settop(gL, 0); - return hooked; + call_single_hook(&hook); + + if (cv_perfstats.value == 3) + { + lua_Debug ar; + time_taken = I_GetTimeMicros() - time_taken; + lua_getinfo(gL, ">S", &ar); + PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + hook_index++; + } + } + + lua_settop(gL, 0); + } } - -// Hook for hurt messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) +int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8)))) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, Mobj_Hook(MobjLineCollide), mobj->type)) { - if (hookp->type != hook_HurtMsg - || (hookp->s.mt && !(inflictor && hookp->s.mt == inflictor->type))) - continue; + LUA_PushUserdata(gL, mobj, META_MOBJ); + LUA_PushUserdata(gL, line, META_LINE); + call_hooks(&hook, 2, 1, res_force); + } + return hook.status; +} - if (lua_gettop(gL) == 1) +int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) +{ + Hook_State hook; + if (prepare_mobj_hook(&hook, false, Mobj_Hook(TouchSpecial), special->type)) + { + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); + call_hooks(&hook, 2, 1, res_true); + } + return hook.status; +} + +static int damage_hook +( + mobj_t *target, + mobj_t *inflictor, + mobj_t *source, + INT32 damage, + UINT8 damagetype, + int hook_type, + int values, + Hook_Callback results_handler +){ + Hook_State hook; + if (prepare_mobj_hook(&hook, 0, hook_type, target->type)) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + if (values == 5) + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + call_hooks(&hook, values, 1, results_handler); + } + return hook.status; +} + +int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +{ + return damage_hook(target, inflictor, source, damage, damagetype, + Mobj_Hook(ShouldDamage), 5, res_force); +} + +int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +{ + return damage_hook(target, inflictor, source, damage, damagetype, + Mobj_Hook(MobjDamage), 5, res_true); +} + +int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) +{ + return damage_hook(target, inflictor, source, 0, damagetype, + Mobj_Hook(MobjDeath), 4, res_true); +} + +typedef struct { + mobj_t * tails; + ticcmd_t * cmd; +} BotAI_State; + +static boolean checkbotkey(const char *field) +{ + return lua_toboolean(gL, -1) && strcmp(lua_tostring(gL, -2), field) == 0; +} + +static void res_botai(Hook_State *hook) +{ + BotAI_State *botai = hook->userdata; + + int k[8]; + + int fields = 0; + + // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. + if (lua_istable(gL, -8)) { + lua_pushnil(gL); // key + while (lua_next(gL, -9)) { +#define check(n, f) (checkbotkey(f) ? (k[(n)-1] = 1) : 0) + if ( + check(1, "forward") || check(2, "backward") || + check(3, "left") || check(4, "right") || + check(5, "strafeleft") || check(6, "straferight") || + check(7, "jump") || check(8, "spin") + ){ + if (8 <= ++fields) + { + lua_pop(gL, 2); // pop key and value + break; + } + } + + lua_pop(gL, 1); // pop value +#undef check + } + } else { + while (fields < 8) { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); + k[fields] = lua_toboolean(gL, -8 + fields); + fields++; } - PushHook(gL, hookp); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); } - lua_settop(gL, 0); - return hooked; + B_KeysToTiccmd(botai->tails, botai->cmd, + k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]); + + hook->status = true; } -void LUAh_NetArchiveHook(lua_CFunction archFunc) +int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) { - hook_p hookp; - int errorhandlerindex; - if (!gL || !(hooksAvailable[hook_NetVars/8] & (1<<(hook_NetVars%8)))) - return; + const char *skin = ((skin_t *)tails->skin)->name; - // stack: tables - I_Assert(lua_gettop(gL) > 0); - I_Assert(lua_istable(gL, -1)); + Hook_State hook; + BotAI_State botai; - lua_pushcfunction(gL, LUA_GetErrorMessage); - errorhandlerindex = lua_gettop(gL); - - // tables becomes an upvalue of archFunc - lua_pushvalue(gL, -2); - lua_pushcclosure(gL, archFunc, 1); - // stack: tables, archFunc - - for (hookp = roothook; hookp; hookp = hookp->next) + if (prepare_string_hook(&hook, false, String_Hook(BotAI), skin)) { - if (hookp->type != hook_NetVars) - continue; + LUA_PushUserdata(gL, sonic, META_MOBJ); + LUA_PushUserdata(gL, tails, META_MOBJ); - PushHook(gL, hookp); - lua_pushvalue(gL, -2); // archFunc - if (lua_pcall(gL, 1, 0, errorhandlerindex)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + botai.tails = tails; + botai.cmd = cmd; + + hook.userdata = &botai; + + call_hooks(&hook, 2, 8, res_botai); } - lua_pop(gL, 2); // Pop archFunc and error handler - // stack: tables + return hook.status; } -boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing) +void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8)))) - return false; - - if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type])) - return false; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj map thing spawn hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_string_hook + (&hook, 0, String_Hook(LinedefExecute), line->stringargs[0])) { - if (hookp->type != hook_MapThingSpawn) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, mthing, META_MAPTHING); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, line, META_LINE); + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, sector, META_SECTOR); + ps_lua_mobjhooks += call_hooks(&hook, 3, 0, res_none); } - - for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_MapThingSpawn) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, mthing, META_MAPTHING); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; } -// Hook for P_PlayerAfterThink Smiles mobj-following -boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj) +int LUA_HookPlayerMsg(int source, int target, int flags, char *msg) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8)))) - return 0; - - if (!(mobjhooks[MT_NULL] || mobjhooks[mobj->type])) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - // Look for all generic mobj follow item hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, false, Hook(PlayerMsg))) { - if (hookp->type != hook_FollowMobj) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, mobj, META_MOBJ); + LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player + if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c + lua_pushinteger(gL, 3); // type + lua_pushnil(gL); // target + } else if (target == -1) { // sayteam + lua_pushinteger(gL, 1); // type + lua_pushnil(gL); // target + } else if (target == 0) { // say + lua_pushinteger(gL, 0); // type + lua_pushnil(gL); // target + } else { // sayto + lua_pushinteger(gL, 2); // type + LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + lua_pushstring(gL, msg); // msg + call_hooks(&hook, 4, 1, res_true); } - - for (hookp = mobjhooks[mobj->type]; hookp; hookp = hookp->next) - { - if (hookp->type != hook_FollowMobj) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, mobj, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; + return hook.status; } -// Hook for P_PlayerCanDamage -UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj) +int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { - hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_PlayerCanDamage/8] & (1<<(hook_PlayerCanDamage%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, false, Hook(HurtMsg))) { - if (hookp->type != hook_PlayerCanDamage) - continue; - - ps_lua_mobjhooks++; - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, mobj, META_MOBJ); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); + call_hooks(&hook, 4, 1, res_true); } - - lua_settop(gL, 0); - return shouldCollide; + return hook.status; } -void LUAh_PlayerQuit(player_t *plr, kickreason_t reason) +void LUA_HookNetArchive(lua_CFunction archFunc) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) - return; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + const int ref = hookRefs[Hook(NetVars)]; + Hook_State hook; + /* this is a remarkable case where the stack isn't reset */ + if (ref > 0) { - if (hookp->type != hook_PlayerQuit) - continue; + // stack: tables + I_Assert(lua_gettop(gL) > 0); + I_Assert(lua_istable(gL, -1)); - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit - lua_pushinteger(gL, reason); // Reason for quitting - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 0, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - } + push_error_handler(); + lua_getref(gL, hookReg); + + lua_insert(gL, HINDEX); + lua_insert(gL, EINDEX); + + // tables becomes an upvalue of archFunc + lua_pushvalue(gL, -1); + lua_pushcclosure(gL, archFunc, 1); + // stack: tables, archFunc + + init_hook_call(&hook, 1, 0, res_none); + call_ref(&hook, ref); + + lua_pop(gL, 2); // pop hook table and archFunc + lua_remove(gL, EINDEX); // pop error handler + lua_remove(gL, HINDEX); // pop hook registry + // stack: tables } - - lua_settop(gL, 0); } -// Hook for Y_Ticker -void LUAh_IntermissionThinker(void) +int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing) { - hook_p hookp; - if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, false, Mobj_Hook(MapThingSpawn), mobj->type)) { - if (hookp->type != hook_IntermissionThinker) - continue; - - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } + LUA_PushUserdata(gL, mobj, META_MOBJ); + LUA_PushUserdata(gL, mthing, META_MAPTHING); + call_hooks(&hook, 2, 1, res_true); } - - lua_pop(gL, 1); // Pop error handler + return hook.status; } -// Hook for team switching -// It's just an edit of LUAh_ViewpointSwitch. -boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) +int LUA_HookFollowMobj(player_t *player, mobj_t *mobj) { - hook_p hookp; - boolean canSwitchTeam = true; - if (!gL || !(hooksAvailable[hook_TeamSwitch/8] & (1<<(hook_TeamSwitch%8)))) - return true; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_mobj_hook(&hook, false, Mobj_Hook(FollowMobj), mobj->type)) { - if (hookp->type != hook_TeamSwitch) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - lua_pushinteger(gL, newteam); - lua_pushboolean(gL, fromspectators); - lua_pushboolean(gL, tryingautobalance); - lua_pushboolean(gL, tryingscramble); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) - canSwitchTeam = false; // Can't switch team - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + call_hooks(&hook, 2, 1, res_true); } - - lua_settop(gL, 0); - return canSwitchTeam; + return hook.status; } -// Hook for spy mode -UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) +int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj) { - hook_p hookp; - UINT8 canSwitchView = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ViewpointSwitch/8] & (1<<(hook_ViewpointSwitch%8)))) - return 0; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hud_running = true; // local hook - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, 0, Hook(PlayerCanDamage))) { - if (hookp->type != hook_ViewpointSwitch) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); - lua_pushboolean(gL, forced); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave canSwitchView = 0. - if (lua_toboolean(gL, -1)) - canSwitchView = 1; // Force viewpoint switch - else - canSwitchView = 2; // Skip viewpoint switch - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + call_hooks(&hook, 2, 1, res_force); } - - lua_settop(gL, 0); - - hud_running = false; - - return canSwitchView; + return hook.status; +} + +void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, Hook(PlayerQuit))) + { + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + call_hooks(&hook, 2, 0, res_none); + } +} + +int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) +{ + Hook_State hook; + if (prepare_hook(&hook, true, Hook(TeamSwitch))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushinteger(gL, newteam); + lua_pushboolean(gL, fromspectators); + lua_pushboolean(gL, tryingautobalance); + lua_pushboolean(gL, tryingscramble); + call_hooks(&hook, 5, 1, res_false); + } + return hook.status; +} + +int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, Hook(ViewpointSwitch))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); + lua_pushboolean(gL, forced); + + hud_running = true; // local hook + call_hooks(&hook, 3, 1, res_force); + hud_running = false; + } + return hook.status; } -// Hook for MT_NAMECHECK #ifdef SEENAMES -boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) +int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend) { - hook_p hookp; - boolean hasSeenPlayer = true; - if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8)))) - return true; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hud_running = true; // local hook - - for (hookp = playerhooks; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_hook(&hook, true, Hook(SeenPlayer))) { - if (hookp->type != hook_SeenPlayer) - continue; + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, seenfriend, META_PLAYER); - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, seenfriend, META_PLAYER); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) - hasSeenPlayer = false; // Hasn't seen player - lua_pop(gL, 1); + hud_running = true; // local hook + call_hooks(&hook, 2, 1, res_false); + hud_running = false; } - - lua_settop(gL, 0); - - hud_running = false; - - return hasSeenPlayer; + return hook.status; } #endif // SEENAMES -boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname) +int LUA_HookShouldJingleContinue(player_t *player, const char *musname) { - hook_p hookp; - boolean keepplaying = false; - if (!gL || !(hooksAvailable[hook_ShouldJingleContinue/8] & (1<<(hook_ShouldJingleContinue%8)))) - return true; - - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hud_running = true; // local hook - - for (hookp = roothook; hookp; hookp = hookp->next) + Hook_State hook; + if (prepare_string_hook + (&hook, false, String_Hook(ShouldJingleContinue), musname)) { - if (hookp->type != hook_ShouldJingleContinue - || (hookp->s.str && strcmp(hookp->s.str, musname))) - continue; + LUA_PushUserdata(gL, player, META_PLAYER); + push_string(); - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - lua_pushstring(gL, musname); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1) && lua_toboolean(gL, -1)) - keepplaying = true; // Keep playing this boolean - lua_pop(gL, 1); + hud_running = true; // local hook + call_hooks(&hook, 2, 1, res_true); + hud_running = false; } - - lua_settop(gL, 0); - - hud_running = false; - - return keepplaying; + return hook.status; } -// Hook for game quitting -void LUAh_GameQuit(void) -{ - hook_p hookp; - if (!gL || !(hooksAvailable[hook_GameQuit/8] & (1<<(hook_GameQuit%8)))) - return; - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - for (hookp = roothook; hookp; hookp = hookp->next) - { - if (hookp->type != hook_GameQuit) - continue; - - PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } - } - - lua_pop(gL, 1); // Pop error handler -} - -// Hook for building player's ticcmd struct (Ported from SRB2Kart) boolean hook_cmd_running = false; -boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd) + +static void update_music_name(struct MusicChange *musicchange) { - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerCmd/8] & (1<<(hook_PlayerCmd%8)))) - return false; + size_t length; + const char * new = lua_tolstring(gL, -6, &length); - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); - - hook_cmd_running = true; - for (hookp = roothook; hookp; hookp = hookp->next) + if (length < 7) { - if (hookp->type != hook_PlayerCmd) - continue; - - if (lua_gettop(gL) == 1) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - PushHook(gL, hookp); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 1)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + strcpy(musicchange->newname, new); + lua_pushvalue(gL, -6);/* may as well keep it for next call */ + } + else + { + memcpy(musicchange->newname, new, 6); + musicchange->newname[6] = '\0'; + lua_pushlstring(gL, new, 6); } - lua_settop(gL, 0); - hook_cmd_running = false; - return hooked; + lua_replace(gL, -7); } -// Hook for music changes -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, - UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms) +static void res_musicchange(Hook_State *hook) { - hook_p hookp; - boolean hooked = false; + struct MusicChange *musicchange = hook->userdata; - if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8)))) - return false; + // output 1: true, false, or string musicname override + if (lua_isstring(gL, -6)) + update_music_name(musicchange); + else if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) + hook->status = true; - lua_settop(gL, 0); - lua_pushcfunction(gL, LUA_GetErrorMessage); + // output 2: mflags override + if (lua_isnumber(gL, -5)) + *musicchange->mflags = lua_tonumber(gL, -5); + // output 3: looping override + if (lua_isboolean(gL, -4)) + *musicchange->looping = lua_toboolean(gL, -4); + // output 4: position override + if (lua_isboolean(gL, -3)) + *musicchange->position = lua_tonumber(gL, -3); + // output 5: prefadems override + if (lua_isboolean(gL, -2)) + *musicchange->prefadems = lua_tonumber(gL, -2); + // output 6: fadeinms override + if (lua_isboolean(gL, -1)) + *musicchange->fadeinms = lua_tonumber(gL, -1); +} - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MusicChange) - { - PushHook(gL, hookp); - lua_pushstring(gL, oldname); - lua_pushstring(gL, newname); - lua_pushinteger(gL, *mflags); - lua_pushboolean(gL, *looping); - lua_pushinteger(gL, *position); - lua_pushinteger(gL, *prefadems); - lua_pushinteger(gL, *fadeinms); - if (lua_pcall(gL, 7, 6, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); - lua_pop(gL, 1); - continue; - } +int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) +{ + Hook_State hook; + if (prepare_hook(&hook, false, Hook(MusicChange))) + { + int n; + int k; - // output 1: true, false, or string musicname override - if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) - hooked = true; - else if (lua_isstring(gL, -6)) - strncpy(newname, lua_tostring(gL, -6), 7); - // output 2: mflags override - if (lua_isnumber(gL, -5)) - *mflags = lua_tonumber(gL, -5); - // output 3: looping override - if (lua_isboolean(gL, -4)) - *looping = lua_toboolean(gL, -4); - // output 4: position override - if (lua_isboolean(gL, -3)) - *position = lua_tonumber(gL, -3); - // output 5: prefadems override - if (lua_isboolean(gL, -2)) - *prefadems = lua_tonumber(gL, -2); - // output 6: fadeinms override - if (lua_isboolean(gL, -1)) - *fadeinms = lua_tonumber(gL, -1); + init_hook_call(&hook, 7, 6, res_musicchange); + hook.userdata = param; - lua_pop(gL, 7); // Pop returned values and error handler + lua_pushstring(gL, oldname);/* the only constant value */ + lua_pushstring(gL, param->newname);/* semi constant */ + + get_hook_table(&hook); + n = lua_objlen(gL, -1); + + for (k = 1; k <= n; ++k) { + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + lua_pushinteger(gL, *param->mflags); + lua_pushboolean(gL, *param->looping); + lua_pushinteger(gL, *param->position); + lua_pushinteger(gL, *param->prefadems); + lua_pushinteger(gL, *param->fadeinms); + + call_single_hook_no_copy(&hook); } - lua_settop(gL, 0); - newname[6] = 0; - return hooked; -} \ No newline at end of file + lua_settop(gL, 0); + } + return hook.status; +} diff --git a/src/lua_script.c b/src/lua_script.c index eb4737f76..a649942b8 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1628,7 +1628,7 @@ void LUA_Archive(void) WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. - LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode + LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode ArchiveTables(); if (gL) @@ -1663,7 +1663,7 @@ void LUA_UnArchive(void) } } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. - LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode + LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode UnArchiveTables(); if (gL) diff --git a/src/lua_script.h b/src/lua_script.h index 79ba0bb38..e9104f3d5 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -61,7 +61,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(const char *name); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, const char *def, const char *const lst[]); -void LUAh_NetArchiveHook(lua_CFunction archFunc); +void LUA_HookNetArchive(lua_CFunction archFunc); // Console wrapper void COM_Lua_f(void); diff --git a/src/m_menu.c b/src/m_menu.c index 77648f877..a9333e36e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6938,7 +6938,7 @@ static void M_UltimateCheat(INT32 choice) { (void)choice; if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); I_Quit(); } @@ -13373,7 +13373,7 @@ void M_QuitResponse(INT32 ch) if (ch != 'y' && ch != KEY_ENTER) return; if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); if (!(netgame || cv_debug)) { S_ResetCaptions(); diff --git a/src/p_enemy.c b/src/p_enemy.c index 22de9bc67..103441701 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3957,7 +3957,7 @@ void A_BossDeath(mobj_t *mo) } bossjustdie: - if (LUAh_BossDeath(mo)) + if (LUA_HookMobj(mo, Mobj_Hook(BossDeath))) return; else if (P_MobjWasRemoved(mo)) return; diff --git a/src/p_inter.c b/src/p_inter.c index 415c679e4..2d5f2736a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -365,7 +365,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->flags & (MF_ENEMY|MF_BOSS) && special->flags2 & MF2_FRET) return; - if (LUAh_TouchSpecial(special, toucher) || P_MobjWasRemoved(special)) + if (LUA_HookTouchSpecial(special, toucher) || P_MobjWasRemoved(special)) return; // 0 = none, 1 = elemental pierce, 2 = bubble bounce @@ -1935,7 +1935,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour if (!netgame) return; // Presumably it's obvious what's happening in splitscreen. - if (LUAh_HurtMsg(player, inflictor, source, damagetype)) + if (LUA_HookHurtMsg(player, inflictor, source, damagetype)) return; deadtarget = (player->mo->health <= 0); @@ -2409,7 +2409,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL); target->health = 0; // This makes it easy to check if something's dead elsewhere. - if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target)) return; // Let EVERYONE know what happened to a player! 01-29-2002 Tails @@ -3544,7 +3544,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Everything above here can't be forced. if (!metalrecording) { - UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage, damagetype); + UINT8 shouldForce = LUA_HookShouldDamage(target, inflictor, source, damage, damagetype); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed if (shouldForce == 1) @@ -3585,7 +3585,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force && target->flags2 & MF2_FRET) // Currently flashing from being hit return false; - if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) + if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) return true; if (target->health > 1) @@ -3635,7 +3635,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da || (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam))) return false; // Don't run eachother over in special stages and team games and such } - if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) + if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) return true; P_NiGHTSDamage(target, source); // -5s :( return true; @@ -3689,13 +3689,13 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (force || (inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE)) // Super Sonic is stunned! { - if (!LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) + if (!LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) P_SuperDamage(player, inflictor, source, damage); return true; } return false; } - else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) + else if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) return true; else if (player->powers[pw_shield] || (player->bot && !ultimatemode)) //If One-Hit Shield { diff --git a/src/p_map.c b/src/p_map.c index 922c0d9ec..8c548ed3c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -747,7 +747,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // underneath // REX HAS SEEN YOU - if (!LUAh_SeenPlayer(tmthing->target->player, thing->player)) + if (!LUA_HookSeenPlayer(tmthing->target->player, thing->player)) return false; seenplayer = thing->player; @@ -937,7 +937,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } { - UINT8 shouldCollide = LUAh_MobjCollide(thing, tmthing); // checks hook for thing's type + UINT8 shouldCollide = LUA_Hook2Mobj(thing, tmthing, Mobj_Hook(MobjCollide)); // checks hook for thing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -945,7 +945,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (shouldCollide == 2) return true; // force no collide - shouldCollide = LUAh_MobjMoveCollide(tmthing, thing); // checks hook for tmthing's type + shouldCollide = LUA_Hook2Mobj(tmthing, thing, Mobj_Hook(MobjMoveCollide)); // checks hook for tmthing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -1927,7 +1927,7 @@ static boolean PIT_CheckLine(line_t *ld) blockingline = ld; { - UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, blockingline); // checks hook for thing's type + UINT8 shouldCollide = LUA_HookMobjLineCollide(tmthing, blockingline); // checks hook for thing's type if (P_MobjWasRemoved(tmthing)) return true; // one of them was removed??? if (shouldCollide == 1) diff --git a/src/p_mobj.c b/src/p_mobj.c index 7ba6d1fad..5523fa273 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1844,7 +1844,7 @@ void P_XYMovement(mobj_t *mo) B_MoveBlocked(player); } - if (LUAh_MobjMoveBlocked(mo)) + if (LUA_HookMobj(mo, Mobj_Hook(MobjMoveBlocked))) { if (P_MobjWasRemoved(mo)) return; @@ -7513,7 +7513,7 @@ static void P_RosySceneryThink(mobj_t *mobj) static void P_MobjSceneryThink(mobj_t *mobj) { - if (LUAh_MobjThinker(mobj)) + if (LUA_HookMobj(mobj, Mobj_Hook(MobjThinker))) return; if (P_MobjWasRemoved(mobj)) return; @@ -7861,7 +7861,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) if (!mobj->fuse) { - if (!LUAh_MobjFuse(mobj)) + if (!LUA_HookMobj(mobj, Mobj_Hook(MobjFuse))) P_RemoveMobj(mobj); return; } @@ -7920,7 +7920,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) mobj->fuse--; if (!mobj->fuse) { - if (!LUAh_MobjFuse(mobj)) + if (!LUA_HookMobj(mobj, Mobj_Hook(MobjFuse))) P_RemoveMobj(mobj); return; } @@ -7949,7 +7949,7 @@ static boolean P_MobjPushableThink(mobj_t *mobj) static boolean P_MobjBossThink(mobj_t *mobj) { - if (LUAh_BossThinker(mobj)) + if (LUA_HookMobj(mobj, Mobj_Hook(BossThinker))) { if (P_MobjWasRemoved(mobj)) return false; @@ -9870,7 +9870,7 @@ static boolean P_FuseThink(mobj_t *mobj) if (mobj->fuse) return true; - if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj)) + if (LUA_HookMobj(mobj, Mobj_Hook(MobjFuse)) || P_MobjWasRemoved(mobj)) ; else if (mobj->info->flags & MF_MONITOR) { @@ -10046,13 +10046,13 @@ void P_MobjThinker(mobj_t *mobj) // Check for a Lua thinker first if (!mobj->player) { - if (LUAh_MobjThinker(mobj) || P_MobjWasRemoved(mobj)) + if (LUA_HookMobj(mobj, Mobj_Hook(MobjThinker)) || P_MobjWasRemoved(mobj)) return; } else if (!mobj->player->spectator) { // You cannot short-circuit the player thinker like you can other thinkers. - LUAh_MobjThinker(mobj); + LUA_HookMobj(mobj, Mobj_Hook(MobjThinker)); if (P_MobjWasRemoved(mobj)) return; } @@ -10523,7 +10523,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks! - if (LUAh_MobjSpawn(mobj)) + if (LUA_HookMobj(mobj, Mobj_Hook(MobjSpawn))) { if (P_MobjWasRemoved(mobj)) return NULL; @@ -10910,7 +10910,7 @@ void P_RemoveMobj(mobj_t *mobj) return; // something already removing this mobj. mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. - LUAh_MobjRemoved(mobj); + LUA_HookMobj(mobj, Mobj_Hook(MobjRemoved)); mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work. // Rings only, please! @@ -12556,7 +12556,7 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) { - boolean override = LUAh_MapThingSpawn(mobj, mthing); + boolean override = LUA_HookMapThingSpawn(mobj, mthing); if (P_MobjWasRemoved(mobj)) return false; diff --git a/src/p_setup.c b/src/p_setup.c index 918ffbd4e..01d43bd88 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -65,7 +65,7 @@ #include "md5.h" // map MD5 -// for LUAh_MapLoad +// for MapLoad hook #include "lua_script.h" #include "lua_hook.h" @@ -4271,7 +4271,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); } P_PreTicker(2); - LUAh_MapLoad(); + LUA_HookInt(gamemap, Hook(MapLoad)); } // No render mode or reloading gamestate, stop here. diff --git a/src/p_spec.c b/src/p_spec.c index a1afdd00d..59b9a0648 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -35,7 +35,7 @@ #include "v_video.h" // V_AUTOFADEOUT|V_ALLOWLOWERCASE #include "m_misc.h" #include "m_cond.h" //unlock triggers -#include "lua_hook.h" // LUAh_LinedefExecute +#include "lua_hook.h" // LUA_HookLinedefExecute #include "f_finale.h" // control text prompt #include "r_skins.h" // skins @@ -3135,7 +3135,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 443: // Calls a named Lua function if (line->stringargs[0]) - LUAh_LinedefExecute(line, mo, callsec); + LUA_HookLinedefExecute(line, mo, callsec); else CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in arg0str)\n", sizeu1(line-lines)); break; diff --git a/src/p_tick.c b/src/p_tick.c index da2a980c4..930223ab9 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -656,7 +656,7 @@ void P_Ticker(boolean run) ps_lua_mobjhooks = 0; ps_checkposition_calls = 0; - LUAh_PreThinkFrame(); + LUA_Hook(PreThinkFrame); ps_playerthink_time = I_GetTimeMicros(); for (i = 0; i < MAXPLAYERS; i++) @@ -687,7 +687,7 @@ void P_Ticker(boolean run) P_PlayerAfterThink(&players[i]); ps_lua_thinkframe_time = I_GetTimeMicros(); - LUAh_ThinkFrame(); + LUA_HookThinkFrame(); ps_lua_thinkframe_time = I_GetTimeMicros() - ps_lua_thinkframe_time; } @@ -760,7 +760,7 @@ void P_Ticker(boolean run) if (modeattacking) G_GhostTicker(); - LUAh_PostThinkFrame(); + LUA_Hook(PostThinkFrame); } P_MapEnd(); @@ -783,7 +783,7 @@ void P_PreTicker(INT32 frames) { P_MapStart(); - LUAh_PreThinkFrame(); + LUA_Hook(PreThinkFrame); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) @@ -810,7 +810,7 @@ void P_PreTicker(INT32 frames) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - LUAh_ThinkFrame(); + LUA_HookThinkFrame(); // Run shield positioning P_RunShields(); @@ -819,7 +819,7 @@ void P_PreTicker(INT32 frames) P_UpdateSpecials(); P_RespawnSpecials(); - LUAh_PostThinkFrame(); + LUA_Hook(PostThinkFrame); P_MapEnd(); } diff --git a/src/p_user.c b/src/p_user.c index c5f919c78..178a26126 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1111,7 +1111,7 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) return false; { - UINT8 shouldCollide = LUAh_PlayerCanDamage(player, thing); + UINT8 shouldCollide = LUA_HookPlayerCanDamage(player, thing); if (P_MobjWasRemoved(thing)) return false; // removed??? if (shouldCollide == 1) @@ -1594,7 +1594,7 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname) break; case JT_OTHER: // Other state - result = LUAh_ShouldJingleContinue(&players[i], musname); + result = LUA_HookShouldJingleContinue(&players[i], musname); break; case JT_NONE: // Null state @@ -1860,7 +1860,7 @@ void P_SpawnShieldOrb(player_t *player) I_Error("P_SpawnShieldOrb: player->mo is NULL!\n"); #endif - if (LUAh_ShieldSpawn(player)) + if (LUA_HookPlayer(player, Hook(ShieldSpawn))) return; if (player->powers[pw_shield] & SH_FORCE) @@ -4577,7 +4577,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_SPIN) { - if (LUAh_SpinSpecial(player)) + if (LUA_HookPlayer(player, Hook(SpinSpecial))) return; } @@ -5043,7 +5043,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects + if (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, Hook(ShieldSpecial))) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5167,7 +5167,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // and you don't have a shield, do it! P_DoSuperTransformation(player, false); } - else if (!LUAh_JumpSpinSpecial(player)) + else if (!LUA_HookPlayer(player, Hook(JumpSpinSpecial))) switch (player->charability) { case CA_THOK: @@ -5240,7 +5240,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_JUMP && !player->exiting && !P_PlayerInPain(player)) { - if (LUAh_JumpSpecial(player)) + if (LUA_HookPlayer(player, Hook(JumpSpecial))) ; // all situations below this require jump button not to be pressed already else if (player->pflags & PF_JUMPDOWN) @@ -5275,7 +5275,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) }*/ else if (player->pflags & PF_JUMPED) { - if (!LUAh_AbilitySpecial(player)) + if (!LUA_HookPlayer(player, Hook(AbilitySpecial))) switch (player->charability) { case CA_THOK: @@ -5468,7 +5468,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } else if (player->pflags & PF_THOKKED) { - if (!LUAh_AbilitySpecial(player)) + if (!LUA_HookPlayer(player, Hook(AbilitySpecial))) switch (player->charability) { case CA_FLY: @@ -10490,7 +10490,7 @@ boolean P_SpectatorJoinGame(player_t *player) else changeto = (P_RandomFixed() & 1) + 1; - if (!LUAh_TeamSwitch(player, changeto, true, false, false)) + if (!LUA_HookTeamSwitch(player, changeto, true, false, false)) return false; if (player->mo) @@ -10507,7 +10507,7 @@ boolean P_SpectatorJoinGame(player_t *player) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -10525,7 +10525,7 @@ boolean P_SpectatorJoinGame(player_t *player) // respawn in place and sit there for the rest of the round. if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE))) { - if (!LUAh_TeamSwitch(player, 3, true, false, false)) + if (!LUA_HookTeamSwitch(player, 3, true, false, false)) return false; if (player->mo) { @@ -10552,7 +10552,7 @@ boolean P_SpectatorJoinGame(player_t *player) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -11477,7 +11477,7 @@ void P_PlayerThink(player_t *player) } if (player->playerstate == PST_REBORN) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, Hook(PlayerThink)); return; } } @@ -11581,7 +11581,7 @@ void P_PlayerThink(player_t *player) if (player->playerstate == PST_DEAD) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, Hook(PlayerThink)); return; } } @@ -11702,7 +11702,7 @@ void P_PlayerThink(player_t *player) { player->mo->flags2 &= ~MF2_SHADOW; P_DeathThink(player); - LUAh_PlayerThink(player); + LUA_HookPlayer(player, Hook(PlayerThink)); return; } @@ -11744,7 +11744,7 @@ void P_PlayerThink(player_t *player) { if (P_SpectatorJoinGame(player)) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, Hook(PlayerThink)); return; // player->mo was removed. } } @@ -11849,7 +11849,7 @@ void P_PlayerThink(player_t *player) if (!player->mo) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, Hook(PlayerThink)); return; // P_MovePlayer removed player->mo. } @@ -12303,7 +12303,7 @@ void P_PlayerThink(player_t *player) } #undef dashmode - LUAh_PlayerThink(player); + LUA_HookPlayer(player, Hook(PlayerThink)); /* // Colormap verification @@ -12863,7 +12863,7 @@ void P_PlayerAfterThink(player_t *player) if (player->followmobj) { - if (LUAh_FollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) + if (LUA_HookFollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) {;} else { diff --git a/src/s_sound.c b/src/s_sound.c index 36bd454c1..106a5bd23 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2262,6 +2262,16 @@ static void S_ChangeMusicToQueue(void) void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms) { char newmusic[7]; + + struct MusicChange hook_param = { + newmusic, + &mflags, + &looping, + &position, + &prefadems, + &fadeinms + }; + boolean currentmidi = (I_SongType() == MU_MID || I_SongType() == MU_MID_EX); boolean midipref = cv_musicpref.value; @@ -2269,7 +2279,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 return; strncpy(newmusic, mmusic, 7); - if (LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) + if (LUA_HookMusicChange(music_name, &hook_param)) return; newmusic[6] = 0; diff --git a/src/s_sound.h b/src/s_sound.h index 4ac3c70bf..c872c2224 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -265,6 +265,16 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst); // Music Playback // +/* this is for the sake of the hook */ +struct MusicChange { + char * newname; + UINT16 * mflags; + boolean * looping; + UINT32 * position; + UINT32 * prefadems; + UINT32 * fadeinms; +}; + // Start music track, arbitrary, given its name, and set whether looping // note: music flags 12 bits for tracknum (gme, other formats with more than one track) // 13-15 aren't used yet diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index b8b3b9d34..8ca4f758a 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1058,7 +1058,7 @@ void I_GetEvent(void) break; case SDL_QUIT: if (Playing()) - LUAh_GameQuit(); + LUA_Hook(GameQuit); I_Quit(); break; } diff --git a/src/y_inter.c b/src/y_inter.c index 061cbb5e1..ae4dcdaf0 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -927,7 +927,7 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; - LUAh_IntermissionThinker(); + LUA_Hook(IntermissionThinker); intertic++; From 3f7c2ae0b0c450cb8993ffe7664ead05fd9f5000 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 10 Dec 2020 05:39:53 -0800 Subject: [PATCH 007/241] Avoid using multiple tables to fetch hook String hooks still use a table to fetch the id, but the id indexes a C array. Also I fixed a missing call in the MusicChange hook. --- src/lua_hooklib.c | 212 ++++++++++++++++++++++------------------------ 1 file changed, 101 insertions(+), 111 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 2d5ee44e4..02c427979 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -52,17 +52,24 @@ static inline int in_bit_array (const UINT8 *array, const int n) { return array[n >> 3] & (1 << (n & 7)); } +typedef struct { + int numHooks; + int *ids; +} hook_t; + typedef struct { int numGeneric; int ref; } stringhook_t; -static int hookRefs[Hook(MAX)]; -static int mobjHookRefs[NUMMOBJTYPES][Mobj_Hook(MAX)]; +static hook_t hookIds[Hook(MAX)]; +static hook_t mobjHookIds[NUMMOBJTYPES][Mobj_Hook(MAX)]; +// Lua tables are used to lookup string hook ids. static stringhook_t stringHooks[String_Hook(MAX)]; -static int hookReg; +// This will be indexed by hook id, the value of which fetches the registry. +static int * hookRefs; // After a hook errors once, don't print the error again. static UINT8 * hooksErrored; @@ -71,8 +78,8 @@ static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) { return ( - mobjHookRefs [MT_NULL] [hook_type] > 0 || - mobjHookRefs[mobj_type][hook_type] > 0 + mobjHookIds [MT_NULL] [hook_type].numHooks > 0 || + mobjHookIds[mobj_type][hook_type].numHooks > 0 ); } @@ -109,32 +116,10 @@ static void get_table(lua_State *L) lua_remove(L, -2); } -static void new_hook_table(lua_State *L, int *ref) +static void add_hook_to_table(lua_State *L, int id, int n) { - if (*ref > 0) - lua_getref(L, *ref); - else - { - lua_newtable(L); - lua_pushvalue(L, -1); - *ref = luaL_ref(L, LUA_REGISTRYINDEX); - } -} - -static void add_hook(lua_State *L, int id) -{ - lua_pushnumber(L, 1 + id); - lua_rawseti(L, -2, 1 + lua_objlen(L, -2)); -} - -static void add_mobj_hook(lua_State *L, int hook_type, int id) -{ - mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL); - - luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t"); - - new_hook_table(L, &mobjHookRefs[mobj_type][hook_type]); - add_hook(L, id); + lua_pushnumber(L, id); + lua_rawseti(L, -2, n); } static void add_string_hook(lua_State *L, int type, int id) @@ -160,19 +145,39 @@ static void add_string_hook(lua_State *L, int type, int id) break; } - new_hook_table(L, &hook->ref); + if (hook->ref > 0) + lua_getref(L, hook->ref); + else + { + lua_newtable(L); + lua_pushvalue(L, -1); + hook->ref = luaL_ref(L, LUA_REGISTRYINDEX); + } if (string) { lua_pushstring(L, string); get_table(L); - add_hook(L, id); + add_hook_to_table(L, id, 1 + lua_objlen(L, -1)); } else - { - lua_pushnumber(L, 1 + id); - lua_rawseti(L, -2, ++hook->numGeneric); - } + add_hook_to_table(L, id, ++hook->numGeneric); +} + +static void add_hook(hook_t *map, int id) +{ + Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids, + PU_STATIC, &map->ids); + map->ids[map->numHooks++] = id; +} + +static void add_mobj_hook(lua_State *L, int hook_type, int id) +{ + mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL); + + luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t"); + + add_hook(&mobjHookIds[mobj_type][hook_type], id); } // Takes hook, function, and additional arguments (mobj type to act on, etc.) @@ -200,8 +205,7 @@ static int lib_addHook(lua_State *L) } else if (( type = hook_in_list(name, hookNames) ) < Hook(MAX)) { - new_hook_table(L, &hookRefs[type]); - add_hook(L, nextid); + add_hook(&hookIds[type], nextid); } else { @@ -216,17 +220,17 @@ static int lib_addHook(lua_State *L) hooksErrored[nextid >> 3] = 0; } + Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs); + // set the hook function in the registry. - lua_getref(L, hookReg); lua_pushvalue(L, 2);/* the function */ - lua_rawseti(L, -2, ++nextid); + hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX); return 0; } int LUA_HookLib(lua_State *L) { - new_hook_table(L, &hookReg); lua_register(L, "addHook", lib_addHook); return 0; } @@ -237,21 +241,19 @@ typedef void (*Hook_Callback)(Hook_State *); struct Hook_State { int status;/* return status to calling function */ void * userdata; - int ref;/* ref for primary hook table */ - int hook_type;/* Hook or Hook(MAX) + Mobj_Hook */ - mobjtype_t mobj_type; + int hook_type; + mobjtype_t mobj_type;/* >0 if mobj hook */ const char * string;/* used to fetch table, ran first if set */ int top;/* index of last argument passed to hook */ - int id;/* id to fetch function from registry */ + int id;/* id to fetch ref */ int values;/* num arguments passed to hook */ int results;/* num values returned by hook */ Hook_Callback results_handler;/* callback when hook successfully returns */ }; enum { - HINDEX = 1,/* hook registry */ - EINDEX = 2,/* error handler */ - SINDEX = 3,/* string itself is pushed in case of string hook */ + EINDEX = 1,/* error handler */ + SINDEX = 2,/* string itself is pushed in case of string hook */ }; static void push_error_handler(void) @@ -268,7 +270,6 @@ static void push_string(void) static boolean start_hook_stack(void) { lua_settop(gL, 0); - lua_getref(gL, hookReg); push_error_handler(); return true; } @@ -280,20 +281,12 @@ static boolean init_hook_type int hook_type, mobjtype_t mobj_type, const char * string, - int ref + int nonzero ){ - boolean ready; - hook->status = status; - if (mobj_type > 0) - ready = mobj_hook_available(hook_type, mobj_type); - else - ready = ref > 0; - - if (ready) + if (nonzero) { - hook->ref = ref; hook->hook_type = hook_type; hook->mobj_type = mobj_type; hook->string = string; @@ -311,7 +304,7 @@ static boolean prepare_hook ){ return init_hook_type(hook, default_status, hook_type, 0, NULL, - hookRefs[hook_type]); + hookIds[hook_type].numHooks); } static boolean prepare_mobj_hook @@ -323,7 +316,7 @@ static boolean prepare_mobj_hook ){ return init_hook_type(hook, default_status, hook_type, mobj_type, NULL, - mobjHookRefs[mobj_type][hook_type]); + mobj_hook_available(hook_type, mobj_type)); } static boolean prepare_string_hook @@ -357,16 +350,17 @@ static void init_hook_call hook->results_handler = results_handler; } -static void get_hook_table(Hook_State *hook) +static void get_hook(Hook_State *hook, const int *ids, int n) { - lua_getref(gL, hook->ref); + hook->id = ids[n]; + lua_getref(gL, hookRefs[hook->id]); } -static void get_hook(Hook_State *hook, int n) +static void get_hook_from_table(Hook_State *hook, int n) { lua_rawgeti(gL, -1, n); - hook->id = lua_tonumber(gL, -1) - 1; - lua_rawget(gL, HINDEX); + hook->id = lua_tonumber(gL, -1); + lua_getref(gL, hookRefs[hook->id]); } static int call_single_hook_no_copy(Hook_State *hook) @@ -409,7 +403,7 @@ static int call_hook_table_for(Hook_State *hook, int n) for (k = 1; k <= n; ++k) { - get_hook(hook, k); + get_hook_from_table(hook, k); call_single_hook(hook); } @@ -421,31 +415,29 @@ static int call_hook_table(Hook_State *hook) return call_hook_table_for(hook, lua_objlen(gL, -1)); } -static int call_ref(Hook_State *hook, int ref) +static int call_mapped(Hook_State *hook, const hook_t *map) { - int calls; + int k; - if (ref > 0) + for (k = 0; k < map->numHooks; ++k) { - lua_getref(gL, ref); - calls = call_hook_table(hook); - - return calls; + get_hook(hook, map->ids, k); + call_single_hook(hook); } - else - return 0; + + return map->numHooks; } static int call_string_hooks(Hook_State *hook) { - const int numGeneric = stringHooks[hook->hook_type].numGeneric; + const stringhook_t *map = &stringHooks[hook->hook_type]; int calls = 0; - get_hook_table(hook); + lua_getref(gL, map->ref); /* call generic string hooks first */ - calls += call_hook_table_for(hook, numGeneric); + calls += call_hook_table_for(hook, map->numGeneric); push_string(); lua_rawget(gL, -2); @@ -454,10 +446,9 @@ static int call_string_hooks(Hook_State *hook) return calls; } -static int call_generic_mobj_hooks(Hook_State *hook) +static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) { - const int ref = mobjHookRefs[MT_NULL][hook->hook_type]; - return call_ref(hook, ref); + return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); } static int call_hooks @@ -475,16 +466,16 @@ static int call_hooks { calls += call_string_hooks(hook); } - else + else if (hook->mobj_type > 0) { - if (hook->mobj_type > 0) - calls += call_generic_mobj_hooks(hook); + /* call generic mobj hooks first */ + calls += call_mobj_type_hooks(hook, MT_NULL); + calls += call_mobj_type_hooks(hook, hook->mobj_type); - calls += call_ref(hook, hook->ref); - - if (hook->mobj_type > 0) - ps_lua_mobjhooks += calls; + ps_lua_mobjhooks += calls; } + else + calls += call_mapped(hook, &hookIds[hook->hook_type]); lua_settop(gL, 0); @@ -600,25 +591,24 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) void LUA_HookThinkFrame(void) { + const int type = Hook(ThinkFrame); + // variables used by perf stats int hook_index = 0; precise_t time_taken = 0; Hook_State hook; - int n; + const hook_t * map = &hookIds[type]; int k; - if (prepare_hook(&hook, 0, Hook(ThinkFrame))) + if (prepare_hook(&hook, 0, type)) { init_hook_call(&hook, 0, 0, res_none); - get_hook_table(&hook); - n = lua_objlen(gL, -1); - - for (k = 1; k <= n; ++k) + for (k = 0; k < map->numHooks; ++k) { - get_hook(&hook, k); + get_hook(&hook, map->ids, k); if (cv_perfstats.value == 3) { @@ -839,19 +829,16 @@ int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 d void LUA_HookNetArchive(lua_CFunction archFunc) { - const int ref = hookRefs[Hook(NetVars)]; + const hook_t * map = &hookIds[Hook(NetVars)]; Hook_State hook; /* this is a remarkable case where the stack isn't reset */ - if (ref > 0) + if (map->numHooks > 0) { // stack: tables I_Assert(lua_gettop(gL) > 0); I_Assert(lua_istable(gL, -1)); push_error_handler(); - lua_getref(gL, hookReg); - - lua_insert(gL, HINDEX); lua_insert(gL, EINDEX); // tables becomes an upvalue of archFunc @@ -860,11 +847,10 @@ void LUA_HookNetArchive(lua_CFunction archFunc) // stack: tables, archFunc init_hook_call(&hook, 1, 0, res_none); - call_ref(&hook, ref); + call_mapped(&hook, map); lua_pop(gL, 2); // pop hook table and archFunc lua_remove(gL, EINDEX); // pop error handler - lua_remove(gL, HINDEX); // pop hook registry // stack: tables } } @@ -1031,22 +1017,25 @@ static void res_musicchange(Hook_State *hook) int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) { - Hook_State hook; - if (prepare_hook(&hook, false, Hook(MusicChange))) - { - int n; - int k; + const int type = Hook(MusicChange); + const hook_t * map = &hookIds[type]; + Hook_State hook; + + int k; + + if (prepare_hook(&hook, false, type)) + { init_hook_call(&hook, 7, 6, res_musicchange); hook.userdata = param; lua_pushstring(gL, oldname);/* the only constant value */ lua_pushstring(gL, param->newname);/* semi constant */ - get_hook_table(&hook); - n = lua_objlen(gL, -1); + for (k = 0; k <= map->numHooks; ++k) + { + get_hook(&hook, map->ids, k); - for (k = 1; k <= n; ++k) { lua_pushvalue(gL, -3); lua_pushvalue(gL, -3); lua_pushinteger(gL, *param->mflags); @@ -1060,5 +1049,6 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) lua_settop(gL, 0); } + return hook.status; } From dbd8903a538e7b87061795ce27ec5c72c26743af Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 10 Dec 2020 08:50:23 -0800 Subject: [PATCH 008/241] Use ref for pushing error handler --- src/lua_hooklib.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 02c427979..1ac9a6952 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -74,6 +74,8 @@ static int * hookRefs; // After a hook errors once, don't print the error again. static UINT8 * hooksErrored; +static int errorRef; + static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type) { return @@ -231,7 +233,11 @@ static int lib_addHook(lua_State *L) int LUA_HookLib(lua_State *L) { + lua_pushcfunction(L, LUA_GetErrorMessage); + errorRef = luaL_ref(L, LUA_REGISTRYINDEX); + lua_register(L, "addHook", lib_addHook); + return 0; } @@ -258,7 +264,7 @@ enum { static void push_error_handler(void) { - lua_pushcfunction(gL, LUA_GetErrorMessage); + lua_getref(gL, errorRef); } /* repush hook string */ From f79ded7c0b86a6d8e9c23f8fb0ec2c417c03752a Mon Sep 17 00:00:00 2001 From: katsy Date: Thu, 10 Dec 2020 20:52:06 -0500 Subject: [PATCH 009/241] scale minimum dashmode thok on actionspd, not normalspeed --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index c5f919c78..c760d52ec 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -5289,7 +5289,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) fixed_t actionspd = player->actionspd; if (player->charflags & SF_DASHMODE) - actionspd = max(player->normalspeed, FixedDiv(player->speed, player->mo->scale)); + actionspd = max(player->actionspd, FixedDiv(player->speed, player->mo->scale)); if (player->mo->eflags & MFE_UNDERWATER) actionspd >>= 1; From ab156e17091479257fd6fc6287c7973a73d7329b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Fri, 11 Dec 2020 23:11:15 -0500 Subject: [PATCH 010/241] Remove music slot compatibility --- src/deh_lua.c | 27 ------------- src/deh_soc.c | 100 ---------------------------------------------- src/deh_soc.h | 5 +-- src/doomdef.h | 4 -- src/lua_baselib.c | 67 +------------------------------ src/s_sound.c | 39 ++---------------- src/s_sound.h | 6 --- 7 files changed, 5 insertions(+), 243 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index e6a436421..51632079b 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -25,10 +25,6 @@ #include "deh_lua.h" #include "deh_tables.h" -#ifdef MUSICSLOT_COMPATIBILITY -#include "deh_soc.h" // for get_mus -#endif - // freeslot takes a name (string only!) // and allocates it to the appropriate free slot. // Returns the slot number allocated for it or nil if failed. @@ -430,29 +426,6 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word); return 0; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (!mathlib && fastncmp("mus_",word,4)) { - p = word+4; - if ((i = get_mus(p, false)) == 0) - return 0; - lua_pushinteger(L, i); - return 1; - } - else if (mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS! - p = word+4; - if ((i = get_mus(p, false)) == 0) - return luaL_error(L, "music '%s' could not be found.\n", word); - lua_pushinteger(L, i); - return 1; - } - else if (mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) { - p = word+2; - if ((i = get_mus(p, false)) == 0) - return luaL_error(L, "music '%s' could not be found.\n", word); - lua_pushinteger(L, i); - return 1; - } -#endif else if (!mathlib && fastncmp("pw_",word,3)) { p = word+3; for (i = 0; i < NUMPOWERS; i++) diff --git a/src/deh_soc.c b/src/deh_soc.c index 5b12ea1b0..2cd872378 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1574,19 +1574,6 @@ void readlevelheader(MYFILE *f, INT32 num) sizeof(mapheaderinfo[num-1]->musname), va("Level header %d: music", num)); } } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastcmp(word, "MUSICSLOT")) - { - i = get_mus(word2, true); - if (i && i <= 1035) - snprintf(mapheaderinfo[num-1]->musname, 7, "%sM", G_BuildMapName(i)); - else if (i && i <= 1050) - strncpy(mapheaderinfo[num-1]->musname, compat_special_music_slots[i - 1036], 7); - else - mapheaderinfo[num-1]->musname[0] = 0; // becomes empty string - mapheaderinfo[num-1]->musname[6] = 0; - } -#endif else if (fastcmp(word, "MUSICTRACK")) mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1); else if (fastcmp(word, "MUSICPOS")) @@ -1964,19 +1951,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7); cutscenes[num]->scene[scenenum].musswitch[6] = 0; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastcmp(word, "MUSICSLOT")) - { - i = get_mus(word2, true); - if (i && i <= 1035) - snprintf(cutscenes[num]->scene[scenenum].musswitch, 7, "%sM", G_BuildMapName(i)); - else if (i && i <= 1050) - strncpy(cutscenes[num]->scene[scenenum].musswitch, compat_special_music_slots[i - 1036], 7); - else - cutscenes[num]->scene[scenenum].musswitch[0] = 0; // becomes empty string - cutscenes[num]->scene[scenenum].musswitch[6] = 0; - } -#endif else if (fastcmp(word, "MUSICTRACK")) { cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK; @@ -2239,19 +2213,6 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) strncpy(textprompts[num]->page[pagenum].musswitch, word2, 7); textprompts[num]->page[pagenum].musswitch[6] = 0; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastcmp(word, "MUSICSLOT")) - { - i = get_mus(word2, true); - if (i && i <= 1035) - snprintf(textprompts[num]->page[pagenum].musswitch, 7, "%sM", G_BuildMapName(i)); - else if (i && i <= 1050) - strncpy(textprompts[num]->page[pagenum].musswitch, compat_special_music_slots[i - 1036], 7); - else - textprompts[num]->page[pagenum].musswitch[0] = 0; // becomes empty string - textprompts[num]->page[pagenum].musswitch[6] = 0; - } -#endif else if (fastcmp(word, "MUSICTRACK")) { textprompts[num]->page[pagenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK; @@ -2577,20 +2538,6 @@ void readmenu(MYFILE *f, INT32 num) menupres[num].musname[6] = 0; titlechanged = true; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastcmp(word, "MUSICSLOT")) - { - value = get_mus(word2, true); - if (value && value <= 1035) - snprintf(menupres[num].musname, 7, "%sM", G_BuildMapName(value)); - else if (value && value <= 1050) - strncpy(menupres[num].musname, compat_special_music_slots[value - 1036], 7); - else - menupres[num].musname[0] = 0; // becomes empty string - menupres[num].musname[6] = 0; - titlechanged = true; - } -#endif else if (fastcmp(word, "MUSICTRACK")) { menupres[num].mustrack = ((UINT16)value - 1); @@ -4178,46 +4125,6 @@ sfxenum_t get_sfx(const char *word) return sfx_None; } -#ifdef MUSICSLOT_COMPATIBILITY -UINT16 get_mus(const char *word, UINT8 dehacked_mode) -{ // Returns the value of MUS_ enumerations - UINT16 i; - char lumptmp[4]; - - if (*word >= '0' && *word <= '9') - return atoi(word); - if (!word[2] && toupper(word[0]) >= 'A' && toupper(word[0]) <= 'Z') - return (UINT16)M_MapNumber(word[0], word[1]); - - if (fastncmp("MUS_",word,4)) - word += 4; // take off the MUS_ - else if (fastncmp("O_",word,2) || fastncmp("D_",word,2)) - word += 2; // take off the O_ or D_ - - strncpy(lumptmp, word, 4); - lumptmp[3] = 0; - if (fasticmp("MAP",lumptmp)) - { - word += 3; - if (toupper(word[0]) >= 'A' && toupper(word[0]) <= 'Z') - return (UINT16)M_MapNumber(word[0], word[1]); - else if ((i = atoi(word))) - return i; - - word -= 3; - if (dehacked_mode) - deh_warning("Couldn't find music named 'MUS_%s'",word); - return 0; - } - for (i = 0; compat_special_music_slots[i][0]; ++i) - if (fasticmp(word, compat_special_music_slots[i])) - return i + 1036; - if (dehacked_mode) - deh_warning("Couldn't find music named 'MUS_%s'",word); - return 0; -} -#endif - hudnum_t get_huditem(const char *word) { // Returns the value of HUD_ enumerations hudnum_t i; @@ -4448,13 +4355,6 @@ static fixed_t find_const(const char **rword) free(word); return r; } -#ifdef MUSICSLOT_COMPATIBILITY - else if (fastncmp("MUS_",word,4) || fastncmp("O_",word,2)) { - r = get_mus(word, true); - free(word); - return r; - } -#endif else if (fastncmp("PW_",word,3)) { r = get_power(word); free(word); diff --git a/src/deh_soc.h b/src/deh_soc.h index 2bcb52e70..0082e0e70 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -43,7 +43,7 @@ #include "info.h" #include "dehacked.h" -#include "doomdef.h" // MUSICSLOT_COMPATIBILITY, HWRENDER +#include "doomdef.h" // HWRENDER // Crazy word-reading stuff /// \todo Put these in a seperate file or something. @@ -52,9 +52,6 @@ statenum_t get_state(const char *word); spritenum_t get_sprite(const char *word); playersprite_t get_sprite2(const char *word); sfxenum_t get_sfx(const char *word); -#ifdef MUSICSLOT_COMPATIBILITY -UINT16 get_mus(const char *word, UINT8 dehacked_mode); -#endif hudnum_t get_huditem(const char *word); menutype_t get_menutype(const char *word); //INT16 get_gametype(const char *word); diff --git a/src/doomdef.h b/src/doomdef.h index d0b7ea0c2..3958d85d0 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -607,10 +607,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.) //#define REDSANALOG -/// Backwards compatibility with musicslots. -/// \note You should leave this enabled unless you're working with a future SRB2 version. -#define MUSICSLOT_COMPATIBILITY - /// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls. //#define PAPER_COLLISIONCORRECTION diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 515f6f0ba..3836fffb8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2803,46 +2803,13 @@ static int lib_sStopSoundByID(lua_State *L) static int lib_sChangeMusic(lua_State *L) { -#ifdef MUSICSLOT_COMPATIBILITY - const char *music_name; - UINT32 music_num, position, prefadems, fadeinms; - char music_compat_name[7]; + UINT32 position, prefadems, fadeinms; - boolean looping; - player_t *player = NULL; - UINT16 music_flags = 0; - //NOHUD - - if (lua_isnumber(L, 1)) - { - music_num = (UINT32)luaL_checkinteger(L, 1); - music_flags = (UINT16)(music_num & 0x0000FFFF); - if (music_flags && music_flags <= 1035) - snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags)); - else if (music_flags && music_flags <= 1050) - strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7); - else - music_compat_name[0] = 0; // becomes empty string - music_compat_name[6] = 0; - music_name = (const char *)&music_compat_name; - music_flags = 0; - } - else - { - music_num = 0; - music_name = luaL_checkstring(L, 1); - } - - looping = (boolean)lua_opttrueboolean(L, 2); - -#else const char *music_name = luaL_checkstring(L, 1); boolean looping = (boolean)lua_opttrueboolean(L, 2); player_t *player = NULL; UINT16 music_flags = 0; - //NOHUD -#endif if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) { player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); @@ -2850,13 +2817,7 @@ static int lib_sChangeMusic(lua_State *L) return LUA_ErrInvalid(L, "player_t"); } -#ifdef MUSICSLOT_COMPATIBILITY - if (music_num) - music_flags = (UINT16)((music_num & 0x7FFF0000) >> 16); - else -#endif music_flags = (UINT16)luaL_optinteger(L, 4, 0); - position = (UINT32)luaL_optinteger(L, 5, 0); prefadems = (UINT32)luaL_optinteger(L, 6, 0); fadeinms = (UINT32)luaL_optinteger(L, 7, 0); @@ -3153,33 +3114,7 @@ static int lib_sMusicExists(lua_State *L) { boolean checkMIDI = lua_opttrueboolean(L, 2); boolean checkDigi = lua_opttrueboolean(L, 3); -#ifdef MUSICSLOT_COMPATIBILITY - const char *music_name; - UINT32 music_num; - char music_compat_name[7]; - UINT16 music_flags = 0; - NOHUD - if (lua_isnumber(L, 1)) - { - music_num = (UINT32)luaL_checkinteger(L, 1); - music_flags = (UINT16)(music_num & 0x0000FFFF); - if (music_flags && music_flags <= 1035) - snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags)); - else if (music_flags && music_flags <= 1050) - strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7); - else - music_compat_name[0] = 0; // becomes empty string - music_compat_name[6] = 0; - music_name = (const char *)&music_compat_name; - } - else - { - music_num = 0; - music_name = luaL_checkstring(L, 1); - } -#else const char *music_name = luaL_checkstring(L, 1); -#endif NOHUD lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi)); return 1; diff --git a/src/s_sound.c b/src/s_sound.c index 36bd454c1..ecce7e9c4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1354,28 +1354,6 @@ void S_InitSfxChannels(INT32 sfxVolume) /// Music /// ------------------------ -#ifdef MUSICSLOT_COMPATIBILITY -const char *compat_special_music_slots[16] = -{ - "_title", // 1036 title screen - "_intro", // 1037 intro - "_clear", // 1038 level clear - "_inv", // 1039 invincibility - "_shoes", // 1040 super sneakers - "_minv", // 1041 Mario invincibility - "_drown", // 1042 drowning - "_gover", // 1043 game over - "_1up", // 1044 extra life - "_conti", // 1045 continue screen - "_super", // 1046 Super Sonic - "_chsel", // 1047 character select - "_creds", // 1048 credits - "_inter", // 1049 Race Results - "_stjr", // 1050 Sonic Team Jr. Presents - "" -}; -#endif - static char music_name[7]; // up to 6-character name static void *music_data; static UINT16 music_flags; @@ -2465,7 +2443,7 @@ void S_StartEx(boolean reset) static void Command_Tunes_f(void) { const char *tunearg; - UINT16 tunenum, track = 0; + UINT16 track = 0; UINT32 position = 0; const size_t argc = COM_Argc(); @@ -2481,7 +2459,6 @@ static void Command_Tunes_f(void) } tunearg = COM_Argv(1); - tunenum = (UINT16)atoi(tunearg); track = 0; if (!strcasecmp(tunearg, "-show")) @@ -2500,24 +2477,14 @@ static void Command_Tunes_f(void) tunearg = mapheaderinfo[gamemap-1]->musname; track = mapheaderinfo[gamemap-1]->mustrack; } - else if (!tunearg[2] && toupper(tunearg[0]) >= 'A' && toupper(tunearg[0]) <= 'Z') - tunenum = (UINT16)M_MapNumber(tunearg[0], tunearg[1]); - if (tunenum && tunenum >= 1036) - { - CONS_Alert(CONS_NOTICE, M_GetText("Valid music slots are 1 to 1035.\n")); - return; - } - if (!tunenum && strlen(tunearg) > 6) // This is automatic -- just show the error just in case + if (strlen(tunearg) > 6) // This is automatic -- just show the error just in case CONS_Alert(CONS_NOTICE, M_GetText("Music name too long - truncated to six characters.\n")); if (argc > 2) track = (UINT16)atoi(COM_Argv(2))-1; - if (tunenum) - snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum)); - else - strncpy(mapmusname, tunearg, 7); + strncpy(mapmusname, tunearg, 7); if (argc > 4) position = (UINT32)atoi(COM_Argv(4)); diff --git a/src/s_sound.h b/src/s_sound.h index 4ac3c70bf..ab2c411c0 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -319,10 +319,4 @@ void S_StopSoundByNum(sfxenum_t sfxnum); #define S_StartScreamSound S_StartSound #endif -#ifdef MUSICSLOT_COMPATIBILITY -// For compatibility with code/scripts relying on older versions -// This is a list of all the "special" slot names and their associated numbers -extern const char *compat_special_music_slots[16]; -#endif - #endif From 9ddeb5f5896de0407b2b6fce8c949295a9e6d5e4 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 12 Dec 2020 02:05:21 -0800 Subject: [PATCH 011/241] Resolve GameQuit hook conflicts --- src/d_clisrv.c | 6 +++--- src/d_netcmd.c | 4 ++-- src/lua_hook.h | 1 + src/lua_hooklib.c | 10 ++++++++++ src/m_menu.c | 4 ++-- src/sdl/i_video.c | 2 +- 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 8ecafcc1b..9a24546ea 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3032,7 +3032,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (pnum == consoleplayer) { - LUAh_GameQuit(false); + LUA_HookBool(false, Hook(GameQuit)); #ifdef DUMPCONSISTENCY if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); #endif @@ -3732,7 +3732,7 @@ static void HandleConnect(SINT8 node) static void HandleShutdown(SINT8 node) { (void)node; - LUAh_GameQuit(false); + LUA_HookBool(false, Hook(GameQuit)); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -3747,7 +3747,7 @@ static void HandleShutdown(SINT8 node) static void HandleTimeout(SINT8 node) { (void)node; - LUAh_GameQuit(false); + LUA_HookBool(false, Hook(GameQuit)); D_QuitNetGame(); CL_Reset(); D_StartTitle(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d2f6add0c..25b4b0aa1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3612,7 +3612,7 @@ static void Command_Playintro_f(void) */ FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void) { - LUAh_GameQuit(true); + LUA_HookBool(true, Hook(GameQuit)); I_Quit(); } @@ -4274,7 +4274,7 @@ void Command_ExitGame_f(void) { INT32 i; - LUAh_GameQuit(false); + LUA_HookBool(false, Hook(GameQuit)); D_QuitNetGame(); CL_Reset(); diff --git a/src/lua_hook.h b/src/lua_hook.h index f44a2e305..873c14643 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -84,6 +84,7 @@ void LUA_Hook(int hook); int LUA_HookMobj(mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); void LUA_HookInt(INT32 integer, int hook); +void LUA_HookBool(boolean value, int hook); int LUA_HookPlayer(player_t *, int hook); int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 1ac9a6952..5492c7921 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -561,6 +561,16 @@ void LUA_HookInt(INT32 number, int hook_type) } } +void LUA_HookBool(boolean value, int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, hook_type)) + { + lua_pushboolean(gL, value); + call_hooks(&hook, 1, 0, res_none); + } +} + int LUA_HookPlayer(player_t *player, int hook_type) { Hook_State hook; diff --git a/src/m_menu.c b/src/m_menu.c index 5ec9132f7..c6b1b2b8a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6937,7 +6937,7 @@ static void M_SelectableClearMenus(INT32 choice) static void M_UltimateCheat(INT32 choice) { (void)choice; - LUAh_GameQuit(true); + LUA_HookBool(true, Hook(GameQuit)); I_Quit(); } @@ -13371,7 +13371,7 @@ void M_QuitResponse(INT32 ch) if (ch != 'y' && ch != KEY_ENTER) return; - LUAh_GameQuit(true); + LUA_HookBool(true, Hook(GameQuit)); if (!(netgame || cv_debug)) { S_ResetCaptions(); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 5ebff8700..f3da446d8 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1057,7 +1057,7 @@ void I_GetEvent(void) M_SetupJoystickMenu(0); break; case SDL_QUIT: - LUAh_GameQuit(true); + LUA_HookBool(true, Hook(GameQuit)); I_Quit(); break; } From 93e4f43e4b3a24fc2d8032e8730cbf427e75b297 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 12 Dec 2020 03:06:57 -0800 Subject: [PATCH 012/241] Hooklib macros names -> uppercase + documentation --- src/b_bot.c | 4 +-- src/d_clisrv.c | 8 ++--- src/d_netcmd.c | 6 ++-- src/g_demo.c | 2 +- src/g_game.c | 6 ++-- src/lua_hook.h | 40 +++++++++++++++------- src/lua_hooklib.c | 84 +++++++++++++++++++++++------------------------ src/m_menu.c | 4 +-- src/p_enemy.c | 2 +- src/p_map.c | 4 +-- src/p_mobj.c | 20 +++++------ src/p_setup.c | 2 +- src/p_tick.c | 8 ++--- src/p_user.c | 26 +++++++-------- src/sdl/i_video.c | 2 +- src/y_inter.c | 2 +- 16 files changed, 117 insertions(+), 103 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index 93a853dee..ba5aa3ccf 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -363,7 +363,7 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) CV_SetValue(&cv_analog[1], false); // Let Lua scripts build ticcmds - if (LUA_HookTiccmd(player, cmd, Hook(BotTiccmd))) + if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd))) return; // We don't have any main character AI, sorry. D: @@ -461,7 +461,7 @@ boolean B_CheckRespawn(player_t *player) // B_RespawnBot doesn't do anything if the condition above this isn't met { - UINT8 shouldForce = LUA_Hook2Mobj(sonic, tails, Mobj_Hook(BotRespawn)); + UINT8 shouldForce = LUA_Hook2Mobj(sonic, tails, MOBJ_HOOK(BotRespawn)); if (P_MobjWasRemoved(sonic) || P_MobjWasRemoved(tails)) return (shouldForce == 1); // mobj was removed diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 9a24546ea..2a461be34 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3032,7 +3032,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (pnum == consoleplayer) { - LUA_HookBool(false, Hook(GameQuit)); + LUA_HookBool(false, HOOK(GameQuit)); #ifdef DUMPCONSISTENCY if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); #endif @@ -3452,7 +3452,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); if (!rejoined) - LUA_HookInt(newplayernum, Hook(PlayerJoin)); + LUA_HookInt(newplayernum, HOOK(PlayerJoin)); } static boolean SV_AddWaitingPlayers(const char *name, const char *name2) @@ -3732,7 +3732,7 @@ static void HandleConnect(SINT8 node) static void HandleShutdown(SINT8 node) { (void)node; - LUA_HookBool(false, Hook(GameQuit)); + LUA_HookBool(false, HOOK(GameQuit)); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -3747,7 +3747,7 @@ static void HandleShutdown(SINT8 node) static void HandleTimeout(SINT8 node) { (void)node; - LUA_HookBool(false, Hook(GameQuit)); + LUA_HookBool(false, HOOK(GameQuit)); D_QuitNetGame(); CL_Reset(); D_StartTitle(); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 25b4b0aa1..ee75b059d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2103,7 +2103,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) } mapnumber = M_MapNumber(mapname[3], mapname[4]); - LUA_HookInt(mapnumber, Hook(MapChange)); + LUA_HookInt(mapnumber, HOOK(MapChange)); G_InitNew(ultimatemode, mapname, resetplayer, skipprecutscene, FLS); if (demoplayback && !timingdemo) @@ -3612,7 +3612,7 @@ static void Command_Playintro_f(void) */ FUNCNORETURN static ATTRNORETURN void Command_Quit_f(void) { - LUA_HookBool(true, Hook(GameQuit)); + LUA_HookBool(true, HOOK(GameQuit)); I_Quit(); } @@ -4274,7 +4274,7 @@ void Command_ExitGame_f(void) { INT32 i; - LUA_HookBool(false, Hook(GameQuit)); + LUA_HookBool(false, HOOK(GameQuit)); D_QuitNetGame(); CL_Reset(); diff --git a/src/g_demo.c b/src/g_demo.c index e4af7086c..5bfe2684c 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1956,7 +1956,7 @@ void G_DoPlayDemo(char *defdemoname) // Set skin SetPlayerSkin(0, skin); - LUA_HookInt(gamemap, Hook(MapChange)); + LUA_HookInt(gamemap, HOOK(MapChange)); displayplayer = consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); playeringame[0] = true; diff --git a/src/g_game.c b/src/g_game.c index e889c7113..209ca0580 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1689,7 +1689,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->angleturn = orighookangle; - LUA_HookTiccmd(player, cmd, Hook(PlayerCmd)); + LUA_HookTiccmd(player, cmd, HOOK(PlayerCmd)); extra = cmd->angleturn - orighookangle; cmd->angleturn = origangle + extra; @@ -2740,7 +2740,7 @@ void G_SpawnPlayer(INT32 playernum) P_SpawnPlayer(playernum); G_MovePlayerToSpawnOrStarpost(playernum); - LUA_HookPlayer(&players[playernum], Hook(PlayerSpawn)); // Lua hook for player spawning :) + LUA_HookPlayer(&players[playernum], HOOK(PlayerSpawn)); // Lua hook for player spawning :) } void G_MovePlayerToSpawnOrStarpost(INT32 playernum) @@ -3119,7 +3119,7 @@ void G_DoReborn(INT32 playernum) } else { - LUA_HookInt(gamemap, Hook(MapChange)); + LUA_HookInt(gamemap, HOOK(MapChange)); titlecardforreload = true; G_DoLoadLevel(true); titlecardforreload = false; diff --git a/src/lua_hook.h b/src/lua_hook.h index 873c14643..4274f1f3c 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -14,7 +14,14 @@ #include "d_player.h" #include "s_sound.h" -#define Mobj_Hook_List(X) \ +/* +Do you know what an 'X Macro' is? Such a macro is called over each element of +a list and expands the input. I use it for the hook lists because both an enum +and array of hook names need to be kept in order. The X Macro handles this +automatically. +*/ + +#define MOBJ_HOOK_LIST(X) \ X (MobjSpawn),/* P_SpawnMobj */\ X (MobjCollide),/* PIT_CheckThing */\ X (MobjLineCollide),/* ditto */\ @@ -33,7 +40,7 @@ X (MapThingSpawn),/* P_SpawnMapThing */\ X (FollowMobj),/* P_PlayerAfterThink Smiles mobj-following */\ -#define Hook_List(X) \ +#define HOOK_LIST(X) \ X (NetVars),/* add to archive table (netsave) */\ X (MapChange),/* (before map load) */\ X (MapLoad),\ @@ -62,24 +69,33 @@ X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ X (MusicChange),\ -#define String_Hook_List(X) \ +#define STRING_HOOK_LIST(X) \ X (BotAI),/* B_BuildTailsTiccmd by skin name */\ X (LinedefExecute),\ X (ShouldJingleContinue),/* should jingle of the given music continue playing */\ -#define Mobj_Hook(name) mobjhook_ ## name -#define Hook(name) hook_ ## name -#define String_Hook(name) stringhook_ ## name +/* +I chose to access the hook enums through a macro as well. This could provide +a hint to lookup the macro's definition instead of the enum's definition. +(Since each enumeration is not defined in the source code, but by the list +macros above, it is not greppable.) The name passed to the macro can also be +grepped and found in the lists above. +*/ -enum { Mobj_Hook_List (Mobj_Hook) Mobj_Hook(MAX) }; -enum { Hook_List (Hook) Hook(MAX) }; -enum { String_Hook_List (String_Hook) String_Hook(MAX) }; +#define MOBJ_HOOK(name) mobjhook_ ## name +#define HOOK(name) hook_ ## name +#define STRING_HOOK(name) stringhook_ ## name + +enum { MOBJ_HOOK_LIST (MOBJ_HOOK) MOBJ_HOOK(MAX) }; +enum { HOOK_LIST (HOOK) HOOK(MAX) }; +enum { STRING_HOOK_LIST (STRING_HOOK) STRING_HOOK(MAX) }; + +/* dead simple, LUA_HOOK(GameQuit) */ +#define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) extern boolean hook_cmd_running; -/* dead simple, LUA_Hook(GameQuit) */ -void LUA_Hook(int hook); -#define LUA_Hook(type) LUA_Hook(Hook(type)) +void LUA_HookVoid(int hook); int LUA_HookMobj(mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 5492c7921..4143fbd8e 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -27,17 +27,15 @@ #include "d_netcmd.h" // for cv_perfstats #include "i_system.h" // I_GetPreciseTime -#undef LUA_Hook - /* ========================================================================= ABSTRACTION ========================================================================= */ -static const char * const mobjHookNames[] = { Mobj_Hook_List (TOSTR) NULL }; -static const char * const hookNames[] = { Hook_List (TOSTR) NULL }; +static const char * const mobjHookNames[] = { MOBJ_HOOK_LIST (TOSTR) NULL }; +static const char * const hookNames[] = { HOOK_LIST (TOSTR) NULL }; static const char * const stringHookNames[] = { - String_Hook_List (TOSTR) NULL + STRING_HOOK_LIST (TOSTR) NULL }; /* TODO: remove when doomtype version is merged */ @@ -62,11 +60,11 @@ typedef struct { int ref; } stringhook_t; -static hook_t hookIds[Hook(MAX)]; -static hook_t mobjHookIds[NUMMOBJTYPES][Mobj_Hook(MAX)]; +static hook_t hookIds[HOOK(MAX)]; +static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)]; // Lua tables are used to lookup string hook ids. -static stringhook_t stringHooks[String_Hook(MAX)]; +static stringhook_t stringHooks[STRING_HOOK(MAX)]; // This will be indexed by hook id, the value of which fetches the registry. static int * hookRefs; @@ -132,8 +130,8 @@ static void add_string_hook(lua_State *L, int type, int id) switch (type) { - case String_Hook(BotAI): - case String_Hook(ShouldJingleContinue): + case STRING_HOOK(BotAI): + case STRING_HOOK(ShouldJingleContinue): if (lua_isstring(L, 3)) { // lowercase copy string = Z_StrDup(lua_tostring(L, 3)); @@ -141,7 +139,7 @@ static void add_string_hook(lua_State *L, int type, int id) } break; - case String_Hook(LinedefExecute): + case STRING_HOOK(LinedefExecute): string = Z_StrDup(luaL_checkstring(L, 3)); strupr(string); break; @@ -197,15 +195,15 @@ static int lib_addHook(lua_State *L) luaL_checktype(L, 2, LUA_TFUNCTION); /* this is a very special case */ - if (( type = hook_in_list(name, stringHookNames) ) < String_Hook(MAX)) + if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX)) { add_string_hook(L, type, nextid); } - else if (( type = hook_in_list(name, mobjHookNames) ) < Mobj_Hook(MAX)) + else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX)) { add_mobj_hook(L, type, nextid); } - else if (( type = hook_in_list(name, hookNames) ) < Hook(MAX)) + else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX)) { add_hook(&hookIds[type], nextid); } @@ -544,7 +542,7 @@ int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type) return hook.status; } -void LUA_Hook(int type) +void LUA_HookVoid(int type) { Hook_State hook; if (prepare_hook(&hook, 0, type)) @@ -590,12 +588,12 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, cmd, META_TICCMD); - if (hook_type == Hook(PlayerCmd)) + if (hook_type == HOOK(PlayerCmd)) hook_cmd_running = true; call_hooks(&hook, 2, 1, res_true); - if (hook_type == Hook(PlayerCmd)) + if (hook_type == HOOK(PlayerCmd)) hook_cmd_running = false; } return hook.status; @@ -607,7 +605,7 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) void LUA_HookThinkFrame(void) { - const int type = Hook(ThinkFrame); + const int type = HOOK(ThinkFrame); // variables used by perf stats int hook_index = 0; @@ -651,7 +649,7 @@ void LUA_HookThinkFrame(void) int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) { Hook_State hook; - if (prepare_mobj_hook(&hook, 0, Mobj_Hook(MobjLineCollide), mobj->type)) + if (prepare_mobj_hook(&hook, 0, MOBJ_HOOK(MobjLineCollide), mobj->type)) { LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, line, META_LINE); @@ -663,7 +661,7 @@ int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line) int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, Mobj_Hook(TouchSpecial), special->type)) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(TouchSpecial), special->type)) { LUA_PushUserdata(gL, special, META_MOBJ); LUA_PushUserdata(gL, toucher, META_MOBJ); @@ -700,19 +698,19 @@ static int damage_hook int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { return damage_hook(target, inflictor, source, damage, damagetype, - Mobj_Hook(ShouldDamage), 5, res_force); + MOBJ_HOOK(ShouldDamage), 5, res_force); } int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { return damage_hook(target, inflictor, source, damage, damagetype, - Mobj_Hook(MobjDamage), 5, res_true); + MOBJ_HOOK(MobjDamage), 5, res_true); } int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { return damage_hook(target, inflictor, source, 0, damagetype, - Mobj_Hook(MobjDeath), 4, res_true); + MOBJ_HOOK(MobjDeath), 4, res_true); } typedef struct { @@ -737,12 +735,12 @@ static void res_botai(Hook_State *hook) if (lua_istable(gL, -8)) { lua_pushnil(gL); // key while (lua_next(gL, -9)) { -#define check(n, f) (checkbotkey(f) ? (k[(n)-1] = 1) : 0) +#define CHECK(n, f) (checkbotkey(f) ? (k[(n)-1] = 1) : 0) if ( - check(1, "forward") || check(2, "backward") || - check(3, "left") || check(4, "right") || - check(5, "strafeleft") || check(6, "straferight") || - check(7, "jump") || check(8, "spin") + CHECK(1, "forward") || CHECK(2, "backward") || + CHECK(3, "left") || CHECK(4, "right") || + CHECK(5, "strafeleft") || CHECK(6, "straferight") || + CHECK(7, "jump") || CHECK(8, "spin") ){ if (8 <= ++fields) { @@ -752,7 +750,7 @@ static void res_botai(Hook_State *hook) } lua_pop(gL, 1); // pop value -#undef check +#undef CHECK } } else { while (fields < 8) @@ -775,7 +773,7 @@ int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) Hook_State hook; BotAI_State botai; - if (prepare_string_hook(&hook, false, String_Hook(BotAI), skin)) + if (prepare_string_hook(&hook, false, STRING_HOOK(BotAI), skin)) { LUA_PushUserdata(gL, sonic, META_MOBJ); LUA_PushUserdata(gL, tails, META_MOBJ); @@ -795,7 +793,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) { Hook_State hook; if (prepare_string_hook - (&hook, 0, String_Hook(LinedefExecute), line->stringargs[0])) + (&hook, 0, STRING_HOOK(LinedefExecute), line->stringargs[0])) { LUA_PushUserdata(gL, line, META_LINE); LUA_PushUserdata(gL, mo, META_MOBJ); @@ -807,7 +805,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) int LUA_HookPlayerMsg(int source, int target, int flags, char *msg) { Hook_State hook; - if (prepare_hook(&hook, false, Hook(PlayerMsg))) + if (prepare_hook(&hook, false, HOOK(PlayerMsg))) { LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c @@ -832,7 +830,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg) int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { Hook_State hook; - if (prepare_hook(&hook, false, Hook(HurtMsg))) + if (prepare_hook(&hook, false, HOOK(HurtMsg))) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, inflictor, META_MOBJ); @@ -845,7 +843,7 @@ int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 d void LUA_HookNetArchive(lua_CFunction archFunc) { - const hook_t * map = &hookIds[Hook(NetVars)]; + const hook_t * map = &hookIds[HOOK(NetVars)]; Hook_State hook; /* this is a remarkable case where the stack isn't reset */ if (map->numHooks > 0) @@ -874,7 +872,7 @@ void LUA_HookNetArchive(lua_CFunction archFunc) int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, Mobj_Hook(MapThingSpawn), mobj->type)) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(MapThingSpawn), mobj->type)) { LUA_PushUserdata(gL, mobj, META_MOBJ); LUA_PushUserdata(gL, mthing, META_MAPTHING); @@ -886,7 +884,7 @@ int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing) int LUA_HookFollowMobj(player_t *player, mobj_t *mobj) { Hook_State hook; - if (prepare_mobj_hook(&hook, false, Mobj_Hook(FollowMobj), mobj->type)) + if (prepare_mobj_hook(&hook, false, MOBJ_HOOK(FollowMobj), mobj->type)) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, mobj, META_MOBJ); @@ -898,7 +896,7 @@ int LUA_HookFollowMobj(player_t *player, mobj_t *mobj) int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj) { Hook_State hook; - if (prepare_hook(&hook, 0, Hook(PlayerCanDamage))) + if (prepare_hook(&hook, 0, HOOK(PlayerCanDamage))) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, mobj, META_MOBJ); @@ -910,7 +908,7 @@ int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj) void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason) { Hook_State hook; - if (prepare_hook(&hook, 0, Hook(PlayerQuit))) + if (prepare_hook(&hook, 0, HOOK(PlayerQuit))) { LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit lua_pushinteger(gL, reason); // Reason for quitting @@ -921,7 +919,7 @@ void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason) int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) { Hook_State hook; - if (prepare_hook(&hook, true, Hook(TeamSwitch))) + if (prepare_hook(&hook, true, HOOK(TeamSwitch))) { LUA_PushUserdata(gL, player, META_PLAYER); lua_pushinteger(gL, newteam); @@ -936,7 +934,7 @@ int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, bo int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) { Hook_State hook; - if (prepare_hook(&hook, 0, Hook(ViewpointSwitch))) + if (prepare_hook(&hook, 0, HOOK(ViewpointSwitch))) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); @@ -953,7 +951,7 @@ int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolea int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend) { Hook_State hook; - if (prepare_hook(&hook, true, Hook(SeenPlayer))) + if (prepare_hook(&hook, true, HOOK(SeenPlayer))) { LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, seenfriend, META_PLAYER); @@ -970,7 +968,7 @@ int LUA_HookShouldJingleContinue(player_t *player, const char *musname) { Hook_State hook; if (prepare_string_hook - (&hook, false, String_Hook(ShouldJingleContinue), musname)) + (&hook, false, STRING_HOOK(ShouldJingleContinue), musname)) { LUA_PushUserdata(gL, player, META_PLAYER); push_string(); @@ -1033,7 +1031,7 @@ static void res_musicchange(Hook_State *hook) int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) { - const int type = Hook(MusicChange); + const int type = HOOK(MusicChange); const hook_t * map = &hookIds[type]; Hook_State hook; diff --git a/src/m_menu.c b/src/m_menu.c index c6b1b2b8a..2a44bb2a4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -6937,7 +6937,7 @@ static void M_SelectableClearMenus(INT32 choice) static void M_UltimateCheat(INT32 choice) { (void)choice; - LUA_HookBool(true, Hook(GameQuit)); + LUA_HookBool(true, HOOK(GameQuit)); I_Quit(); } @@ -13371,7 +13371,7 @@ void M_QuitResponse(INT32 ch) if (ch != 'y' && ch != KEY_ENTER) return; - LUA_HookBool(true, Hook(GameQuit)); + LUA_HookBool(true, HOOK(GameQuit)); if (!(netgame || cv_debug)) { S_ResetCaptions(); diff --git a/src/p_enemy.c b/src/p_enemy.c index 276fc999d..2aec5c989 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3961,7 +3961,7 @@ void A_BossDeath(mobj_t *mo) } bossjustdie: - if (LUA_HookMobj(mo, Mobj_Hook(BossDeath))) + if (LUA_HookMobj(mo, MOBJ_HOOK(BossDeath))) return; else if (P_MobjWasRemoved(mo)) return; diff --git a/src/p_map.c b/src/p_map.c index e55238ffa..14eac1147 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -937,7 +937,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } { - UINT8 shouldCollide = LUA_Hook2Mobj(thing, tmthing, Mobj_Hook(MobjCollide)); // checks hook for thing's type + UINT8 shouldCollide = LUA_Hook2Mobj(thing, tmthing, MOBJ_HOOK(MobjCollide)); // checks hook for thing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -945,7 +945,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (shouldCollide == 2) return true; // force no collide - shouldCollide = LUA_Hook2Mobj(tmthing, thing, Mobj_Hook(MobjMoveCollide)); // checks hook for tmthing's type + shouldCollide = LUA_Hook2Mobj(tmthing, thing, MOBJ_HOOK(MobjMoveCollide)); // checks hook for tmthing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) diff --git a/src/p_mobj.c b/src/p_mobj.c index c2de01fa7..9d8a7bd7d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1844,7 +1844,7 @@ void P_XYMovement(mobj_t *mo) B_MoveBlocked(player); } - if (LUA_HookMobj(mo, Mobj_Hook(MobjMoveBlocked))) + if (LUA_HookMobj(mo, MOBJ_HOOK(MobjMoveBlocked))) { if (P_MobjWasRemoved(mo)) return; @@ -7509,7 +7509,7 @@ static void P_RosySceneryThink(mobj_t *mobj) static void P_MobjSceneryThink(mobj_t *mobj) { - if (LUA_HookMobj(mobj, Mobj_Hook(MobjThinker))) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker))) return; if (P_MobjWasRemoved(mobj)) return; @@ -7857,7 +7857,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) if (!mobj->fuse) { - if (!LUA_HookMobj(mobj, Mobj_Hook(MobjFuse))) + if (!LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse))) P_RemoveMobj(mobj); return; } @@ -7916,7 +7916,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) mobj->fuse--; if (!mobj->fuse) { - if (!LUA_HookMobj(mobj, Mobj_Hook(MobjFuse))) + if (!LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse))) P_RemoveMobj(mobj); return; } @@ -7945,7 +7945,7 @@ static boolean P_MobjPushableThink(mobj_t *mobj) static boolean P_MobjBossThink(mobj_t *mobj) { - if (LUA_HookMobj(mobj, Mobj_Hook(BossThinker))) + if (LUA_HookMobj(mobj, MOBJ_HOOK(BossThinker))) { if (P_MobjWasRemoved(mobj)) return false; @@ -9872,7 +9872,7 @@ static boolean P_FuseThink(mobj_t *mobj) if (mobj->fuse) return true; - if (LUA_HookMobj(mobj, Mobj_Hook(MobjFuse)) || P_MobjWasRemoved(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjFuse)) || P_MobjWasRemoved(mobj)) ; else if (mobj->info->flags & MF_MONITOR) { @@ -10048,13 +10048,13 @@ void P_MobjThinker(mobj_t *mobj) // Check for a Lua thinker first if (!mobj->player) { - if (LUA_HookMobj(mobj, Mobj_Hook(MobjThinker)) || P_MobjWasRemoved(mobj)) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker)) || P_MobjWasRemoved(mobj)) return; } else if (!mobj->player->spectator) { // You cannot short-circuit the player thinker like you can other thinkers. - LUA_HookMobj(mobj, Mobj_Hook(MobjThinker)); + LUA_HookMobj(mobj, MOBJ_HOOK(MobjThinker)); if (P_MobjWasRemoved(mobj)) return; } @@ -10525,7 +10525,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks! - if (LUA_HookMobj(mobj, Mobj_Hook(MobjSpawn))) + if (LUA_HookMobj(mobj, MOBJ_HOOK(MobjSpawn))) { if (P_MobjWasRemoved(mobj)) return NULL; @@ -10912,7 +10912,7 @@ void P_RemoveMobj(mobj_t *mobj) return; // something already removing this mobj. mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. - LUA_HookMobj(mobj, Mobj_Hook(MobjRemoved)); + LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved)); mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work. // Rings only, please! diff --git a/src/p_setup.c b/src/p_setup.c index 09addd73d..0ab43a8bc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4271,7 +4271,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); } P_PreTicker(2); - LUA_HookInt(gamemap, Hook(MapLoad)); + LUA_HookInt(gamemap, HOOK(MapLoad)); } // No render mode or reloading gamestate, stop here. diff --git a/src/p_tick.c b/src/p_tick.c index 5857100a3..0f342daf1 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -656,7 +656,7 @@ void P_Ticker(boolean run) ps_lua_mobjhooks = 0; ps_checkposition_calls = 0; - LUA_Hook(PreThinkFrame); + LUA_HOOK(PreThinkFrame); ps_playerthink_time = I_GetPreciseTime(); for (i = 0; i < MAXPLAYERS; i++) @@ -760,7 +760,7 @@ void P_Ticker(boolean run) if (modeattacking) G_GhostTicker(); - LUA_Hook(PostThinkFrame); + LUA_HOOK(PostThinkFrame); } P_MapEnd(); @@ -783,7 +783,7 @@ void P_PreTicker(INT32 frames) { P_MapStart(); - LUA_Hook(PreThinkFrame); + LUA_HOOK(PreThinkFrame); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) @@ -819,7 +819,7 @@ void P_PreTicker(INT32 frames) P_UpdateSpecials(); P_RespawnSpecials(); - LUA_Hook(PostThinkFrame); + LUA_HOOK(PostThinkFrame); P_MapEnd(); } diff --git a/src/p_user.c b/src/p_user.c index 370a0c1f1..e6bd8e5ec 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1860,7 +1860,7 @@ void P_SpawnShieldOrb(player_t *player) I_Error("P_SpawnShieldOrb: player->mo is NULL!\n"); #endif - if (LUA_HookPlayer(player, Hook(ShieldSpawn))) + if (LUA_HookPlayer(player, HOOK(ShieldSpawn))) return; if (player->powers[pw_shield] & SH_FORCE) @@ -4581,7 +4581,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_SPIN) { - if (LUA_HookPlayer(player, Hook(SpinSpecial))) + if (LUA_HookPlayer(player, HOOK(SpinSpecial))) return; } @@ -5047,7 +5047,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, Hook(ShieldSpecial))) // Spin button effects + if (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, HOOK(ShieldSpecial))) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5171,7 +5171,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // and you don't have a shield, do it! P_DoSuperTransformation(player, false); } - else if (!LUA_HookPlayer(player, Hook(JumpSpinSpecial))) + else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) switch (player->charability) { case CA_THOK: @@ -5244,7 +5244,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_JUMP && !player->exiting && !P_PlayerInPain(player)) { - if (LUA_HookPlayer(player, Hook(JumpSpecial))) + if (LUA_HookPlayer(player, HOOK(JumpSpecial))) ; // all situations below this require jump button not to be pressed already else if (player->pflags & PF_JUMPDOWN) @@ -5279,7 +5279,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) }*/ else if (player->pflags & PF_JUMPED) { - if (!LUA_HookPlayer(player, Hook(AbilitySpecial))) + if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) switch (player->charability) { case CA_THOK: @@ -5472,7 +5472,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } else if (player->pflags & PF_THOKKED) { - if (!LUA_HookPlayer(player, Hook(AbilitySpecial))) + if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) switch (player->charability) { case CA_FLY: @@ -11479,7 +11479,7 @@ void P_PlayerThink(player_t *player) } if (player->playerstate == PST_REBORN) { - LUA_HookPlayer(player, Hook(PlayerThink)); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -11583,7 +11583,7 @@ void P_PlayerThink(player_t *player) if (player->playerstate == PST_DEAD) { - LUA_HookPlayer(player, Hook(PlayerThink)); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -11704,7 +11704,7 @@ void P_PlayerThink(player_t *player) { player->mo->flags2 &= ~MF2_SHADOW; P_DeathThink(player); - LUA_HookPlayer(player, Hook(PlayerThink)); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } @@ -11746,7 +11746,7 @@ void P_PlayerThink(player_t *player) { if (P_SpectatorJoinGame(player)) { - LUA_HookPlayer(player, Hook(PlayerThink)); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; // player->mo was removed. } } @@ -11851,7 +11851,7 @@ void P_PlayerThink(player_t *player) if (!player->mo) { - LUA_HookPlayer(player, Hook(PlayerThink)); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; // P_MovePlayer removed player->mo. } @@ -12305,7 +12305,7 @@ void P_PlayerThink(player_t *player) } #undef dashmode - LUA_HookPlayer(player, Hook(PlayerThink)); + LUA_HookPlayer(player, HOOK(PlayerThink)); /* // Colormap verification diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index f3da446d8..0bdb70d1f 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1057,7 +1057,7 @@ void I_GetEvent(void) M_SetupJoystickMenu(0); break; case SDL_QUIT: - LUA_HookBool(true, Hook(GameQuit)); + LUA_HookBool(true, HOOK(GameQuit)); I_Quit(); break; } diff --git a/src/y_inter.c b/src/y_inter.c index ae4dcdaf0..5930d35ec 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -927,7 +927,7 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; - LUA_Hook(IntermissionThinker); + LUA_HOOK(IntermissionThinker); intertic++; From 5bb221b3bfb501c940e96871cbb068abc8f4a8d4 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 12 Dec 2020 15:39:13 -0800 Subject: [PATCH 013/241] Yeah Fuck You SEENAMES --- src/lua_hook.h | 2 -- src/lua_hooklib.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 4274f1f3c..0f8482794 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -120,9 +120,7 @@ int LUA_HookPlayerCanDamage(player_t *, mobj_t *); void LUA_HookPlayerQuit(player_t *, kickreason_t); int LUA_HookTeamSwitch(player_t *, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); -#ifdef SEENAMES int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend); -#endif int LUA_HookShouldJingleContinue(player_t *, const char *musname); int LUA_HookPlayerCmd(player_t *, ticcmd_t *); int LUA_HookMusicChange(const char *oldname, struct MusicChange *); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 4143fbd8e..3a63e446e 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -947,7 +947,6 @@ int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolea return hook.status; } -#ifdef SEENAMES int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend) { Hook_State hook; @@ -962,7 +961,6 @@ int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend) } return hook.status; } -#endif // SEENAMES int LUA_HookShouldJingleContinue(player_t *player, const char *musname) { From 83e80eef9ba1e60a71970807962ed49c9669eceb Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 12 Dec 2020 18:54:47 -0500 Subject: [PATCH 014/241] Add deprecation warning when using the level header parameter --- src/deh_soc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/deh_soc.c b/src/deh_soc.c index 2cd872378..2075d6484 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1574,6 +1574,8 @@ void readlevelheader(MYFILE *f, INT32 num) sizeof(mapheaderinfo[num-1]->musname), va("Level header %d: music", num)); } } + else if (fastcmp(word, "MUSICSLOT")) + deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num); else if (fastcmp(word, "MUSICTRACK")) mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1); else if (fastcmp(word, "MUSICPOS")) From 4713b258376da8120a27aa7422e3ab9cbcfa7f3c Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 16 Dec 2020 08:41:58 -0800 Subject: [PATCH 015/241] Bit array conflicts --- src/lua_hooklib.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 3a63e446e..7f5e3dc96 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -38,18 +38,6 @@ static const char * const stringHookNames[] = { STRING_HOOK_LIST (TOSTR) NULL }; -/* TODO: remove when doomtype version is merged */ - -#define BIT_ARRAY_LENGTH(n) (((n) + 7) >> 3) - -static inline void set_bit_array (UINT8 *array, const int n) { - array[n >> 3] |= 1 << (n & 7); -} - -static inline int in_bit_array (const UINT8 *array, const int n) { - return array[n >> 3] & (1 << (n & 7)); -} - typedef struct { int numHooks; int *ids; @@ -215,7 +203,7 @@ static int lib_addHook(lua_State *L) if (!(nextid & 7)) { Z_Realloc(hooksErrored, - BIT_ARRAY_LENGTH (nextid + 1) * sizeof *hooksErrored, + BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored, PU_STATIC, &hooksErrored); hooksErrored[nextid >> 3] = 0; } From 4717261459efb5861943cb46a65b0038b5b9eb3c Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Sat, 19 Dec 2020 17:32:45 -0300 Subject: [PATCH 016/241] Optimize Picture_GetPatchPixel --- src/r_picformats.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index f87362c76..eeebb94fd 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -540,9 +540,7 @@ void *Picture_GetPatchPixel( { fixed_t ofs; column_t *column; - UINT8 *s8 = NULL; - UINT16 *s16 = NULL; - UINT32 *s32 = NULL; + INT32 inbpp = Picture_FormatBPP(informat); softwarepatch_t *doompatch = (softwarepatch_t *)patch; boolean isdoompatch = Picture_IsDoomPatchFormat(informat); INT16 width; @@ -566,30 +564,36 @@ void *Picture_GetPatchPixel( while (column->topdelta != 0xff) { + UINT8 *s8 = NULL; + UINT16 *s16 = NULL; + UINT32 *s32 = NULL; + topdelta = column->topdelta; if (topdelta <= prevdelta) topdelta += prevdelta; prevdelta = topdelta; - s8 = (UINT8 *)(column) + 3; - if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) - s32 = (UINT32 *)s8; - else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) - s16 = (UINT16 *)s8; - for (ofs = 0; ofs < column->length; ofs++) + + ofs = (y - topdelta); + + if (y >= topdelta && ofs < column->length) { - if ((topdelta + ofs) == y) + s8 = (UINT8 *)(column) + 3; + switch (inbpp) { - if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) + case PICDEPTH_32BPP: + s32 = (UINT32 *)s8; return &s32[ofs]; - else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) + case PICDEPTH_16BPP: + s16 = (UINT16 *)s8; return &s16[ofs]; - else // PICDEPTH_8BPP + default: // PICDEPTH_8BPP return &s8[ofs]; } } - if (Picture_FormatBPP(informat) == PICDEPTH_32BPP) + + if (inbpp == PICDEPTH_32BPP) column = (column_t *)((UINT32 *)column + column->length); - else if (Picture_FormatBPP(informat) == PICDEPTH_16BPP) + else if (inbpp == PICDEPTH_16BPP) column = (column_t *)((UINT16 *)column + column->length); else column = (column_t *)((UINT8 *)column + column->length); From 50d46e1fa634abd6672ca6a8bf43daaec528fa80 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 27 Dec 2020 00:21:09 -0600 Subject: [PATCH 017/241] Set the target of a spawned ghost to where it came from. --- src/p_user.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index a70dceb8b..8361004d6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2016,6 +2016,8 @@ 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_SetScale(ghost, mobj->scale); ghost->destscale = mobj->scale; From ed82b94e64139a12d21376800cb123585f1ebc40 Mon Sep 17 00:00:00 2001 From: Hannu Hanhi Date: Tue, 29 Dec 2020 23:29:00 +0200 Subject: [PATCH 018/241] Take slopes into account in FOF wall cutoff in HWR_ProcessSeg --- src/hardware/hw_main.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index a7e37d231..5de6f8e11 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1104,7 +1104,6 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight) SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight) -#undef SLOPEPARAMS // hack to allow height changes in outdoor areas // This is what gets rid of the upper textures if there should be sky @@ -1589,14 +1588,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { ffloor_t * rover; fixed_t highcut = 0, lowcut = 0; + fixed_t lowcutslope, highcutslope; + + // Used for height comparisons and etc across FOFs and slopes + fixed_t high1, highslope1, low1, lowslope1; INT32 texnum; line_t * newline = NULL; // Multi-Property FOF - ///TODO add slope support (fixing cutoffs, proper wall clipping) - maybe just disable highcut/lowcut if either sector or FOF has a slope - /// to allow fun plane intersecting in OGL? But then people would abuse that and make software look bad. :C - highcut = gl_frontsector->ceilingheight < gl_backsector->ceilingheight ? gl_frontsector->ceilingheight : gl_backsector->ceilingheight; - lowcut = gl_frontsector->floorheight > gl_backsector->floorheight ? gl_frontsector->floorheight : gl_backsector->floorheight; + lowcut = max(worldbottom, worldlow); + highcut = min(worldtop, worldhigh); + lowcutslope = max(worldbottomslope, worldlowslope); + highcutslope = min(worldtopslope, worldhighslope); if (gl_backsector->ffloors) { @@ -1618,7 +1621,11 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom continue; if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES) continue; - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) + + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) + + if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture); @@ -1764,7 +1771,11 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom continue; if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) continue; - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) + + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) + + if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture); @@ -1856,6 +1867,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } } } +#undef SLOPEPARAMS //Hurdler: end of 3d-floors test } From c19539248aa02b64a4cb1c8ecebfde1d4c648eed Mon Sep 17 00:00:00 2001 From: katsy Date: Thu, 31 Dec 2020 04:38:26 -0600 Subject: [PATCH 019/241] add sprung flag to steam --- src/p_map.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_map.c b/src/p_map.c index b934e3255..7ca6d653a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -511,6 +511,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) if (spring->state != &states[S_STEAM1]) // Only when it bursts break; + object->eflags |= MFE_SPRUNG; object->momz = flipval*FixedMul(speed, FixedSqrt(FixedMul(spring->scale, object->scale))); // scale the speed with both objects' scales, just like with springs! if (p) From 3b4a52b8b85a7c17127f92423d90b273710ca04f Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Mon, 4 Jan 2021 00:03:18 -0600 Subject: [PATCH 020/241] Allows Lua to transport you to a different map in place of a Special Stage. --- src/g_game.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 6171c7b72..e204cdb2c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3920,12 +3920,13 @@ static void G_DoCompleted(void) { token--; - for (i = 0; i < 7; i++) - if (!(emeralds & (1< Date: Sun, 10 Jan 2021 20:52:03 +0200 Subject: [PATCH 021/241] Take slopes into account even more in FOF wall cutoff in HWR_ProcessSeg --- src/hardware/hw_main.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5de6f8e11..671a21017 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1641,10 +1641,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom hS = P_GetFFloorTopZAt (rover, v2x, v2y); l = P_GetFFloorBottomZAt(rover, v1x, v1y); lS = P_GetFFloorBottomZAt(rover, v2x, v2y); - if (!(*rover->t_slope) && !gl_frontsector->c_slope && !gl_backsector->c_slope && h > highcut) - h = hS = highcut; - if (!(*rover->b_slope) && !gl_frontsector->f_slope && !gl_backsector->f_slope && l < lowcut) - l = lS = lowcut; + // Adjust the heights so the FOF does not overlap with top and bottom textures. + if (h >= highcut && hS >= highcutslope) + { + h = highcut; + hS = highcutslope; + } + if (l <= lowcut && lS <= lowcutslope) + { + l = lowcut; + lS = lowcutslope; + } //Hurdler: HW code starts here //FIXME: check if peging is correct // set top/bottom coords @@ -1790,10 +1797,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom hS = P_GetFFloorTopZAt (rover, v2x, v2y); l = P_GetFFloorBottomZAt(rover, v1x, v1y); lS = P_GetFFloorBottomZAt(rover, v2x, v2y); - if (!(*rover->t_slope) && !gl_frontsector->c_slope && !gl_backsector->c_slope && h > highcut) - h = hS = highcut; - if (!(*rover->b_slope) && !gl_frontsector->f_slope && !gl_backsector->f_slope && l < lowcut) - l = lS = lowcut; + // Adjust the heights so the FOF does not overlap with top and bottom textures. + if (h >= highcut && hS >= highcutslope) + { + h = highcut; + hS = highcutslope; + } + if (l <= lowcut && lS <= lowcutslope) + { + l = lowcut; + lS = lowcutslope; + } //Hurdler: HW code starts here //FIXME: check if peging is correct // set top/bottom coords From 8aac7454b8a90dafe57e454ab98bdce5ddec67b5 Mon Sep 17 00:00:00 2001 From: Zippy_Zolton Date: Sun, 10 Jan 2021 17:20:07 -0600 Subject: [PATCH 022/241] Make Armageddon Shield instantly kill Egg Guards --- src/p_user.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index a70dceb8b..e2aa258e1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9009,8 +9009,11 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE))) mo->flags = (mo->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; - if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! + if (mo->type == MT_EGGGUARD && mo->tracer) // Egg Guard's shield needs to be removed if it has one! + { P_KillMobj(mo->tracer, inflictor, source, DMG_NUKE); + P_KillMobj(mo, inflictor, source, DMG_NUKE); + } if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players! P_DamageMobj(mo, inflictor, source, 1, DMG_NUKE); From d2be3110bda87db82ca9fe74fbb5c375af2c8f88 Mon Sep 17 00:00:00 2001 From: lachwright Date: Wed, 13 Jan 2021 22:28:38 +1100 Subject: [PATCH 023/241] Have Metal Sonic use spinheight while dashing --- src/p_user.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index a70dceb8b..a1bbe8d57 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8652,7 +8652,9 @@ void P_MovePlayer(player_t *player) || (player->pflags & PF_SPINNING) || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) - || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) + || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED) + || (player->dashmode >= DASHMODE_THRESHOLD && (player->charflags & SF_MACHINE) + && player->mo->state-states == S_PLAY_DASH && (player->mo->sprite2 & ~FF_SPR2SUPER) == player->mo->state->frame)) { player->mo->height = P_GetPlayerSpinHeight(player); atspinheight = true; From 149535634e757bb6bb833e18d866dc1005b63c0d Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 14 Jan 2021 04:24:48 +1100 Subject: [PATCH 024/241] Keep Metal's jet fume at a consistent height during dashmode --- src/p_user.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index a1bbe8d57..47d73ec2a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11357,6 +11357,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) mobj_t *mo = player->mo; angle_t angle = player->drawangle; fixed_t dist; + fixed_t playerheight = P_GetPlayerHeight(player); panim_t panim = player->panim; tic_t dashmode = player->dashmode; boolean underwater = mo->eflags & MFE_UNDERWATER; @@ -11390,7 +11391,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) 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 + (mo->height >> 1) + offsetV; + z = mo->z + (playerheight >> 1) + offsetV; P_SpawnMobj(x, y, z, MT_SMALLBUBBLE)->scale = mo->scale >> 1; } @@ -11453,7 +11454,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) P_UnsetThingPosition(fume); fume->x = mo->x + P_ReturnThrustX(fume, angle, dist); fume->y = mo->y + P_ReturnThrustY(fume, angle, dist); - fume->z = mo->z + ((mo->height - fume->height) >> 1); + fume->z = mo->z + ((playerheight - fume->height) >> 1); P_SetThingPosition(fume); // If dashmode is high enough, spawn a trail From a117ec98599f65b4836b05a33f63f281ef3a434f Mon Sep 17 00:00:00 2001 From: lachwright Date: Thu, 14 Jan 2021 04:34:43 +1100 Subject: [PATCH 025/241] oops that doesn't work in reverse gravity --- src/p_user.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 47d73ec2a..f2b7759fa 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11357,7 +11357,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) mobj_t *mo = player->mo; angle_t angle = player->drawangle; fixed_t dist; - fixed_t playerheight = P_GetPlayerHeight(player); + fixed_t heightoffset = ((mo->eflags & MFE_VERTICALFLIP) ? mo->height - (P_GetPlayerHeight(player) >> 1) : (P_GetPlayerHeight(player) >> 1)); panim_t panim = player->panim; tic_t dashmode = player->dashmode; boolean underwater = mo->eflags & MFE_UNDERWATER; @@ -11391,7 +11391,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) 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 + (playerheight >> 1) + offsetV; + z = mo->z + heightoffset + offsetV; P_SpawnMobj(x, y, z, MT_SMALLBUBBLE)->scale = mo->scale >> 1; } @@ -11454,7 +11454,7 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) P_UnsetThingPosition(fume); fume->x = mo->x + P_ReturnThrustX(fume, angle, dist); fume->y = mo->y + P_ReturnThrustY(fume, angle, dist); - fume->z = mo->z + ((playerheight - fume->height) >> 1); + fume->z = mo->z + heightoffset - (fume->height >> 1); P_SetThingPosition(fume); // If dashmode is high enough, spawn a trail From 794d92767032f718e6c31aa62f3125cd21b2511f Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 16:44:26 -0500 Subject: [PATCH 026/241] Add conditions for new player bot type --- src/p_inter.c | 64 ++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index e9a16a3dd..778ec703b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -151,7 +151,7 @@ boolean P_CanPickupItem(player_t *player, boolean weapon) if (!player->mo || player->mo->health <= 0) return false; - if (player->bot) + if (player->bot && player->bot != 3) { if (weapon) return false; @@ -178,7 +178,7 @@ void P_DoNightsScore(player_t *player) return; // Don't do any fancy shit for failures. dummymo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+player->mo->height/2, MT_NIGHTSCORE); - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; if (G_IsSpecialStage(gamemap)) // Global link count? Maybe not a good idea... @@ -470,14 +470,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) 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 { boolean underwater = toucher->eflags & MFE_UNDERWATER; - + if (underwater) toucher->momz /= 2; toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height! @@ -630,7 +630,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // ***************************** // // Special Stage Token case MT_TOKEN: - if (player->bot) + if (player->bot && player->bot != 3) return; P_AddPlayerScore(player, 1000); @@ -670,7 +670,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Emerald Hunt case MT_EMERHUNT: - if (player->bot) + if (player->bot && player->bot != 3) return; if (hunt1 == special) @@ -701,7 +701,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_EMERALD5: case MT_EMERALD6: case MT_EMERALD7: - if (player->bot) + if (player->bot && player->bot != 3) return; if (special->threshold) @@ -738,7 +738,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Secret emblem thingy case MT_EMBLEM: { - if (demoplayback || player->bot) + if (demoplayback || (player->bot && player->bot != 3)) return; emblemlocations[special->health-1].collected = true; @@ -751,7 +751,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // CTF Flags case MT_REDFLAG: case MT_BLUEFLAG: - if (player->bot) + if (player->bot && player->bot != 3) return; if (player->powers[pw_flashing] || player->tossdelay) return; @@ -826,7 +826,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { boolean spec = G_IsSpecialStage(gamemap); boolean cangiveemmy = false; - if (player->bot) + if (player->bot && player->bot != 3) return; if (player->exiting) return; @@ -1072,7 +1072,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; case MT_EGGCAPSULE: - if (player->bot) + if (player->bot && player->bot != 3) return; // make sure everything is as it should be, THEN take rings from players in special stages @@ -1164,7 +1164,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; case MT_NIGHTSSUPERLOOP: - if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) player->powers[pw_nights_superloop] = (UINT16)special->info->speed; @@ -1186,7 +1186,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSDRILLREFILL: - if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) player->drillmeter = special->info->speed; @@ -1208,7 +1208,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSHELPER: - if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1240,7 +1240,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSEXTRATIME: - if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1272,7 +1272,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSLINKFREEZE: - if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1332,7 +1332,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) players[i].drillmeter += TICRATE/2; } - else if (player->bot) + else if (player->bot && player->bot != 3) players[consoleplayer].drillmeter += TICRATE/2; else player->drillmeter += TICRATE/2; @@ -1385,13 +1385,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) thinker_t *th; mobj_t *mo2; - if (player->bot) + if (player->bot && player->bot != 3) return; - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - Tag_FSet(&junk.tags, LE_AXE); EV_DoElevator(&junk, bridgeFall, false); @@ -1423,7 +1419,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; } case MT_FIREFLOWER: - if (player->bot) + if (player->bot && player->bot != 3) return; S_StartSound(toucher, sfx_mario3); @@ -1617,7 +1613,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX)) macespin = true; - + if (macespin ? (player->powers[pw_ignorelatch] & (1<<15)) : (player->powers[pw_ignorelatch])) return; @@ -1685,7 +1681,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; // Only go in the mouth // Eaten by player! - if ((!player->bot) && (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)) + if ((!player->bot || player->bot == 3) && (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)) { player->powers[pw_underwater] = underwatertics + 1; P_RestoreMusic(player); @@ -1696,7 +1692,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!player->climbing) { - if (player->bot && toucher->state-states != S_PLAY_GASP) + if (player->bot && player->bot != 3 && toucher->state-states != S_PLAY_GASP) S_StartSound(toucher, special->info->deathsound); // Force it to play a sound for bots P_SetPlayerMobjState(toucher, S_PLAY_GASP); P_ResetPlayer(player); @@ -1704,7 +1700,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->momx = toucher->momy = toucher->momz = 0; - if (player->bot) + if (player->bot && player->bot != 3) return; else break; @@ -1736,7 +1732,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_MINECARTSPAWNER: - if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15))) + if (!player->bot && player->bot != 3 && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15))) { mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); P_SetTarget(&mcart->target, toucher); @@ -1789,7 +1785,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; default: // SOC or script pickup - if (player->bot) + if (player->bot && player->bot != 3) return; P_SetTarget(&special->target, toucher); break; @@ -1813,7 +1809,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) mobj_t *toucher = player->mo; mobj_t *checkbase = snaptopost ? post : toucher; - if (player->bot) + if (player->bot && player->bot != 3) return; // In circuit, player must have touched all previous starposts if (circuitmap @@ -2555,7 +2551,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0)) ; - else if (!target->player->bot && !target->player->spectator && (target->player->lives != INFLIVES) + else if ((!target->player->bot || target->player->bot == 3) && !target->player->spectator && (target->player->lives != INFLIVES) && G_GametypeUsesLives()) { if (!(target->player->pflags & PF_FINISHED)) @@ -3475,7 +3471,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (inflictor && inflictor->type == MT_LHRT) return; - if (player->powers[pw_shield] || player->bot) //If One-Hit Shield + if (player->powers[pw_shield] || (player->bot && player->bot != 3)) //If One-Hit Shield { P_RemoveShield(player); S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss. @@ -3566,7 +3562,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Make sure that boxes cannot be popped by enemies, red rings, etc. - if (target->flags & MF_MONITOR && ((!source || !source->player || source->player->bot) + if (target->flags & MF_MONITOR && ((!source || !source->player || (source->player->bot && source->player->bot != 3)) || (inflictor && (inflictor->type == MT_REDRING || (inflictor->type >= MT_THROWNBOUNCE && inflictor->type <= MT_THROWNGRENADE))))) return false; } @@ -3701,7 +3697,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) return true; - else if (player->powers[pw_shield] || (player->bot && !ultimatemode)) //If One-Hit Shield + else if (player->powers[pw_shield] || (player->bot && player->bot != 3 && !ultimatemode)) //If One-Hit Shield { P_ShieldDamage(player, inflictor, source, damage, damagetype); damage = 0; From 4b9a95a53837166a080b200b34982ce867a31ffd Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 16:46:15 -0500 Subject: [PATCH 027/241] Add conditions for new player bot type --- src/p_enemy.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 203e04af1..38df59855 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -743,7 +743,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if (player->mo->health <= 0) continue; // dead - if (player->bot) + if (player->bot && player->bot != 3) continue; // ignore bots if (player->quittime) @@ -1834,7 +1834,7 @@ void A_SnailerThink(mobj_t *actor) fixed_t dist; fixed_t dx, dy; - dist = R_PointToDist2(0, 0, actor->x - actor->target->x, actor->y - actor->target->y); + dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); if (an > ANGLE_45 && an <= ANGLE_90) // fire at 45 degrees to the left { @@ -3924,10 +3924,6 @@ void A_BossDeath(mobj_t *mo) } else { - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - // Bring the egg trap up to the surface // Incredibly shitty code ahead Tag_FSet(&junk.tags, LE_CAPSULE0); @@ -4057,10 +4053,6 @@ bossjustdie: } case MT_KOOPA: { - // Initialize my junk - junk.tags.tags = NULL; - junk.tags.count = 0; - Tag_FSet(&junk.tags, LE_KOOPA); EV_DoCeiling(&junk, raiseToHighest); return; From b995e3cb75b67116d51583c1ae85debf25013621 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 16:48:19 -0500 Subject: [PATCH 028/241] Add conditions for new player bot type --- src/p_user.c | 125 ++++++++++++++++++++------------------------------- 1 file changed, 48 insertions(+), 77 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index a70dceb8b..2466310bb 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1189,7 +1189,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) if (!player) return; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; if (!player->mo) @@ -1234,7 +1234,7 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres) if (!player) return; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; if (!player->mo) @@ -1261,7 +1261,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) if (!player) return; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; if (gamestate == GS_LEVEL) @@ -1341,7 +1341,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) // Transformation animation P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1); - if (giverings && player->rings < 50) + if (giverings) player->rings = 50; // Just in case. @@ -1367,7 +1367,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) { UINT32 oldscore; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; // NiGHTS does it different! @@ -1491,10 +1491,10 @@ void P_PlayLivesJingle(player_t *player) if (player && !P_IsLocalPlayer(player)) return; - if (mariomode) - S_StartSound(NULL, sfx_marioa); - else if (use1upSound || cv_1upsound.value) + if (use1upSound || cv_1upsound.value) S_StartSound(NULL, sfx_oneup); + else if (mariomode) + S_StartSound(NULL, sfx_marioa); else { P_PlayJingle(player, JT_1UP); @@ -2329,8 +2329,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) P_MobjCheckWater(player->mo); if (player->pflags & PF_SPINNING) { - if (!(player->pflags & PF_STARTDASH) && player->panim != PA_ROLL && player->panim != PA_ETC - && player->panim != PA_ABILITY && player->panim != PA_ABILITY2) + if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) { P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_spin); @@ -2613,10 +2612,10 @@ static void P_CheckBustableBlocks(player_t *player) if ((netgame || multiplayer) && player->spectator) return; - + oldx = player->mo->x; oldy = player->mo->y; - + if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways { P_UnsetThingPosition(player->mo); @@ -2635,7 +2634,7 @@ static void P_CheckBustableBlocks(player_t *player) if (!node->m_sector->ffloors) continue; - + for (rover = node->m_sector->ffloors; rover; rover = rover->next) { if (!P_PlayerCanBust(player, rover)) @@ -2993,7 +2992,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) player->powers[pw_spacetime] = 0; // Underwater audio cues - if (P_IsLocalPlayer(player) && !player->bot) + if (P_IsLocalPlayer(player) && !player->bot && player->bot != 3) { if ((player->powers[pw_underwater] == 25*TICRATE + 1) || (player->powers[pw_underwater] == 20*TICRATE + 1) @@ -4526,9 +4525,6 @@ void P_DoJump(player_t *player, boolean soundandstate) player->pflags |= P_GetJumpFlags(player);; - if (player->charflags & SF_NOJUMPDAMAGE) - player->pflags &= ~PF_SPINNING; - if (soundandstate) { if (!player->spectator) @@ -5024,7 +5020,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN) && ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && !(player->charflags & SF_NOSHIELDABILITY)) + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) { if ((lockonshield = P_LookForEnemies(player, false, false))) { @@ -5047,7 +5043,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player))) // Spin button effects + if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5495,7 +5491,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; } } - else if ((!(player->charflags & SF_NOSHIELDABILITY)) && ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super] && !LUAh_ShieldSpecial(player))) + else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super]) P_DoJumpShield(player); } @@ -5924,7 +5920,7 @@ static void P_3dMovement(player_t *player) player->rmomy = player->mo->momy - player->cmomy; // Calculates player's speed based on distance-of-a-line formula - player->speed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); + player->speed = P_AproxDistance(player->rmomx, player->rmomy); // Monster Iestyn - 04-11-13 // Quadrants are stupid, excessive and broken, let's do this a much simpler way! @@ -5957,22 +5953,6 @@ static void P_3dMovement(player_t *player) acceleration = 96 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * 40; topspeed = normalspd; } - else if (player->bot) - { // Bot steals player 1's stats - normalspd = FixedMul(players[consoleplayer].normalspeed, player->mo->scale); - thrustfactor = players[consoleplayer].thrustfactor; - acceleration = players[consoleplayer].accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * players[consoleplayer].acceleration; - - if (player->powers[pw_tailsfly]) - topspeed = normalspd/2; - else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER)) - { - topspeed = normalspd/2; - acceleration = 2*acceleration/3; - } - else - topspeed = normalspd; - } else { if (player->powers[pw_super] || player->powers[pw_sneakers]) @@ -7756,11 +7736,6 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale)); P_SetObjectMomZ(flame, 3*FRACUNIT, false); - if (!(gametyperules & GTR_FRIENDLY)) - { - P_SetMobjState(flame, S_TEAM_SPINFIRE1); - flame->color = player->mo->color; - } } #undef limitangle #undef numangles @@ -7788,11 +7763,6 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); - if (!(gametyperules & GTR_FRIENDLY)) - { - P_SetMobjState(flame, S_TEAM_SPINFIRE1); - flame->color = player->mo->color; - } flame->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others P_XYMovement(flame); @@ -8619,6 +8589,12 @@ void P_MovePlayer(player_t *player) player->climbing--; } + if (!player->climbing) + { + player->lastsidehit = -1; + player->lastlinehit = -1; + } + // Make sure you're not teetering when you shouldn't be. if (player->panim == PA_EDGE && (player->mo->momx || player->mo->momy || player->mo->momz)) @@ -8643,7 +8619,6 @@ void P_MovePlayer(player_t *player) P_DoFiring(player, cmd); { - boolean atspinheight = false; fixed_t oldheight = player->mo->height; // Less height while spinning. Good for spinning under things...? @@ -8653,35 +8628,32 @@ void P_MovePlayer(player_t *player) || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) - { player->mo->height = P_GetPlayerSpinHeight(player); - atspinheight = true; - } else player->mo->height = P_GetPlayerHeight(player); if (player->mo->eflags & MFE_VERTICALFLIP && player->mo->height != oldheight) // adjust z height for reverse gravity, similar to how it's done for scaling player->mo->z -= player->mo->height - oldheight; + } - // Crush test... - if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) - && !(player->mo->flags & MF_NOCLIP)) + // Crush test... + if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) + && !(player->mo->flags & MF_NOCLIP)) + { + if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SPINNING)) { - if (!atspinheight) - { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - } - else if (player->mo->ceilingz - player->mo->floorz < player->mo->height) - { - if ((netgame || multiplayer) && player->spectator) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators - else - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED); + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + } + else if (player->mo->ceilingz - player->mo->floorz < player->mo->height) + { + if ((netgame || multiplayer) && player->spectator) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators + else + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED); - if (player->playerstate == PST_DEAD) - return; - } + if (player->playerstate == PST_DEAD) + return; } } @@ -9497,11 +9469,11 @@ static void P_DeathThink(player_t *player) if (player->deadtimer < INT32_MAX) player->deadtimer++; - if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already + if (player->bot && player->bot != 3) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already goto notrealplayer; // continue logic - if (!(netgame || multiplayer) && player->lives <= 0) + if (!(netgame || multiplayer) && player->lives <= 0 && player ==&players[consoleplayer]) //Extra players in SP can't be allowed to continue or end game { if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_SPIN || cmd->buttons & BT_JUMP) && (!continuesInSession || player->continues > 0)) G_UseContinue(); @@ -11480,7 +11452,7 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } - if (player->bot) + if (player->bot && player->bot != 3) { if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD) { @@ -11494,6 +11466,7 @@ void P_PlayerThink(player_t *player) } } +#ifdef SEENAMES if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5))) { seenplayer = NULL; @@ -11518,6 +11491,7 @@ void P_PlayerThink(player_t *player) } } } +#endif if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { @@ -12588,16 +12562,13 @@ void P_PlayerAfterThink(player_t *player) player->powers[pw_carry] = CR_NONE; else { - if (tails->player) - P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); - else - P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true); + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); player->mo->momx = tails->momx; player->mo->momy = tails->momy; player->mo->momz = tails->momz; } - if (G_CoopGametype() && tails->player && tails->player->bot != 1) + if (G_CoopGametype() && (!tails->player || tails->player->bot != 1)) { player->mo->angle = tails->angle; @@ -12612,7 +12583,7 @@ void P_PlayerAfterThink(player_t *player) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); - if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) + if ((tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) tails->player->powers[pw_tailsfly] = 0; } else From 5e8313e157ab0bef4f2e2a346906aa1a6efdd58b Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 16:50:01 -0500 Subject: [PATCH 029/241] Implementation of lua function P_AddPlayer() --- src/lua_baselib.c | 89 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index c5f847be6..9bc8813a2 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -155,8 +155,6 @@ static const struct { {META_PIVOTLIST, "spriteframepivot_t[]"}, {META_FRAMEPIVOT, "spriteframepivot_t"}, - {META_TAGLIST, "taglist"}, - {META_MOBJ, "mobj_t"}, {META_MAPTHING, "mapthing_t"}, @@ -165,8 +163,6 @@ static const struct { {META_SKIN, "skin_t"}, {META_POWERS, "player_t.powers"}, {META_SOUNDSID, "skin_t.soundsid"}, - {META_SKINSPRITES, "skin_t.sprites"}, - {META_SKINSPRITESLIST, "skin_t.sprites[]"}, {META_VERTEX, "vertex_t"}, {META_LINE, "line_t"}, @@ -188,9 +184,6 @@ static const struct { {META_CVAR, "consvar_t"}, {META_SECTORLINES, "sector_t.lines"}, -#ifdef MUTABLE_TAGS - {META_SECTORTAGLIST, "sector_t.taglist"}, -#endif {META_SIDENUM, "line_t.sidenum"}, {META_LINEARGS, "line_t.args"}, {META_LINESTRINGARGS, "line_t.stringargs"}, @@ -2639,7 +2632,7 @@ static int lib_rSkinUsable(lua_State *L) else // skin name { const char *skinname = luaL_checkstring(L, 2); - i = R_SkinAvailable(skinname); + if (R_SkinAvailable(skinname) >= 0) if (i == -1) return luaL_error(L, "skin %s (argument 2) is not loaded", skinname); } @@ -3407,6 +3400,85 @@ static int lib_gAddGametype(lua_State *L) return 0; } +// Bot adding function! +// Partly lifted from Got_AddPlayer +static int lib_gAddPlayer(lua_State *L) +{ + INT16 i, newplayernum, botcount = 1; + player_t *newplayer; + INT8 skinnum = 0, bot; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + break; + + if (players[i].bot) + botcount++; // How many of us are there already? + } + if (i >= MAXPLAYERS) + { + lua_pushnil(L); + return 1; + } + + + newplayernum = i; + + //if (!splitscreen && !botingame) + CL_ClearPlayer(newplayernum); + + playeringame[newplayernum] = true; + G_AddPlayer(newplayernum); + newplayer = &players[newplayernum]; + + newplayer->jointime = 0; + newplayer->quittime = 0; + + // I hereby name you Bot X + strcpy(player_names[newplayernum], va("Bot %d", botcount)); + + // Read the skin string! + if (!lua_isnoneornil(L, 1)) + { + skinnum = R_SkinAvailable(luaL_checkstring(L, 1)); + skinnum = skinnum < 0 ? 0 : skinnum; + + // Bots can be whatever they want + if (!R_SkinUsable(newplayernum, skinnum)) + newplayer->availabilities |= 1 << skinnum; + } + + // Read the color! + if (!lua_isnoneornil(L, 2)) + newplayer->skincolor = R_GetColorByName(luaL_checkstring(L, 2)); + else + newplayer->skincolor = skins[newplayer->skin].prefcolor; + + // Read the bot name, if given! + if (!lua_isnoneornil(L, 3)) + strcpy(player_names[newplayernum], luaL_checkstring(L, 3)); + + bot = luaL_optinteger(L, 4, 3); + newplayer->bot = (bot >= 0 && bot <= 3) ? bot : 3; + + // Set the skin + SetPlayerSkinByNum(newplayernum, skinnum); + + + if (netgame) + { + char joinmsg[256]; + + 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); + } + + LUA_PushUserdata(L, newplayer, META_PLAYER); + return 0; +} + static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) { if (ISINLEVEL) @@ -3987,6 +4059,7 @@ static luaL_Reg lib[] = { // g_game {"G_AddGametype", lib_gAddGametype}, + {"G_AddPlayer", lib_gAddPlayer}, {"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_FindMap",lib_gFindMap}, From 9eeaef2e32c90d2c23a314c2cd99a0b72dde0f0a Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 16:55:49 -0500 Subject: [PATCH 030/241] Exception made in R_SkinUsable() for player bot types --- src/r_skins.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/r_skins.c b/src/r_skins.c index 6f150f234..155a64700 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -198,6 +198,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. || (netgame && (cv_forceskin.value == skinnum)) // Force 2. || (metalrecording && skinnum == 5) // Force 3. + || players[playernum].bot //Force (player is a bot) ); } @@ -511,10 +512,6 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETFLAG(MULTIABILITY) GETFLAG(NONIGHTSROTATION) GETFLAG(NONIGHTSSUPER) - GETFLAG(NOSUPERSPRITES) - GETFLAG(NOSUPERJUMPBOOST) - GETFLAG(CANBUSTWALLS) - GETFLAG(NOSHIELDABILITY) #undef GETFLAG else // let's check if it's a sound, otherwise error out From f166af4d8b7805e1ce5688cbef386f6ddc6e3ec1 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:00:21 -0500 Subject: [PATCH 031/241] CL_RemovePlayer() - Allow for removal of non-consoleplayer and non-secondaryviewplayer player instances (e.g. bot players) --- src/r_skins.c | 5748 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 5019 insertions(+), 729 deletions(-) diff --git a/src/r_skins.c b/src/r_skins.c index 155a64700..88b4d9387 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -1,6 +1,5 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2020 by Sonic Team Junior. // @@ -8,826 +7,5117 @@ // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file r_skins.c -/// \brief Loading skins +/// \file d_clisrv.c +/// \brief SRB2 Network game communication and protocol, all OS independent parts. -#include "doomdef.h" -#include "console.h" -#include "g_game.h" -#include "r_local.h" -#include "st_stuff.h" -#include "w_wad.h" -#include "z_zone.h" -#include "m_misc.h" -#include "info.h" // spr2names -#include "i_video.h" // rendermode +#include +#ifdef __GNUC__ +#include //for unlink +#endif + +#include "i_net.h" #include "i_system.h" -#include "r_things.h" -#include "r_skins.h" +#include "i_video.h" +#include "d_net.h" +#include "d_main.h" +#include "g_game.h" +#include "st_stuff.h" +#include "hu_stuff.h" +#include "keys.h" +#include "g_input.h" // JOY1 +#include "m_menu.h" +#include "console.h" +#include "d_netfil.h" +#include "byteptr.h" +#include "p_saveg.h" +#include "z_zone.h" #include "p_local.h" -#include "dehacked.h" // get_number (for thok) -#include "m_cond.h" -#ifdef HWRENDER -#include "hardware/hw_md2.h" -#endif +#include "m_misc.h" +#include "am_map.h" +#include "m_random.h" +#include "mserv.h" +#include "y_inter.h" +#include "r_local.h" +#include "m_argv.h" +#include "p_setup.h" +#include "lzf.h" +#include "lua_script.h" +#include "lua_hook.h" +#include "md5.h" +#include "m_perfstats.h" -INT32 numskins = 0; -skin_t skins[MAXSKINS]; - -// FIXTHIS: don't work because it must be inistilised before the config load -//#define SKINVALUES -#ifdef SKINVALUES -CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; +#ifndef NONET +// cl loading screen +#include "v_video.h" +#include "f_finale.h" #endif // -// P_GetSkinSprite2 -// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. -// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. +// NETWORKING // +// gametic is the tic about to (or currently being) run +// Server: +// maketic is the tic that hasn't had control made for it yet +// nettics is the tic for each node +// firstticstosend is the lowest value of nettics +// Client: +// neededtic is the tic needed by the client to run the game +// firstticstosend is used to optimize a condition +// Normally maketic >= gametic > 0 -UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) +#define PREDICTIONQUEUE BACKUPTICS +#define PREDICTIONMASK (PREDICTIONQUEUE-1) +#define MAX_REASONLENGTH 30 + +boolean server = true; // true or false but !server == client +#define client (!server) +boolean nodownload = false; +boolean serverrunning = false; +INT32 serverplayer = 0; +char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support) + +// Server specific vars +UINT8 playernode[MAXPLAYERS]; +char playeraddress[MAXPLAYERS][64]; + +// Minimum timeout for sending the savegame +// The actual timeout will be longer depending on the savegame length +tic_t jointimeout = (10*TICRATE); +static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame? +static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame? +static tic_t savegameresendcooldown[MAXNETNODES]; // How long before we can resend again? +static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout? + +// Incremented by cv_joindelay when a client joins, decremented each tic. +// If higher than cv_joindelay * 2 (3 joins in a short timespan), joins are temporarily disabled. +static tic_t joindelay = 0; + +UINT16 pingmeasurecount = 1; +UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. +UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. +SINT8 nodetoplayer[MAXNETNODES]; +SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) +UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen +boolean nodeingame[MAXNETNODES]; // set false as nodes leave game +tic_t servermaxping = 800; // server's max ping. Defaults to 800 +static tic_t nettics[MAXNETNODES]; // what tic the client have received +static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet +static UINT8 nodewaiting[MAXNETNODES]; +static tic_t firstticstosend; // min of the nettics +static tic_t tictoclear = 0; // optimize d_clearticcmd +static tic_t maketic; + +static INT16 consistancy[BACKUPTICS]; + +static UINT8 player_joining = false; +UINT8 hu_redownloadinggamestate = 0; + +UINT8 adminpassmd5[16]; +boolean adminpasswordset = false; + +// Client specific +static ticcmd_t localcmds; +static ticcmd_t localcmds2; +static boolean cl_packetmissed; +// here it is for the secondary local player (splitscreen) +static UINT8 mynode; // my address pointofview server +static boolean cl_redownloadinggamestate = false; + +static UINT8 localtextcmd[MAXTEXTCMD]; +static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen +static tic_t neededtic; +SINT8 servernode = 0; // the number of the server node +/// \brief do we accept new players? +/// \todo WORK! +boolean acceptnewnode = true; + +// engine + +// Must be a power of two +#define TEXTCMD_HASH_SIZE 4 + +typedef struct textcmdplayer_s { - UINT8 super = 0, i = 0; + INT32 playernum; + UINT8 cmd[MAXTEXTCMD]; + struct textcmdplayer_s *next; +} textcmdplayer_t; - if (!skin) - return 0; +typedef struct textcmdtic_s +{ + tic_t tic; + textcmdplayer_t *playercmds[TEXTCMD_HASH_SIZE]; + struct textcmdtic_s *next; +} textcmdtic_t; - if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) - return 0; +ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; +static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; - while (!skin->sprites[spr2].numframes - && spr2 != SPR2_STND - && ++i < 32) // recursion limiter - { - if (spr2 & FF_SPR2SUPER) - { - super = FF_SPR2SUPER; - spr2 &= ~FF_SPR2SUPER; - continue; - } - switch(spr2) - { - // Normal special cases. - case SPR2_JUMP: - spr2 = ((player - ? player->charflags - : skin->flags) - & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; - break; - case SPR2_TIRE: - spr2 = ((player - ? player->charability - : skin->ability) - == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; - break; - // Use the handy list, that's what it's there for! - default: - spr2 = spr2defaults[spr2]; - break; - } +consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - spr2 |= super; - } +static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; +consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); - if (i >= 32) // probably an infinite loop... - return 0; +static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n) +{ + const size_t d = n / sizeof(ticcmd_t); + const size_t r = n % sizeof(ticcmd_t); + UINT8 *ret = dest; - return spr2; + if (r) + M_Memcpy(dest, src, n); + else if (d) + G_MoveTiccmd(dest, src, d); + return ret+n; } -static void Sk_SetDefaultValue(skin_t *skin) +static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n) { - INT32 i; - // - // set default skin values - // - memset(skin, 0, sizeof (skin_t)); - snprintf(skin->name, - sizeof skin->name, "skin %u", (UINT32)(skin-skins)); - skin->name[sizeof skin->name - 1] = '\0'; - skin->wadnum = INT16_MAX; + const size_t d = n / sizeof(ticcmd_t); + const size_t r = n % sizeof(ticcmd_t); + UINT8 *ret = src; - skin->flags = 0; - - strcpy(skin->realname, "Someone"); - strcpy(skin->hudname, "???"); - - skin->starttranscolor = 96; - skin->prefcolor = SKINCOLOR_GREEN; - skin->supercolor = SKINCOLOR_SUPERGOLD1; - skin->prefoppositecolor = 0; // use tables - - skin->normalspeed = 36<runspeed = 28<thrustfactor = 5; - skin->accelstart = 96; - skin->acceleration = 40; - - skin->ability = CA_NONE; - skin->ability2 = CA2_SPINDASH; - skin->jumpfactor = FRACUNIT; - skin->actionspd = 30<mindash = 15<maxdash = 70<radius = mobjinfo[MT_PLAYER].radius; - skin->height = mobjinfo[MT_PLAYER].height; - skin->spinheight = FixedMul(skin->height, 2*FRACUNIT/3); - - skin->shieldscale = FRACUNIT; - skin->camerascale = FRACUNIT; - - skin->thokitem = -1; - skin->spinitem = -1; - skin->revitem = -1; - skin->followitem = 0; - - skin->highresscale = FRACUNIT; - skin->contspeed = 17; - skin->contangle = 0; - - skin->availability = 0; - - for (i = 0; i < sfx_skinsoundslot0; i++) - if (S_sfx[i].skinsound != -1) - skin->soundsid[S_sfx[i].skinsound] = i; + if (r) + M_Memcpy(dest, src, n); + else if (d) + G_MoveTiccmd(dest, src, d); + return ret+n; } -// -// Initialize the basic skins -// -void R_InitSkins(void) -{ -#ifdef SKINVALUES - INT32 i; - for (i = 0; i <= MAXSKINS; i++) - { - skin_cons_t[i].value = 0; - skin_cons_t[i].strvalue = NULL; - } + +// Some software don't support largest packet +// (original sersetup, not exactely, but the probability of sending a packet +// of 512 bytes is like 0.1) +UINT16 software_MAXPACKETLENGTH; + +/** Guesses the full value of a tic from its lowest byte, for a specific node + * + * \param low The lowest byte of the tic value + * \param node The node to deduce the tic for + * \return The full tic value + * + */ +tic_t ExpandTics(INT32 low, INT32 node) +{ + INT32 delta; + + delta = low - (nettics[node] & UINT8_MAX); + + if (delta >= -64 && delta <= 64) + return (nettics[node] & ~UINT8_MAX) + low; + else if (delta > 64) + return (nettics[node] & ~UINT8_MAX) - 256 + low; + else //if (delta < -64) + return (nettics[node] & ~UINT8_MAX) + 256 + low; +} + +// ----------------------------------------------------------------- +// Some extra data function for handle textcmd buffer +// ----------------------------------------------------------------- + +static void (*listnetxcmd[MAXNETXCMD])(UINT8 **p, INT32 playernum); + +void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) +{ +#ifdef PARANOIA + if (id >= MAXNETXCMD) + I_Error("Command id %d too big", id); + if (listnetxcmd[id] != 0) + I_Error("Command id %d already used", id); #endif - - // no default skin! - numskins = 0; + listnetxcmd[id] = cmd_f; } -UINT32 R_GetSkinAvailabilities(void) +void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam) { - INT32 s; - UINT32 response = 0; - - for (s = 0; s < MAXSKINS; s++) + if (localtextcmd[0]+2+nparam > MAXTEXTCMD) { - if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) - response |= (1 << s); - } - return response; -} - -// returns true if available in circumstances, otherwise nope -// warning don't use with an invalid skinnum other than -1 which always returns true -boolean R_SkinUsable(INT32 playernum, INT32 skinnum) -{ - return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... - || (!skins[skinnum].availability) - || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) - || (modeattacking) // If you have someone else's run you might as well take a look - || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. - || (netgame && (cv_forceskin.value == skinnum)) // Force 2. - || (metalrecording && skinnum == 5) // Force 3. - || players[playernum].bot //Force (player is a bot) - ); -} - -// returns true if the skin name is found (loaded from pwad) -// warning return -1 if not found -INT32 R_SkinAvailable(const char *name) -{ - INT32 i; - - for (i = 0; i < numskins; i++) - { - // search in the skin list - if (stricmp(skins[i].name,name)==0) - return i; - } - return -1; -} - -// network code calls this when a 'skin change' is received -void SetPlayerSkin(INT32 playernum, const char *skinname) -{ - INT32 i = R_SkinAvailable(skinname); - player_t *player = &players[playernum]; - - if ((i != -1) && R_SkinUsable(playernum, i)) - { - SetPlayerSkinByNum(playernum, i); + // for future reference: if (cv_debug) != debug disabled. + CONS_Alert(CONS_ERROR, M_GetText("NetXCmd buffer full, cannot add netcmd %d! (size: %d, needed: %s)\n"), id, localtextcmd[0], sizeu1(nparam)); return; } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); - - SetPlayerSkinByNum(playernum, 0); + localtextcmd[0]++; + localtextcmd[localtextcmd[0]] = (UINT8)id; + if (param && nparam) + { + M_Memcpy(&localtextcmd[localtextcmd[0]+1], param, nparam); + localtextcmd[0] = (UINT8)(localtextcmd[0] + (UINT8)nparam); + } } -// Same as SetPlayerSkin, but uses the skin #. -// network code calls this when a 'skin change' is received -void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) +// splitscreen player +void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) { - player_t *player = &players[playernum]; - skin_t *skin = &skins[skinnum]; - UINT16 newcolor = 0; - - if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists! + if (localtextcmd2[0]+2+nparam > MAXTEXTCMD) { - player->skin = skinnum; + I_Error("No more place in the buffer for netcmd %d\n",id); + return; + } + localtextcmd2[0]++; + localtextcmd2[localtextcmd2[0]] = (UINT8)id; + if (param && nparam) + { + M_Memcpy(&localtextcmd2[localtextcmd2[0]+1], param, nparam); + localtextcmd2[0] = (UINT8)(localtextcmd2[0] + (UINT8)nparam); + } +} - player->camerascale = skin->camerascale; - player->shieldscale = skin->shieldscale; +UINT8 GetFreeXCmdSize(void) +{ + // -1 for the size and another -1 for the ID. + return (UINT8)(localtextcmd[0] - 2); +} - player->charability = (UINT8)skin->ability; - player->charability2 = (UINT8)skin->ability2; +// Frees all textcmd memory for the specified tic +static void D_FreeTextcmd(tic_t tic) +{ + textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + textcmdtic_t *textcmdtic = *tctprev; - player->charflags = (UINT32)skin->flags; + while (textcmdtic && textcmdtic->tic != tic) + { + tctprev = &textcmdtic->next; + textcmdtic = textcmdtic->next; + } - player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; - player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; - player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; - player->followitem = skin->followitem; + if (textcmdtic) + { + INT32 i; - if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff. - player->powers[pw_shield] &= SH_STACK; + // Remove this tic from the list. + *tctprev = textcmdtic->next; - player->actionspd = skin->actionspd; - player->mindash = skin->mindash; - player->maxdash = skin->maxdash; - - player->normalspeed = skin->normalspeed; - player->runspeed = skin->runspeed; - player->thrustfactor = skin->thrustfactor; - player->accelstart = skin->accelstart; - player->acceleration = skin->acceleration; - - player->jumpfactor = skin->jumpfactor; - - player->height = skin->height; - player->spinheight = skin->spinheight; - - if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) + // Free all players. + for (i = 0; i < TEXTCMD_HASH_SIZE; i++) { - if (playernum == consoleplayer) - CV_StealthSetValue(&cv_playercolor, skin->prefcolor); - else if (playernum == secondarydisplayplayer) - CV_StealthSetValue(&cv_playercolor2, skin->prefcolor); - player->skincolor = newcolor = skin->prefcolor; - if (player->bot && botingame) + textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i]; + + while (textcmdplayer) { - botskin = (UINT8)(skinnum + 1); - botcolor = skin->prefcolor; + textcmdplayer_t *tcpnext = textcmdplayer->next; + Z_Free(textcmdplayer); + textcmdplayer = tcpnext; } } - if (player->followmobj) - { - P_RemoveMobj(player->followmobj); - P_SetTarget(&player->followmobj, NULL); - } - - if (player->mo) - { - fixed_t radius = FixedMul(skin->radius, player->mo->scale); - if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. - { - skin = &skins[DEFAULTNIGHTSSKIN]; - player->followitem = skin->followitem; - if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) - newcolor = skin->prefcolor; // will be updated in thinker to flashing - } - player->mo->skin = skin; - if (newcolor) - player->mo->color = newcolor; - P_SetScale(player->mo, player->mo->scale); - player->mo->radius = radius; - - P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames - } - return; + // Free this tic's own memory. + Z_Free(textcmdtic); } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); - SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin } -// -// Add skins from a pwad, each skin preceded by 'S_SKIN' marker -// - -// Does the same is in w_wad, but check only for -// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2.. -// for wad editors that don't like multiple resources of the same name) -// -static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +// Gets the buffer for the specified ticcmd, or NULL if there isn't one +static UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) { - UINT16 i; - const char *S_SKIN = "S_SKIN"; - lumpinfo_t *lump_p; + textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + while (textcmdtic && textcmdtic->tic != tic) textcmdtic = textcmdtic->next; - // scan forward, start at - if (startlump < wadfiles[wadid]->numlumps) + // Do we have an entry for the tic? If so, look for player. + if (textcmdtic) { - 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) - return i; + textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; + while (textcmdplayer && textcmdplayer->playernum != playernum) textcmdplayer = textcmdplayer->next; + + if (textcmdplayer) return textcmdplayer->cmd; } - return INT16_MAX; // not found + + return NULL; } -#define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value) +// Gets the buffer for the specified ticcmd, creating one if necessary +static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) +{ + textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; + textcmdplayer_t *textcmdplayer, **tcpprev; -// turn _ into spaces and . into katana dot -#define SYMBOLCONVERT(name) for (value = name; *value; value++)\ - {\ - if (*value == '_') *value = ' ';\ - else if (*value == '.') *value = '\x1E';\ + // Look for the tic. + while (textcmdtic && textcmdtic->tic != tic) + { + tctprev = &textcmdtic->next; + textcmdtic = textcmdtic->next; + } + + // If we don't have an entry for the tic, make it. + if (!textcmdtic) + { + textcmdtic = *tctprev = Z_Calloc(sizeof (textcmdtic_t), PU_STATIC, NULL); + textcmdtic->tic = tic; + } + + tcpprev = &textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; + textcmdplayer = *tcpprev; + + // Look for the player. + while (textcmdplayer && textcmdplayer->playernum != playernum) + { + tcpprev = &textcmdplayer->next; + textcmdplayer = textcmdplayer->next; + } + + // If we don't have an entry for the player, make it. + if (!textcmdplayer) + { + textcmdplayer = *tcpprev = Z_Calloc(sizeof (textcmdplayer_t), PU_STATIC, NULL); + textcmdplayer->playernum = playernum; + } + + return textcmdplayer->cmd; +} + +static void ExtraDataTicker(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] || i == 0) + { + UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); + + if (bufferstart) + { + UINT8 *curpos = bufferstart; + UINT8 *bufferend = &curpos[curpos[0]+1]; + + curpos++; + while (curpos < bufferend) + { + if (*curpos < MAXNETXCMD && listnetxcmd[*curpos]) + { + const UINT8 id = *curpos; + curpos++; + DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i)); + (listnetxcmd[id])(&curpos, i); + DEBFILE("done\n"); } - -// -// Patch skins from a pwad, each skin preceded by 'P_SKIN' marker -// - -// Does the same is in w_wad, but check only for -// the first 6 characters (this is so we can have P_SKIN1, P_SKIN2.. -// for wad editors that don't like multiple resources of the same name) -// -static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) -{ - UINT16 i; - 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,P_SKIN,6)==0) - return i; - } - return INT16_MAX; // not found -} - -static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin) -{ - UINT16 newlastlump; - UINT8 sprite2; - - *lump += 1; // start after S_SKIN - *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END - - // old wadding practices die hard -- stop at S_SKIN (or P_SKIN) or S_START if they come before S_END. - newlastlump = W_CheckForSkinMarkerInPwad(wadnum,*lump); - if (newlastlump < *lastlump) *lastlump = newlastlump; - newlastlump = W_CheckForPatchSkinMarkerInPwad(wadnum,*lump); - if (newlastlump < *lastlump) *lastlump = newlastlump; - newlastlump = W_CheckNumForNamePwad("S_START",wadnum,*lump); - if (newlastlump < *lastlump) *lastlump = newlastlump; - - // ...and let's handle super, too - newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,*lump); - if (newlastlump < *lastlump) - { - newlastlump++; - // load all sprite sets we are aware of... for super! - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); - - newlastlump--; - *lastlump = newlastlump; // okay, make the normal sprite set loading end there - } - - // load all sprite sets we are aware of... for normal stuff. - for (sprite2 = 0; sprite2 < free_spr2; sprite2++) - 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]); -} - -// returns whether found appropriate property -static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) -{ - // custom translation table - if (!stricmp(stoken, "startcolor")) - skin->starttranscolor = atoi(value); - -#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); - // character type identification - FULLPROCESS(flags) - FULLPROCESS(ability) - FULLPROCESS(ability2) - - FULLPROCESS(thokitem) - FULLPROCESS(spinitem) - FULLPROCESS(revitem) - FULLPROCESS(followitem) -#undef FULLPROCESS - -#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<field = atoi(value); - GETINT(thrustfactor) - GETINT(accelstart) - GETINT(acceleration) - GETINT(contspeed) - GETINT(contangle) -#undef GETINT - -#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) \ -{ \ - UINT16 color = R_GetColorByName(value); \ - skin->field = (color ? color : SKINCOLOR_GREEN); \ -} - GETSKINCOLOR(prefcolor) - GETSKINCOLOR(prefoppositecolor) -#undef GETSKINCOLOR - else if (!stricmp(stoken, "supercolor")) - { - UINT16 color = R_GetSuperColorByName(value); - skin->supercolor = (color ? color : SKINCOLOR_SUPERGOLD1); - } - -#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value)); - GETFLOAT(jumpfactor) - GETFLOAT(highresscale) - GETFLOAT(shieldscale) - GETFLOAT(camerascale) -#undef GETFLOAT - -#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \ - strupr(value); \ - if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \ - skin->flags |= (SF_##field); \ - else \ - skin->flags &= ~(SF_##field); \ -} - // parameters for individual character flags - // these are uppercase so they can be concatenated with SF_ - // 1, true, yes are all valid values - GETFLAG(SUPER) - GETFLAG(NOSUPERSPIN) - GETFLAG(NOSPINDASHDUST) - GETFLAG(HIRES) - GETFLAG(NOSKID) - GETFLAG(NOSPEEDADJUST) - GETFLAG(RUNONWATER) - GETFLAG(NOJUMPSPIN) - GETFLAG(NOJUMPDAMAGE) - GETFLAG(STOMPDAMAGE) - GETFLAG(MARIODAMAGE) - GETFLAG(MACHINE) - GETFLAG(DASHMODE) - GETFLAG(FASTEDGE) - GETFLAG(MULTIABILITY) - GETFLAG(NONIGHTSROTATION) - GETFLAG(NONIGHTSSUPER) -#undef GETFLAG - - else // let's check if it's a sound, otherwise error out - { - boolean found = false; - sfxenum_t i; - size_t stokenadjust; - - // Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.) - if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS* - stokenadjust = 2; - else // sfx_* - stokenadjust = 4; - - // Remove the prefix. (We can affect this directly since we're not going to use it again.) - if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS* - value += 2; - else // sfx_* - value += 4; - - // copy name of sounds that are remapped - // for this skin - for (i = 0; i < sfx_skinsoundslot0; i++) - { - if (!S_sfx[i].name) - continue; - if (S_sfx[i].skinsound != -1 - && !stricmp(S_sfx[i].name, - stoken + stokenadjust)) - { - skin->soundsid[S_sfx[i].skinsound] = - S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true); - found = true; + else + { + if (server) + { + SendKick(i, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic)); + } + CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]); + break; + } + } } } - return found; - } + + // If you are a client, you can safely forget the net commands for this tic + // If you are the server, you need to remember them until every client has been acknowledged, + // because if you need to resend a PT_SERVERTICS packet, you will need to put the commands in it + if (client) + D_FreeTextcmd(gametic); +} + +static void D_Clearticcmd(tic_t tic) +{ + INT32 i; + + D_FreeTextcmd(tic); + + for (i = 0; i < MAXPLAYERS; i++) + netcmds[tic%BACKUPTICS][i].angleturn = 0; + + DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); +} + +void D_ResetTiccmds(void) +{ + INT32 i; + + memset(&localcmds, 0, sizeof(ticcmd_t)); + memset(&localcmds2, 0, sizeof(ticcmd_t)); + + // Reset the net command list + for (i = 0; i < TEXTCMD_HASH_SIZE; i++) + while (textcmds[i]) + D_Clearticcmd(textcmds[i]->tic); +} + +void SendKick(UINT8 playernum, UINT8 msg) +{ + UINT8 buf[2]; + + if (!(server && cv_rejointimeout.value)) + msg &= ~KICK_MSG_KEEP_BODY; + + buf[0] = playernum; + buf[1] = msg; + SendNetXCmd(XD_KICK, &buf, 2); +} + +// ----------------------------------------------------------------- +// end of extra data function +// ----------------------------------------------------------------- + +// ----------------------------------------------------------------- +// extra data function for lmps +// ----------------------------------------------------------------- + +// if extradatabit is set, after the ziped tic you find this: +// +// type | description +// ---------+-------------- +// byte | size of the extradata +// byte | the extradata (xd) bits: see XD_... +// with this byte you know what parameter folow +// if (xd & XDNAMEANDCOLOR) +// byte | color +// char[MAXPLAYERNAME] | name of the player +// endif +// if (xd & XD_WEAPON_PREF) +// byte | original weapon switch: boolean, true if use the old +// | weapon switch methode +// char[NUMWEAPONS] | the weapon switch priority +// byte | autoaim: true if use the old autoaim system +// endif +/*boolean AddLmpExtradata(UINT8 **demo_point, INT32 playernum) +{ + UINT8 *textcmd = D_GetExistingTextcmd(gametic, playernum); + + if (!textcmd) + return false; + + M_Memcpy(*demo_point, textcmd, textcmd[0]+1); + *demo_point += textcmd[0]+1; return true; } -// -// Find skin sprites, sounds & optional status bar face, & add them -// -void R_AddSkins(UINT16 wadnum) +void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) { - UINT16 lump, lastlump = 0; - char *buf; - char *buf2; - char *stoken; - char *value; - size_t size; - skin_t *skin; - boolean hudname, realname; + UINT8 nextra; + UINT8 *textcmd; - // - // search for all skin markers in pwad - // + if (!demo_pointer) + return; - while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + textcmd = D_GetTextcmd(gametic, playernum); + nextra = **demo_pointer; + M_Memcpy(textcmd, *demo_pointer, nextra + 1); + // increment demo pointer + *demo_pointer += nextra + 1; +}*/ + +// ----------------------------------------------------------------- +// end extra data function for lmps +// ----------------------------------------------------------------- + +static INT16 Consistancy(void); + +typedef enum +{ + CL_SEARCHING, + CL_DOWNLOADFILES, + CL_ASKJOIN, + CL_WAITJOINRESPONSE, + CL_DOWNLOADSAVEGAME, + CL_CONNECTED, + CL_ABORTED +} cl_mode_t; + +static void GetPackets(void); + +static cl_mode_t cl_mode = CL_SEARCHING; + +#ifndef NONET +#define SNAKE_SPEED 5 + +#define SNAKE_NUM_BLOCKS_X 20 +#define SNAKE_NUM_BLOCKS_Y 10 +#define SNAKE_BLOCK_SIZE 12 +#define SNAKE_BORDER_SIZE 12 + +#define SNAKE_MAP_WIDTH (SNAKE_NUM_BLOCKS_X * SNAKE_BLOCK_SIZE) +#define SNAKE_MAP_HEIGHT (SNAKE_NUM_BLOCKS_Y * SNAKE_BLOCK_SIZE) + +#define SNAKE_LEFT_X ((BASEVIDWIDTH - SNAKE_MAP_WIDTH) / 2 - SNAKE_BORDER_SIZE) +#define SNAKE_RIGHT_X (SNAKE_LEFT_X + SNAKE_MAP_WIDTH + SNAKE_BORDER_SIZE * 2 - 1) +#define SNAKE_BOTTOM_Y (BASEVIDHEIGHT - 48) +#define SNAKE_TOP_Y (SNAKE_BOTTOM_Y - SNAKE_MAP_HEIGHT - SNAKE_BORDER_SIZE * 2 + 1) + +enum snake_bonustype_s { + SNAKE_BONUS_NONE = 0, + SNAKE_BONUS_SLOW, + SNAKE_BONUS_FAST, + SNAKE_BONUS_GHOST, + SNAKE_BONUS_NUKE, + SNAKE_BONUS_SCISSORS, + SNAKE_BONUS_REVERSE, + SNAKE_BONUS_EGGMAN, + SNAKE_NUM_BONUSES, +}; + +static const char *snake_bonuspatches[] = { + NULL, + "DL_SLOW", + "TVSSC0", + "TVIVC0", + "TVARC0", + "DL_SCISSORS", + "TVRCC0", + "TVEGC0", +}; + +static const char *snake_backgrounds[] = { + "RVPUMICF", + "FRSTRCKF", + "TAR", + "MMFLRB4", + "RVDARKF1", + "RVZWALF1", + "RVZWALF4", + "RVZWALF5", + "RVZGRS02", + "RVZGRS04", +}; + +typedef struct snake_s +{ + boolean paused; + boolean pausepressed; + tic_t time; + tic_t nextupdate; + boolean gameover; + UINT8 background; + + UINT16 snakelength; + enum snake_bonustype_s snakebonus; + tic_t snakebonustime; + UINT8 snakex[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; + UINT8 snakey[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; + UINT8 snakedir[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; + + UINT8 applex; + UINT8 appley; + + enum snake_bonustype_s bonustype; + UINT8 bonusx; + UINT8 bonusy; +} snake_t; + +static snake_t *snake = NULL; + +static void Snake_Initialise(void) +{ + if (!snake) + snake = malloc(sizeof(snake_t)); + + snake->paused = false; + snake->pausepressed = false; + snake->time = 0; + snake->nextupdate = SNAKE_SPEED; + snake->gameover = false; + snake->background = M_RandomKey(sizeof(snake_backgrounds) / sizeof(*snake_backgrounds)); + + snake->snakelength = 1; + snake->snakebonus = SNAKE_BONUS_NONE; + snake->snakex[0] = M_RandomKey(SNAKE_NUM_BLOCKS_X); + snake->snakey[0] = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + snake->snakedir[0] = 0; + snake->snakedir[1] = 0; + + snake->applex = M_RandomKey(SNAKE_NUM_BLOCKS_X); + snake->appley = M_RandomKey(SNAKE_NUM_BLOCKS_Y); + + snake->bonustype = SNAKE_BONUS_NONE; +} + +static UINT8 Snake_GetOppositeDir(UINT8 dir) +{ + if (dir == 1 || dir == 3) + return dir + 1; + else if (dir == 2 || dir == 4) + return dir - 1; + else + return 12 + 5 - dir; +} + +static void Snake_FindFreeSlot(UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) +{ + UINT8 x, y; + UINT16 i; + + do { - // advance by default - lastlump = lump + 1; + x = M_RandomKey(SNAKE_NUM_BLOCKS_X); + y = M_RandomKey(SNAKE_NUM_BLOCKS_Y); - if (numskins >= MAXSKINS) - { - CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS); - continue; // so we know how many skins couldn't be added - } - buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); + for (i = 0; i < snake->snakelength; i++) + if (x == snake->snakex[i] && y == snake->snakey[i]) + break; + } while (i < snake->snakelength || (x == headx && y == heady) + || (x == snake->applex && y == snake->appley) + || (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy)); - // for strtok - buf2 = malloc(size+1); - if (!buf2) - I_Error("R_AddSkins: No more free memory\n"); - M_Memcpy(buf2,buf,size); - buf2[size] = '\0'; + *freex = x; + *freey = y; +} - // set defaults - skin = &skins[numskins]; - Sk_SetDefaultValue(skin); - skin->wadnum = wadnum; - hudname = realname = false; - // parse - 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 - } +static void Snake_Handle(void) +{ + UINT8 x, y; + UINT8 oldx, oldy; + UINT16 i; - value = strtok(NULL, "\r\n= "); - - if (!value) - I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); - - // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. - // Others can't go in there because we don't want them to be patchable. - if (!stricmp(stoken, "name")) - { - INT32 skinnum = R_SkinAvailable(value); - strlwr(value); - if (skinnum == -1) - STRBUFCPY(skin->name, value); - // the skin name must uniquely identify a single skin - // if the name is already used I make the name 'namex' - // using the default skin name's number set above - else - { - const size_t stringspace = - strlen(value) + sizeof (numskins) + 1; - char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL); - snprintf(value2, stringspace, - "%s%d", value, numskins); - value2[stringspace - 1] = '\0'; - if (R_SkinAvailable(value2) == -1) - // I'm lazy so if NEW name is already used I leave the 'skin x' - // default skin name set in Sk_SetDefaultValue - STRBUFCPY(skin->name, value2); - Z_Free(value2); - } - - // copy to hudname and fullname as a default. - if (!realname) - { - STRBUFCPY(skin->realname, skin->name); - for (value = skin->realname; *value; value++) - { - if (*value == '_') *value = ' '; // turn _ into spaces. - else if (*value == '.') *value = '\x1E'; // turn . into katana dot. - } - } - if (!hudname) - { - HUDNAMEWRITE(skin->name); - strupr(skin->hudname); - SYMBOLCONVERT(skin->hudname) - } - } - else if (!stricmp(stoken, "realname")) - { // Display name (eg. "Knuckles") - realname = true; - STRBUFCPY(skin->realname, value); - SYMBOLCONVERT(skin->realname) - if (!hudname) - HUDNAMEWRITE(skin->realname); - } - else if (!stricmp(stoken, "hudname")) - { // Life icon name (eg. "K.T.E") - hudname = true; - HUDNAMEWRITE(value); - SYMBOLCONVERT(skin->hudname) - if (!realname) - STRBUFCPY(skin->realname, skin->hudname); - } - else if (!stricmp(stoken, "availability")) - { - skin->availability = atoi(value); - if (skin->availability >= MAXUNLOCKABLES) - skin->availability = 0; - } - else if (!R_ProcessPatchableFields(skin, stoken, value)) - CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); - -next_token: - stoken = strtok(NULL, "\r\n= "); - } - free(buf2); - - // Add sprites - R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); - //ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere - - R_FlushTranslationColormapCache(); - - if (!skin->availability) // Safe to print... - CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); -#ifdef SKINVALUES - skin_cons_t[numskins].value = numskins; - skin_cons_t[numskins].strvalue = skin->name; -#endif - -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddPlayerModel(numskins); -#endif - - numskins++; + // Handle retry + if (snake->gameover && (PLAYER1INPUTDOWN(gc_jump) || gamekeydown[KEY_ENTER])) + { + Snake_Initialise(); + snake->pausepressed = true; // Avoid accidental pause on respawn } - return; + + // Handle pause + if (PLAYER1INPUTDOWN(gc_pause) || gamekeydown[KEY_ENTER]) + { + if (!snake->pausepressed) + snake->paused = !snake->paused; + snake->pausepressed = true; + } + else + snake->pausepressed = false; + + if (snake->paused) + return; + + snake->time++; + + x = snake->snakex[0]; + y = snake->snakey[0]; + oldx = snake->snakex[1]; + oldy = snake->snakey[1]; + + // Update direction + if (gamekeydown[KEY_LEFTARROW]) + { + if (snake->snakelength < 2 || x <= oldx) + snake->snakedir[0] = 1; + } + else if (gamekeydown[KEY_RIGHTARROW]) + { + if (snake->snakelength < 2 || x >= oldx) + snake->snakedir[0] = 2; + } + else if (gamekeydown[KEY_UPARROW]) + { + if (snake->snakelength < 2 || y <= oldy) + snake->snakedir[0] = 3; + } + else if (gamekeydown[KEY_DOWNARROW]) + { + if (snake->snakelength < 2 || y >= oldy) + snake->snakedir[0] = 4; + } + + if (snake->snakebonustime) + { + snake->snakebonustime--; + if (!snake->snakebonustime) + snake->snakebonus = SNAKE_BONUS_NONE; + } + + snake->nextupdate--; + if (snake->nextupdate) + return; + if (snake->snakebonus == SNAKE_BONUS_SLOW) + snake->nextupdate = SNAKE_SPEED * 2; + else if (snake->snakebonus == SNAKE_BONUS_FAST) + snake->nextupdate = SNAKE_SPEED * 2 / 3; + else + snake->nextupdate = SNAKE_SPEED; + + if (snake->gameover) + return; + + // Find new position + switch (snake->snakedir[0]) + { + case 1: + if (x > 0) + x--; + else + snake->gameover = true; + break; + case 2: + if (x < SNAKE_NUM_BLOCKS_X - 1) + x++; + else + snake->gameover = true; + break; + case 3: + if (y > 0) + y--; + else + snake->gameover = true; + break; + case 4: + if (y < SNAKE_NUM_BLOCKS_Y - 1) + y++; + else + snake->gameover = true; + break; + } + + // Check collision with snake + if (snake->snakebonus != SNAKE_BONUS_GHOST) + for (i = 1; i < snake->snakelength - 1; i++) + if (x == snake->snakex[i] && y == snake->snakey[i]) + { + if (snake->snakebonus == SNAKE_BONUS_SCISSORS) + { + snake->snakebonus = SNAKE_BONUS_NONE; + snake->snakelength = i; + S_StartSound(NULL, sfx_adderr); + } + else + snake->gameover = true; + } + + if (snake->gameover) + { + S_StartSound(NULL, sfx_lose); + return; + } + + // Check collision with apple + if (x == snake->applex && y == snake->appley) + { + if (snake->snakelength + 3 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y) + { + snake->snakelength++; + snake->snakex [snake->snakelength - 1] = snake->snakex [snake->snakelength - 2]; + snake->snakey [snake->snakelength - 1] = snake->snakey [snake->snakelength - 2]; + snake->snakedir[snake->snakelength - 1] = snake->snakedir[snake->snakelength - 2]; + } + + // Spawn new apple + Snake_FindFreeSlot(&snake->applex, &snake->appley, x, y); + + // Spawn new bonus + if (!(snake->snakelength % 5)) + { + do + { + snake->bonustype = M_RandomKey(SNAKE_NUM_BONUSES - 1) + 1; + } while (snake->snakelength > SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y * 3 / 4 + && (snake->bonustype == SNAKE_BONUS_EGGMAN || snake->bonustype == SNAKE_BONUS_FAST || snake->bonustype == SNAKE_BONUS_REVERSE)); + + Snake_FindFreeSlot(&snake->bonusx, &snake->bonusy, x, y); + } + + S_StartSound(NULL, sfx_s3k6b); + } + + if (snake->snakelength > 1 && snake->snakedir[0]) + { + UINT8 dir = snake->snakedir[0]; + + oldx = snake->snakex[1]; + oldy = snake->snakey[1]; + + // Move + for (i = snake->snakelength - 1; i > 0; i--) + { + snake->snakex[i] = snake->snakex[i - 1]; + snake->snakey[i] = snake->snakey[i - 1]; + snake->snakedir[i] = snake->snakedir[i - 1]; + } + + // Handle corners + if (x < oldx && dir == 3) + dir = 5; + else if (x > oldx && dir == 3) + dir = 6; + else if (x < oldx && dir == 4) + dir = 7; + else if (x > oldx && dir == 4) + dir = 8; + else if (y < oldy && dir == 1) + dir = 9; + else if (y < oldy && dir == 2) + dir = 10; + else if (y > oldy && dir == 1) + dir = 11; + else if (y > oldy && dir == 2) + dir = 12; + snake->snakedir[1] = dir; + } + + snake->snakex[0] = x; + snake->snakey[0] = y; + + // Check collision with bonus + if (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy) + { + S_StartSound(NULL, sfx_ncchip); + + switch (snake->bonustype) + { + case SNAKE_BONUS_SLOW: + snake->snakebonus = SNAKE_BONUS_SLOW; + snake->snakebonustime = 20 * TICRATE; + break; + case SNAKE_BONUS_FAST: + snake->snakebonus = SNAKE_BONUS_FAST; + snake->snakebonustime = 20 * TICRATE; + break; + case SNAKE_BONUS_GHOST: + snake->snakebonus = SNAKE_BONUS_GHOST; + snake->snakebonustime = 10 * TICRATE; + break; + case SNAKE_BONUS_NUKE: + for (i = 0; i < snake->snakelength; i++) + { + snake->snakex [i] = snake->snakex [0]; + snake->snakey [i] = snake->snakey [0]; + snake->snakedir[i] = snake->snakedir[0]; + } + + S_StartSound(NULL, sfx_bkpoof); + break; + case SNAKE_BONUS_SCISSORS: + snake->snakebonus = SNAKE_BONUS_SCISSORS; + snake->snakebonustime = 60 * TICRATE; + break; + case SNAKE_BONUS_REVERSE: + for (i = 0; i < (snake->snakelength + 1) / 2; i++) + { + UINT16 i2 = snake->snakelength - 1 - i; + UINT8 tmpx = snake->snakex [i]; + UINT8 tmpy = snake->snakey [i]; + UINT8 tmpdir = snake->snakedir[i]; + + // Swap first segment with last segment + snake->snakex [i] = snake->snakex [i2]; + snake->snakey [i] = snake->snakey [i2]; + snake->snakedir[i] = Snake_GetOppositeDir(snake->snakedir[i2]); + snake->snakex [i2] = tmpx; + snake->snakey [i2] = tmpy; + snake->snakedir[i2] = Snake_GetOppositeDir(tmpdir); + } + + snake->snakedir[0] = 0; + + S_StartSound(NULL, sfx_gravch); + break; + default: + if (snake->snakebonus != SNAKE_BONUS_GHOST) + { + snake->gameover = true; + S_StartSound(NULL, sfx_lose); + } + } + + snake->bonustype = SNAKE_BONUS_NONE; + } +} + +static void Snake_Draw(void) +{ + INT16 i; + + // Background + V_DrawFlatFill( + SNAKE_LEFT_X + SNAKE_BORDER_SIZE, + SNAKE_TOP_Y + SNAKE_BORDER_SIZE, + SNAKE_MAP_WIDTH, + SNAKE_MAP_HEIGHT, + W_GetNumForName(snake_backgrounds[snake->background]) + ); + + // Borders + V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Top + V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_TOP_Y, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Right + V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Bottom + V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y + SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Left + + // Apple + V_DrawFixedPatch( + (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->applex * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->appley * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + FRACUNIT / 4, + 0, + W_CachePatchLongName("DL_APPLE", PU_HUDGFX), + NULL + ); + + // Bonus + if (snake->bonustype != SNAKE_BONUS_NONE) + V_DrawFixedPatch( + (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->bonusx * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 ) * FRACUNIT, + (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->bonusy * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 + 4) * FRACUNIT, + FRACUNIT / 2, + 0, + W_CachePatchLongName(snake_bonuspatches[snake->bonustype], PU_HUDGFX), + NULL + ); + + // Snake + if (!snake->gameover || snake->time % 8 < 8 / 2) // Blink if game over + { + for (i = snake->snakelength - 1; i >= 0; i--) + { + const char *patchname; + UINT8 dir = snake->snakedir[i]; + + if (i == 0) // Head + { + switch (dir) + { + case 1: patchname = "DL_SNAKEHEAD_L"; break; + case 2: patchname = "DL_SNAKEHEAD_R"; break; + case 3: patchname = "DL_SNAKEHEAD_T"; break; + case 4: patchname = "DL_SNAKEHEAD_B"; break; + default: patchname = "DL_SNAKEHEAD_M"; + } + } + else // Body + { + switch (dir) + { + case 1: patchname = "DL_SNAKEBODY_L"; break; + case 2: patchname = "DL_SNAKEBODY_R"; break; + case 3: patchname = "DL_SNAKEBODY_T"; break; + case 4: patchname = "DL_SNAKEBODY_B"; break; + case 5: patchname = "DL_SNAKEBODY_LT"; break; + case 6: patchname = "DL_SNAKEBODY_RT"; break; + case 7: patchname = "DL_SNAKEBODY_LB"; break; + case 8: patchname = "DL_SNAKEBODY_RB"; break; + case 9: patchname = "DL_SNAKEBODY_TL"; break; + case 10: patchname = "DL_SNAKEBODY_TR"; break; + case 11: patchname = "DL_SNAKEBODY_BL"; break; + case 12: patchname = "DL_SNAKEBODY_BR"; break; + default: patchname = "DL_SNAKEBODY_B"; + } + } + + V_DrawFixedPatch( + (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->snakex[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->snakey[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, + i == 0 && dir == 0 ? FRACUNIT / 5 : FRACUNIT / 2, + snake->snakebonus == SNAKE_BONUS_GHOST ? V_TRANSLUCENT : 0, + W_CachePatchLongName(patchname, PU_HUDGFX), + NULL + ); + } + } + + // Length + V_DrawString(SNAKE_RIGHT_X + 4, SNAKE_TOP_Y, V_MONOSPACE, va("%u", snake->snakelength)); + + // Bonus + if (snake->snakebonus != SNAKE_BONUS_NONE + && (snake->snakebonustime >= 3 * TICRATE || snake->time % 4 < 4 / 2)) + V_DrawFixedPatch( + (SNAKE_RIGHT_X + 10) * FRACUNIT, + (SNAKE_TOP_Y + 24) * FRACUNIT, + FRACUNIT / 2, + 0, + W_CachePatchLongName(snake_bonuspatches[snake->snakebonus], PU_HUDGFX), + NULL + ); } // -// Patch skin sprites +// CL_DrawConnectionStatus // -void R_PatchSkins(UINT16 wadnum) +// Keep the local client informed of our status. +// +static inline void CL_DrawConnectionStatus(void) { - UINT16 lump, lastlump = 0; - char *buf; - char *buf2; - char *stoken; - char *value; - size_t size; - skin_t *skin; - boolean noskincomplain, realname, hudname; + INT32 ccstime = I_GetTime(); - // - // search for all skin patch markers in pwad - // + // Draw background fade + if (!menuactive) // menu already draws its own fade + V_DrawFadeScreen(0xFF00, 16); // force default - while ((lump = W_CheckForPatchSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + // Draw the bottom box. + M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); + + if (cl_mode != CL_DOWNLOADFILES) { - INT32 skinnum = 0; + INT32 i, animtime = ((ccstime / 4) & 15) + 16; + UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96; + // 15 pal entries total. + const char *cltext; - // advance by default - lastlump = lump + 1; + if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1)) + for (i = 0; i < 16; ++i) + V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15)); - buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); - - // for strtok - buf2 = malloc(size+1); - if (!buf2) - I_Error("R_PatchSkins: No more free memory\n"); - M_Memcpy(buf2,buf,size); - buf2[size] = '\0'; - - skin = NULL; - noskincomplain = realname = hudname = 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) + switch (cl_mode) { - 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_PatchSkins: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); - - if (!skin) // Get the name! - { - if (!stricmp(stoken, "name")) + case CL_DOWNLOADSAVEGAME: + if (lastfilenum != -1) { - strlwr(value); - skinnum = R_SkinAvailable(value); - if (skinnum != -1) - skin = &skins[skinnum]; - else - { - CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); - noskincomplain = true; - } - } - } - else // Get the properties! - { - // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. - if (!stricmp(stoken, "realname")) - { // Display name (eg. "Knuckles") - realname = true; - STRBUFCPY(skin->realname, value); - SYMBOLCONVERT(skin->realname) - if (!hudname) - HUDNAMEWRITE(skin->realname); - } - else if (!stricmp(stoken, "hudname")) - { // Life icon name (eg. "K.T.E") - hudname = true; - HUDNAMEWRITE(value); - SYMBOLCONVERT(skin->hudname) - if (!realname) - STRBUFCPY(skin->realname, skin->hudname); - } - else if (!R_ProcessPatchableFields(skin, stoken, value)) - CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); - } + UINT32 currentsize = fileneeded[lastfilenum].currentsize; + UINT32 totalsize = fileneeded[lastfilenum].totalsize; + INT32 dldlength; - if (!skin) + cltext = M_GetText("Downloading game state..."); + Net_GetNetStat(); + + dldlength = (INT32)((currentsize/(double)totalsize) * 256); + if (dldlength > 256) + dldlength = 256; + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); + + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va(" %4uK/%4uK",currentsize>>10,totalsize>>10)); + + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va("%3.1fK/s ", ((double)getbps)/1024)); + } + else + cltext = M_GetText("Waiting to download game state..."); + break; + case CL_ASKJOIN: + case CL_WAITJOINRESPONSE: + cltext = M_GetText("Requesting to join..."); + break; + default: + cltext = M_GetText("Connecting to server..."); break; - -next_token: - stoken = strtok(NULL, "\r\n= "); } - free(buf2); - - if (!skin) // Didn't include a name parameter? What a waste. + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, cltext); + } + else + { + if (lastfilenum != -1) { - if (!noskincomplain) - CONS_Debug(DBG_SETUP, "R_PatchSkins: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename); + INT32 dldlength; + static char tempname[28]; + fileneeded_t *file = &fileneeded[lastfilenum]; + char *filename = file->filename; + + Snake_Draw(); + + Net_GetNetStat(); + dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); + if (dldlength > 256) + dldlength = 256; + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); + + memset(tempname, 0, sizeof(tempname)); + // offset filename to just the name only part + filename += strlen(filename) - nameonlylength(filename); + + if (strlen(filename) > sizeof(tempname)-1) // too long to display fully + { + size_t endhalfpos = strlen(filename)-10; + // display as first 14 chars + ... + last 10 chars + // which should add up to 27 if our math(s) is correct + snprintf(tempname, sizeof(tempname), "%.14s...%.10s", filename, filename+endhalfpos); + } + else // we can copy the whole thing in safely + { + strncpy(tempname, filename, sizeof(tempname)-1); + } + + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, + va(M_GetText("Downloading \"%s\""), tempname)); + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10)); + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, + va("%3.1fK/s ", ((double)getbps)/1024)); + } + else + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, + M_GetText("Waiting to download files...")); + } +} +#endif + +/** Sends a special packet to declare how many players in local + * Used only in arbitratrenetstart() + * Sends a PT_CLIENTJOIN packet to the server + * + * \return True if the packet was successfully sent + * \todo Improve the description... + * Because to be honest, I have no idea what arbitratrenetstart is... + * Is it even used...? + * + */ +static boolean CL_SendJoin(void) +{ + UINT8 localplayers = 1; + if (netgame) + CONS_Printf(M_GetText("Sending join request...\n")); + netbuffer->packettype = PT_CLIENTJOIN; + + if (splitscreen || botingame) + localplayers++; + netbuffer->u.clientcfg.localplayers = localplayers; + netbuffer->u.clientcfg._255 = 255; + netbuffer->u.clientcfg.packetversion = PACKETVERSION; + netbuffer->u.clientcfg.version = VERSION; + netbuffer->u.clientcfg.subversion = SUBVERSION; + strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application); + + CleanupPlayerName(consoleplayer, cv_playername.zstring); + if (splitscreen) + CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ + + strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); + strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); + + return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); +} + +static INT32 FindRejoinerNum(SINT8 node) +{ + char strippednodeaddress[64]; + const char *nodeaddress; + char *port; + INT32 i; + + // Make sure there is no dead dress before proceeding to the stripping + if (!I_GetNodeAddress) + return -1; + nodeaddress = I_GetNodeAddress(node); + if (!nodeaddress) + return -1; + + // Strip the address of its port + strcpy(strippednodeaddress, nodeaddress); + port = strchr(strippednodeaddress, ':'); + if (port) + *port = '\0'; + + // Check if any player matches the stripped address + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX + && !strcmp(playeraddress[i], strippednodeaddress)) + return i; + } + + return -1; +} + +static void SV_SendServerInfo(INT32 node, tic_t servertime) +{ + UINT8 *p; + + netbuffer->packettype = PT_SERVERINFO; + netbuffer->u.serverinfo._255 = 255; + netbuffer->u.serverinfo.packetversion = PACKETVERSION; + netbuffer->u.serverinfo.version = VERSION; + netbuffer->u.serverinfo.subversion = SUBVERSION; + strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION, + sizeof netbuffer->u.serverinfo.application); + // return back the time value so client can compute their ping + netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); + netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); + + netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); + netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; + + if (!node || FindRejoinerNum(node) != -1) + netbuffer->u.serverinfo.refusereason = 0; + else if (!cv_allownewplayer.value) + netbuffer->u.serverinfo.refusereason = 1; + else if (D_NumPlayers() >= cv_maxplayers.value) + netbuffer->u.serverinfo.refusereason = 2; + else + netbuffer->u.serverinfo.refusereason = 0; + + strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], + sizeof netbuffer->u.serverinfo.gametypename); + netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; + netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); + netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated; + strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, + MAXSERVERNAME); + strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); + + M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16); + + memset(netbuffer->u.serverinfo.maptitle, 0, sizeof netbuffer->u.serverinfo.maptitle); + + if (mapheaderinfo[gamemap-1] && *mapheaderinfo[gamemap-1]->lvlttl) + { + char *read = mapheaderinfo[gamemap-1]->lvlttl, *writ = netbuffer->u.serverinfo.maptitle; + while (writ < (netbuffer->u.serverinfo.maptitle+32) && *read != '\0') + { + if (!(*read & 0x80)) + { + *writ = toupper(*read); + writ++; + } + read++; + } + *writ = '\0'; + //strncpy(netbuffer->u.serverinfo.maptitle, (char *)mapheaderinfo[gamemap-1]->lvlttl, 33); + } + else + strncpy(netbuffer->u.serverinfo.maptitle, "UNKNOWN", 32); + + if (mapheaderinfo[gamemap-1] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + netbuffer->u.serverinfo.iszone = 1; + else + netbuffer->u.serverinfo.iszone = 0; + + if (mapheaderinfo[gamemap-1]) + netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum; + + p = PutFileNeeded(); + + HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); +} + +static void SV_SendPlayerInfo(INT32 node) +{ + UINT8 i; + netbuffer->packettype = PT_PLAYERINFO; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + { + netbuffer->u.playerinfo[i].num = 255; // This slot is empty. continue; } - // Patch sprites - R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); - //ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere + netbuffer->u.playerinfo[i].num = i; + strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); + netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; - R_FlushTranslationColormapCache(); + //fetch IP address + //No, don't do that, you fuckface. + memset(netbuffer->u.playerinfo[i].address, 0, 4); - if (!skin->availability) // Safe to print... - CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); + if (G_GametypeHasTeams()) + { + if (!players[i].ctfteam) + netbuffer->u.playerinfo[i].team = 255; + else + netbuffer->u.playerinfo[i].team = (UINT8)players[i].ctfteam; + } + else + { + if (players[i].spectator) + netbuffer->u.playerinfo[i].team = 255; + else + netbuffer->u.playerinfo[i].team = 0; + } + + netbuffer->u.playerinfo[i].score = LONG(players[i].score); + netbuffer->u.playerinfo[i].timeinserver = SHORT((UINT16)(players[i].jointime / TICRATE)); + netbuffer->u.playerinfo[i].skin = (UINT8)(players[i].skin +#ifdef DEVELOP // it's safe to do this only because PLAYERINFO isn't read by the game itself + % 3 +#endif + ); + + // Extra data + netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor; + + if (players[i].pflags & PF_TAGIT) + netbuffer->u.playerinfo[i].data |= 0x20; + + if (players[i].gotflag) + netbuffer->u.playerinfo[i].data |= 0x40; + + if (players[i].powers[pw_super]) + netbuffer->u.playerinfo[i].data |= 0x80; } - return; + + HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); } -#undef HUDNAMEWRITE -#undef SYMBOLCONVERT +/** Sends a PT_SERVERCFG packet + * + * \param node The destination + * \return True if the packet was successfully sent + * + */ +static boolean SV_SendServerConfig(INT32 node) +{ + boolean waspacketsent; + + netbuffer->packettype = PT_SERVERCFG; + + netbuffer->u.servercfg.version = VERSION; + netbuffer->u.servercfg.subversion = SUBVERSION; + + netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer; + netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots); + netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic); + netbuffer->u.servercfg.clientnode = (UINT8)node; + netbuffer->u.servercfg.gamestate = (UINT8)gamestate; + netbuffer->u.servercfg.gametype = (UINT8)gametype; + netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; + + memcpy(netbuffer->u.servercfg.server_context, server_context, 8); + + { + const size_t len = sizeof (serverconfig_pak); + +#ifdef DEBUGFILE + if (debugfile) + { + fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n", + sizeu1(len), node); + } +#endif + + waspacketsent = HSendPacket(node, true, 0, len); + } + +#ifdef DEBUGFILE + if (debugfile) + { + if (waspacketsent) + { + fprintf(debugfile, "ServerConfig Packet was sent\n"); + } + else + { + fprintf(debugfile, "ServerConfig Packet could not be sent right now\n"); + } + } +#endif + + return waspacketsent; +} + +#ifndef NONET +#define SAVEGAMESIZE (768*1024) + +static boolean SV_ResendingSavegameToAnyone(void) +{ + INT32 i; + + for (i = 0; i < MAXNETNODES; i++) + if (resendingsavegame[i]) + return true; + return false; +} + +static void SV_SendSaveGame(INT32 node, boolean resending) +{ + size_t length, compressedlen; + UINT8 *savebuffer; + UINT8 *compressedsave; + UINT8 *buffertosend; + + // first save it in a malloced buffer + savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); + if (!savebuffer) + { + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + return; + } + + // Leave room for the uncompressed length. + save_p = savebuffer + sizeof(UINT32); + + P_SaveNetGame(resending); + + length = save_p - savebuffer; + if (length > SAVEGAMESIZE) + { + free(savebuffer); + save_p = NULL; + I_Error("Savegame buffer overrun"); + } + + // Allocate space for compressed save: one byte fewer than for the + // uncompressed data to ensure that the compression is worthwhile. + compressedsave = malloc(length - 1); + if (!compressedsave) + { + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + return; + } + + // Attempt to compress it. + if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) + { + // Compressing succeeded; send compressed data + + free(savebuffer); + + // State that we're compressed. + buffertosend = compressedsave; + WRITEUINT32(compressedsave, length - sizeof(UINT32)); + length = compressedlen + sizeof(UINT32); + } + else + { + // Compression failed to make it smaller; send original + + free(compressedsave); + + // State that we're not compressed + buffertosend = savebuffer; + WRITEUINT32(savebuffer, 0); + } + + AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0); + save_p = NULL; + + // Remember when we started sending the savegame so we can handle timeouts + sendingsavegame[node] = true; + freezetimeout[node] = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte +} + +#ifdef DUMPCONSISTENCY +#define TMPSAVENAME "badmath.sav" +static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +static void SV_SavedGame(void) +{ + size_t length; + UINT8 *savebuffer; + char tmpsave[256]; + + if (!cv_dumpconsistency.value) + return; + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + // first save it in a malloced buffer + save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); + if (!save_p) + { + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + return; + } + + P_SaveNetGame(false); + + length = save_p - savebuffer; + if (length > SAVEGAMESIZE) + { + free(savebuffer); + save_p = NULL; + I_Error("Savegame buffer overrun"); + } + + // then save it! + if (!FIL_WriteFile(tmpsave, savebuffer, length)) + CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); + + free(savebuffer); + save_p = NULL; +} + +#undef TMPSAVENAME +#endif +#define TMPSAVENAME "$$$.sav" + + +static void CL_LoadReceivedSavegame(boolean reloading) +{ + UINT8 *savebuffer = NULL; + size_t length, decompressedlen; + char tmpsave[256]; + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + length = FIL_ReadFile(tmpsave, &savebuffer); + + CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); + if (!length) + { + I_Error("Can't read savegame sent"); + return; + } + + save_p = savebuffer; + + // Decompress saved game if necessary. + decompressedlen = READUINT32(save_p); + if(decompressedlen > 0) + { + UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); + lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); + Z_Free(savebuffer); + save_p = savebuffer = decompressedbuffer; + } + + paused = false; + demoplayback = false; + titlemapinaction = TITLEMAP_OFF; + titledemo = false; + automapactive = false; + + // load a base level + if (P_LoadNetGame(reloading)) + { + const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; + CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); + if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, "")) + { + CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl); + if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + CONS_Printf(M_GetText(" Zone")); + if (actnum > 0) + CONS_Printf(" %2d", actnum); + } + CONS_Printf("\"\n"); + } + else + { + CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); + Z_Free(savebuffer); + save_p = NULL; + if (unlink(tmpsave) == -1) + CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); + return; + } + + // done + Z_Free(savebuffer); + save_p = NULL; + if (unlink(tmpsave) == -1) + CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); + consistancy[gametic%BACKUPTICS] = Consistancy(); + CON_ToggleOff(); + + // Tell the server we have received and reloaded the gamestate + // so they know they can resume the game + netbuffer->packettype = PT_RECEIVEDGAMESTATE; + HSendPacket(servernode, true, 0, 0); +} + +static void CL_ReloadReceivedSavegame(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { +#ifdef HAVE_BLUA + LUA_InvalidatePlayer(&players[i]); +#endif + sprintf(player_names[i], "Player %d", i + 1); + } + + CL_LoadReceivedSavegame(true); + + if (neededtic < gametic) + neededtic = gametic; + maketic = neededtic; + + ticcmd_oldangleturn[0] = players[consoleplayer].oldrelangleturn; + P_ForceLocalAngle(&players[consoleplayer], (angle_t)(players[consoleplayer].angleturn << 16)); + if (splitscreen) + { + ticcmd_oldangleturn[1] = players[secondarydisplayplayer].oldrelangleturn; + P_ForceLocalAngle(&players[secondarydisplayplayer], (angle_t)(players[secondarydisplayplayer].angleturn << 16)); + } + + camera.subsector = R_PointInSubsector(camera.x, camera.y); + camera2.subsector = R_PointInSubsector(camera2.x, camera2.y); + + cl_redownloadinggamestate = false; + + CONS_Printf(M_GetText("Game state reloaded\n")); +} +#endif + +#ifndef NONET +static void SendAskInfo(INT32 node) +{ + const tic_t asktime = I_GetTime(); + netbuffer->packettype = PT_ASKINFO; + netbuffer->u.askinfo.version = VERSION; + netbuffer->u.askinfo.time = (tic_t)LONG(asktime); + + // Even if this never arrives due to the host being firewalled, we've + // now allowed traffic from the host to us in, so once the MS relays + // our address to the host, it'll be able to speak to us. + HSendPacket(node, false, 0, sizeof (askinfo_pak)); +} + +serverelem_t serverlist[MAXSERVERLIST]; +UINT32 serverlistcount = 0; + +#define FORCECLOSE 0x8000 + +static void SL_ClearServerList(INT32 connectedserver) +{ + UINT32 i; + + for (i = 0; i < serverlistcount; i++) + if (connectedserver != serverlist[i].node) + { + Net_CloseConnection(serverlist[i].node|FORCECLOSE); + serverlist[i].node = 0; + } + serverlistcount = 0; +} + +static UINT32 SL_SearchServer(INT32 node) +{ + UINT32 i; + for (i = 0; i < serverlistcount; i++) + if (serverlist[i].node == node) + return i; + + return UINT32_MAX; +} + +static void SL_InsertServer(serverinfo_pak* info, SINT8 node) +{ + UINT32 i; + + // search if not already on it + i = SL_SearchServer(node); + if (i == UINT32_MAX) + { + // not found add it + if (serverlistcount >= MAXSERVERLIST) + return; // list full + + if (info->_255 != 255) + return;/* old packet format */ + + if (info->packetversion != PACKETVERSION) + return;/* old new packet format */ + + if (info->version != VERSION) + return; // Not same version. + + if (info->subversion != SUBVERSION) + return; // Close, but no cigar. + + if (strcmp(info->application, SRB2APPLICATION)) + return;/* that's a different mod */ + + i = serverlistcount++; + } + + serverlist[i].info = *info; + serverlist[i].node = node; + + // resort server list + M_SortServerList(); +} + +#if defined (MASTERSERVER) && defined (HAVE_THREADS) +struct Fetch_servers_ctx +{ + int room; + int id; +}; + +static void +Fetch_servers_thread (struct Fetch_servers_ctx *ctx) +{ + msg_server_t *server_list; + + server_list = GetShortServersList(ctx->room, ctx->id); + + if (server_list) + { + I_lock_mutex(&ms_QueryId_mutex); + { + if (ctx->id != ms_QueryId) + { + free(server_list); + server_list = NULL; + } + } + I_unlock_mutex(ms_QueryId_mutex); + + if (server_list) + { + I_lock_mutex(&m_menu_mutex); + { + if (m_waiting_mode == M_WAITING_SERVERS) + m_waiting_mode = M_NOT_WAITING; + } + I_unlock_mutex(m_menu_mutex); + + I_lock_mutex(&ms_ServerList_mutex); + { + ms_ServerList = server_list; + } + I_unlock_mutex(ms_ServerList_mutex); + } + } + + free(ctx); +} +#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ + +void CL_QueryServerList (msg_server_t *server_list) +{ + INT32 i; + + for (i = 0; server_list[i].header.buffer[0]; i++) + { + // Make sure MS version matches our own, to + // thwart nefarious servers who lie to the MS. + + /* lol bruh, that version COMES from the servers */ + //if (strcmp(version, server_list[i].version) == 0) + { + INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port); + if (node == -1) + break; // no more node free + SendAskInfo(node); + // Force close the connection so that servers can't eat + // up nodes forever if we never get a reply back from them + // (usually when they've not forwarded their ports). + // + // Don't worry, we'll get in contact with the working + // servers again when they send SERVERINFO to us later! + // + // (Note: as a side effect this probably means every + // server in the list will probably be using the same node (e.g. node 1), + // not that it matters which nodes they use when + // the connections are closed afterwards anyway) + // -- Monster Iestyn 12/11/18 + Net_CloseConnection(node|FORCECLOSE); + } + } +} + +void CL_UpdateServerList(boolean internetsearch, INT32 room) +{ + (void)internetsearch; + (void)room; + + SL_ClearServerList(0); + + if (!netgame && I_NetOpenSocket) + { + if (I_NetOpenSocket()) + { + netgame = true; + multiplayer = true; + } + } + + // search for local servers + if (netgame) + SendAskInfo(BROADCASTADDR); + +#ifdef MASTERSERVER + if (internetsearch) + { +#ifdef HAVE_THREADS + struct Fetch_servers_ctx *ctx; + + ctx = malloc(sizeof *ctx); + + /* This called from M_Refresh so I don't use a mutex */ + m_waiting_mode = M_WAITING_SERVERS; + + I_lock_mutex(&ms_QueryId_mutex); + { + ctx->id = ms_QueryId; + } + I_unlock_mutex(ms_QueryId_mutex); + + ctx->room = room; + + I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx); +#else + msg_server_t *server_list; + + server_list = GetShortServersList(room, 0); + + if (server_list) + { + CL_QueryServerList(server_list); + free(server_list); + } +#endif + } +#endif/*MASTERSERVER*/ +} + +#endif // ifndef NONET + +/** Called by CL_ServerConnectionTicker + * + * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. + * \return False if the connection was aborted + * \sa CL_ServerConnectionTicker + * \sa CL_ConnectToServer + * + */ +static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) +{ +#ifndef NONET + INT32 i; + + // serverlist is updated by GetPacket function + if (serverlistcount > 0) + { + // this can be a responce to our broadcast request + if (servernode == -1 || servernode >= MAXNETNODES) + { + i = 0; + servernode = serverlist[i].node; + CONS_Printf(M_GetText("Found, ")); + } + else + { + i = SL_SearchServer(servernode); + if (i < 0) + return true; + } + + // Quit here rather than downloading files and being refused later. + if (serverlist[i].info.refusereason) + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + if (serverlist[i].info.refusereason == 1) + M_StartMessage(M_GetText("The server is not accepting\njoins for the moment.\n\nPress ESC\n"), NULL, MM_NOTHING); + else if (serverlist[i].info.refusereason == 2) + M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING); + else + M_StartMessage(M_GetText("You can't join.\nI don't know why,\nbut you can't join.\n\nPress ESC\n"), NULL, MM_NOTHING); + return false; + } + + if (client) + { + D_ParseFileneeded(serverlist[i].info.fileneedednum, + serverlist[i].info.fileneeded); + CONS_Printf(M_GetText("Checking files...\n")); + i = CL_CheckFiles(); + if (i == 3) // too many files + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have too many WAD files loaded\n" + "to add ones the server is using.\n" + "Please restart SRB2 before connecting.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 2) // cannot join for some reason + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have the wrong addons loaded.\n\n" + "To play on this server, restart\n" + "the game and don't load any addons.\n" + "SRB2 will automatically add\n" + "everything you need when you join.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 1) + cl_mode = CL_ASKJOIN; + else + { + // must download something + // can we, though? + if (!CL_CheckDownloadable()) // nope! + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You cannot connect to this server\n" + "because you cannot download the files\n" + "that you are missing from the server.\n\n" + "See the console or log file for\n" + "more details.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + // no problem if can't send packet, we will retry later + if (CL_SendFileRequest()) + { + cl_mode = CL_DOWNLOADFILES; +#ifndef NONET + Snake_Initialise(); +#endif + } + } + } + else + cl_mode = CL_ASKJOIN; // files need not be checked for the server. + + return true; + } + + // Ask the info to the server (askinfo packet) + if (*asksent + NEWTICRATE < I_GetTime()) + { + SendAskInfo(servernode); + *asksent = I_GetTime(); + } +#else + (void)asksent; + // No netgames, so we skip this state. + cl_mode = CL_ASKJOIN; +#endif // ifndef NONET/else + + return true; +} + +/** Called by CL_ConnectToServer + * + * \param tmpsave The name of the gamestate file??? + * \param oldtic Used for knowing when to poll events and redraw + * \param asksent ??? + * \return False if the connection was aborted + * \sa CL_ServerConnectionSearchTicker + * \sa CL_ConnectToServer + * + */ +static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic_t *asksent) +{ + boolean waitmore; + INT32 i; + +#ifdef NONET + (void)tmpsave; +#endif + + switch (cl_mode) + { + case CL_SEARCHING: + if (!CL_ServerConnectionSearchTicker(asksent)) + return false; + break; + + case CL_DOWNLOADFILES: + waitmore = false; + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_DOWNLOADING + || fileneeded[i].status == FS_REQUESTED) + { + waitmore = true; + break; + } + if (waitmore) + break; // exit the case + +#ifndef NONET + if (snake) + { + free(snake); + snake = NULL; + } +#endif + + cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now + /* FALLTHRU */ + + case CL_ASKJOIN: + CL_LoadServerFiles(); +#ifndef NONET + // prepare structures to save the file + // WARNING: this can be useless in case of server not in GS_LEVEL + // but since the network layer doesn't provide ordered packets... + CL_PrepareDownloadSaveGame(tmpsave); +#endif + if (CL_SendJoin()) + cl_mode = CL_WAITJOINRESPONSE; + break; + +#ifndef NONET + case CL_DOWNLOADSAVEGAME: + // At this state, the first (and only) needed file is the gamestate + if (fileneeded[0].status == FS_FOUND) + { + // Gamestate is now handled within CL_LoadReceivedSavegame() + CL_LoadReceivedSavegame(false); + cl_mode = CL_CONNECTED; + } // don't break case continue to CL_CONNECTED + else + break; +#endif + + case CL_WAITJOINRESPONSE: + case CL_CONNECTED: + default: + break; + + // Connection closed by cancel, timeout or refusal. + case CL_ABORTED: + cl_mode = CL_SEARCHING; + return false; + + } + + GetPackets(); + Net_AckTicker(); + + // Call it only once by tic + if (*oldtic != I_GetTime()) + { + I_OsPolling(); + for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) + G_MapEventsToControls(&events[eventtail]); + + if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1]) + { + CONS_Printf(M_GetText("Network game synchronization aborted.\n")); +// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); + +#ifndef NONET + if (snake) + { + free(snake); + snake = NULL; + } +#endif + + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + memset(gamekeydown, 0, NUMKEYS); + return false; + } +#ifndef NONET + else if (cl_mode == CL_DOWNLOADFILES && snake) + Snake_Handle(); +#endif + + if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) + FileReceiveTicker(); + + // why are these here? this is for servers, we're a client + //if (key == 's' && server) + // doomcom->numnodes = (INT16)pnumnodes; + //FileSendTicker(); + *oldtic = I_GetTime(); + +#ifndef NONET + if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) + { + if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME) + { + F_MenuPresTicker(true); // title sky + F_TitleScreenTicker(true); + F_TitleScreenDrawer(); + } + CL_DrawConnectionStatus(); + I_UpdateNoVsync(); // page flip or blit buffer + if (moviemode) + M_SaveFrame(); + S_UpdateSounds(); + S_UpdateClosedCaptions(); + } +#else + CON_Drawer(); + I_UpdateNoVsync(); +#endif + } + else + I_Sleep(); + + return true; +} + +/** Use adaptive send using net_bandwidth and stat.sendbytes + * + * \todo Better description... + * + */ +static void CL_ConnectToServer(void) +{ + INT32 pnumnodes, nodewaited = doomcom->numnodes, i; + tic_t oldtic; +#ifndef NONET + tic_t asksent; + char tmpsave[256]; + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + lastfilenum = -1; +#endif + + cl_mode = CL_SEARCHING; + +#ifndef NONET + // Don't get a corrupt savegame error because tmpsave already exists + if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) + I_Error("Can't delete %s\n", tmpsave); +#endif + + if (netgame) + { + if (servernode < 0 || servernode >= MAXNETNODES) + CONS_Printf(M_GetText("Searching for a server...\n")); + else + CONS_Printf(M_GetText("Contacting the server...\n")); + } + + if (gamestate == GS_INTERMISSION) + Y_EndIntermission(); // clean up intermission graphics etc + + DEBFILE(va("waiting %d nodes\n", doomcom->numnodes)); + G_SetGamestate(GS_WAITINGPLAYERS); + wipegamestate = GS_WAITINGPLAYERS; + + ClearAdminPlayers(); + pnumnodes = 1; + oldtic = I_GetTime() - 1; +#ifndef NONET + asksent = (tic_t) - TICRATE; + + i = SL_SearchServer(servernode); + + if (i != -1) + { + char *gametypestr = serverlist[i].info.gametypename; + CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); + gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0'; + CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); + CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, + serverlist[i].info.version%100, serverlist[i].info.subversion); + } + SL_ClearServerList(servernode); +#endif + + do + { + // If the connection was aborted for some reason, leave +#ifndef NONET + if (!CL_ServerConnectionTicker(tmpsave, &oldtic, &asksent)) +#else + if (!CL_ServerConnectionTicker((char*)NULL, &oldtic, (tic_t *)NULL)) +#endif + return; + + if (server) + { + pnumnodes = 0; + for (i = 0; i < MAXNETNODES; i++) + if (nodeingame[i]) + pnumnodes++; + } + } + while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); + + DEBFILE(va("Synchronisation Finished\n")); + + displayplayer = consoleplayer; +} + +#ifndef NONET +typedef struct banreason_s +{ + char *reason; + struct banreason_s *prev; //-1 + struct banreason_s *next; //+1 +} banreason_t; + +static banreason_t *reasontail = NULL; //last entry, use prev +static banreason_t *reasonhead = NULL; //1st entry, use next + +static void Command_ShowBan(void) //Print out ban list +{ + size_t i; + const char *address, *mask; + banreason_t *reasonlist = reasonhead; + + if (I_GetBanAddress) + CONS_Printf(M_GetText("Ban List:\n")); + else + return; + + for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) + { + if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) + CONS_Printf("%s: %s ", sizeu1(i+1), address); + else + CONS_Printf("%s: %s/%s ", sizeu1(i+1), address, mask); + + if (reasonlist && reasonlist->reason) + CONS_Printf("(%s)\n", reasonlist->reason); + else + CONS_Printf("\n"); + + if (reasonlist) reasonlist = reasonlist->next; + } + + if (i == 0 && !address) + CONS_Printf(M_GetText("(empty)\n")); +} + +void D_SaveBan(void) +{ + FILE *f; + size_t i; + banreason_t *reasonlist = reasonhead; + const char *address, *mask; + + if (!reasonhead) + return; + + f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "w"); + + if (!f) + { + CONS_Alert(CONS_WARNING, M_GetText("Could not save ban list into ban.txt\n")); + return; + } + + for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) + { + if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) + fprintf(f, "%s 0", address); + else + fprintf(f, "%s %s", address, mask); + + if (reasonlist && reasonlist->reason) + fprintf(f, " %s\n", reasonlist->reason); + else + fprintf(f, " %s\n", "NA"); + + if (reasonlist) reasonlist = reasonlist->next; + } + + fclose(f); +} + +static void Ban_Add(const char *reason) +{ + banreason_t *reasonlist = malloc(sizeof(*reasonlist)); + + if (!reasonlist) + return; + if (!reason) + reason = "NA"; + + reasonlist->next = NULL; + reasonlist->reason = Z_StrDup(reason); + if ((reasonlist->prev = reasontail) == NULL) + reasonhead = reasonlist; + else + reasontail->next = reasonlist; + reasontail = reasonlist; +} + +static void Command_ClearBans(void) +{ + banreason_t *temp; + + if (!I_ClearBans) + return; + + I_ClearBans(); + D_SaveBan(); + reasontail = NULL; + while (reasonhead) + { + temp = reasonhead->next; + Z_Free(reasonhead->reason); + free(reasonhead); + reasonhead = temp; + } +} + +static void Ban_Load_File(boolean warning) +{ + FILE *f; + size_t i; + const char *address, *mask; + char buffer[MAX_WADPATH]; + + f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); + + if (!f) + { + if (warning) + CONS_Alert(CONS_WARNING, M_GetText("Could not open ban.txt for ban list\n")); + return; + } + + if (I_ClearBans) + Command_ClearBans(); + else + { + fclose(f); + return; + } + + for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++) + { + address = strtok(buffer, " \t\r\n"); + mask = strtok(NULL, " \t\r\n"); + + I_SetBanAddress(address, mask); + + Ban_Add(strtok(NULL, "\r\n")); + } + + fclose(f); +} + +static void Command_ReloadBan(void) //recheck ban.txt +{ + Ban_Load_File(true); +} + +static void Command_connect(void) +{ + if (COM_Argc() < 2 || *COM_Argv(1) == 0) + { + CONS_Printf(M_GetText( + "Connect (port): connect to a server\n" + "Connect ANY: connect to the first lan server found\n" + //"Connect SELF: connect to your own server.\n" + )); + return; + } + + if (Playing() || titledemo) + { + CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); + return; + } + + // modified game check: no longer handled + // we don't request a restart unless the filelist differs + + server = false; +/* + if (!stricmp(COM_Argv(1), "self")) + { + servernode = 0; + server = true; + /// \bug should be but... + //SV_SpawnServer(); + } + else +*/ + { + // used in menu to connect to a server in the list + if (netgame && !stricmp(COM_Argv(1), "node")) + { + servernode = (SINT8)atoi(COM_Argv(2)); + } + else if (netgame) + { + CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); + return; + } + else if (I_NetOpenSocket) + { + I_NetOpenSocket(); + netgame = true; + multiplayer = true; + + if (!stricmp(COM_Argv(1), "any")) + servernode = BROADCASTADDR; + else if (I_NetMakeNodewPort) + { + if (COM_Argc() >= 3) // address AND port + servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2)); + else // address only, or address:port + servernode = I_NetMakeNode(COM_Argv(1)); + } + else + { + CONS_Alert(CONS_ERROR, M_GetText("There is no server identification with this network driver\n")); + D_CloseConnection(); + return; + } + } + else + CONS_Alert(CONS_ERROR, M_GetText("There is no network driver\n")); + } + + splitscreen = false; + SplitScreen_OnChange(); + botingame = false; + botskin = 0; + CL_ConnectToServer(); +} +#endif + +static void ResetNode(INT32 node); + +// +// CL_ClearPlayer +// +// Clears the player data so that a future client can use this slot +// +void CL_ClearPlayer(INT32 playernum) +{ + if (players[playernum].mo) + P_RemoveMobj(players[playernum].mo); + memset(&players[playernum], 0, sizeof (player_t)); + memset(playeraddress[playernum], 0, sizeof(*playeraddress)); +} + +// +// CL_RemovePlayer +// +// Removes a player from the current game +// +static void CL_RemovePlayer(INT32 playernum, kickreason_t reason) +{ + // Sanity check: exceptional cases (i.e. c-fails) can cause multiple + // kick commands to be issued for the same player. + if (!playeringame[playernum]) + return; + + if (server && !demoplayback && playernode[playernum] != UINT8_MAX) + { + INT32 node = playernode[playernum]; + playerpernode[node]--; + if (playerpernode[node] <= 0) + { + nodeingame[node] = false; + Net_CloseConnection(node); + ResetNode(node); + } + } + + if (gametyperules & GTR_TEAMFLAGS) + P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! + + // If in a special stage, redistribute the player's spheres across + // the remaining players. + if (G_IsSpecialStage(gamemap)) + { + INT32 i, count, sincrement, spheres, rincrement, rings; + + for (i = 0, count = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + count++; + } + + count--; + sincrement = spheres = players[playernum].spheres; + rincrement = rings = players[playernum].rings; + + if (count) + { + sincrement /= count; + rincrement /= count; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && i != playernum) + { + if (spheres < 2*sincrement) + { + P_GivePlayerSpheres(&players[i], spheres); + spheres = 0; + } + else + { + P_GivePlayerSpheres(&players[i], sincrement); + spheres -= sincrement; + } + + if (rings < 2*rincrement) + { + P_GivePlayerRings(&players[i], rings); + rings = 0; + } + else + { + P_GivePlayerRings(&players[i], rincrement); + rings -= rincrement; + } + } + } + } + + LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting + + // don't look through someone's view who isn't there + if (playernum == displayplayer) + { + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); + displayplayer = consoleplayer; + } + + // Reset player data + CL_ClearPlayer(playernum); + + // remove avatar of player + playeringame[playernum] = false; + playernode[playernum] = UINT8_MAX; + while (!playeringame[doomcom->numslots-1] && doomcom->numslots > 1) + doomcom->numslots--; + + // Reset the name + sprintf(player_names[playernum], "Player %d", playernum+1); + + player_name_changes[playernum] = 0; + + if (IsPlayerAdmin(playernum)) + { + RemoveAdminPlayer(playernum); // don't stay admin after you're gone + } + + LUA_InvalidatePlayer(&players[playernum]); + + if (G_TagGametype()) //Check if you still have a game. Location flexible. =P + P_CheckSurvivors(); + else if (gametyperules & GTR_RACE) + P_CheckRacers(); +} + +void CL_Reset(void) +{ + if (metalrecording) + G_StopMetalRecording(false); + if (metalplayback) + G_StopMetalDemo(); + if (demorecording) + G_CheckDemoStatus(); + + // reset client/server code + DEBFILE(va("\n-=-=-=-=-=-=-= Client reset =-=-=-=-=-=-=-\n\n")); + + if (servernode > 0 && servernode < MAXNETNODES) + { + nodeingame[(UINT8)servernode] = false; + Net_CloseConnection(servernode); + } + D_CloseConnection(); // netgame = false + multiplayer = false; + servernode = 0; + server = true; + doomcom->numnodes = 1; + doomcom->numslots = 1; + SV_StopServer(); + SV_ResetServer(); + CV_RevertNetVars(); + + // make sure we don't leave any fileneeded gunk over from a failed join + fileneedednum = 0; + memset(fileneeded, 0, sizeof(fileneeded)); + + // D_StartTitle should get done now, but the calling function will handle it +} + +#ifndef NONET +static void Command_GetPlayerNum(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + if (serverplayer == i) + CONS_Printf(M_GetText("num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); + else + CONS_Printf(M_GetText("\x82num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); + } +} + +SINT8 nametonum(const char *name) +{ + INT32 playernum, i; + + if (!strcmp(name, "0")) + return 0; + + playernum = (SINT8)atoi(name); + + if (playernum < 0 || playernum >= MAXPLAYERS) + return -1; + + if (playernum) + { + if (playeringame[playernum]) + return (SINT8)playernum; + else + return -1; + } + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && !stricmp(player_names[i], name)) + return (SINT8)i; + + CONS_Printf(M_GetText("There is no player named \"%s\"\n"), name); + + return -1; +} + +/** Lists all players and their player numbers. + * + * \sa Command_GetPlayerNum + */ +static void Command_Nodes(void) +{ + INT32 i; + size_t maxlen = 0; + const char *address; + + for (i = 0; i < MAXPLAYERS; i++) + { + const size_t plen = strlen(player_names[i]); + if (playeringame[i] && plen > maxlen) + maxlen = plen; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]); + + if (playernode[i] != UINT8_MAX) + { + CONS_Printf(" - node %.2d", playernode[i]); + if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL) + CONS_Printf(" - %s", address); + } + + if (IsPlayerAdmin(i)) + CONS_Printf(M_GetText(" (verified admin)")); + + if (players[i].spectator) + CONS_Printf(M_GetText(" (spectator)")); + + CONS_Printf("\n"); + } + } +} + +static void Command_Ban(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("Ban : ban and kick a player\n")); + return; + } + + if (!netgame) // Don't kick Tails in splitscreen! + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + + if (server || IsPlayerAdmin(consoleplayer)) + { + UINT8 buf[3 + MAX_REASONLENGTH]; + UINT8 *p = buf; + const SINT8 pn = nametonum(COM_Argv(1)); + const INT32 node = playernode[(INT32)pn]; + + if (pn == -1 || pn == 0) + return; + + WRITEUINT8(p, pn); + + if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now + { + CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); + WRITEUINT8(p, KICK_MSG_GO_AWAY); + SendNetXCmd(XD_KICK, &buf, 2); + } + else + { + if (server) // only the server is allowed to do this right now + { + Ban_Add(COM_Argv(2)); + D_SaveBan(); // save the ban list + } + + if (COM_Argc() == 2) + { + WRITEUINT8(p, KICK_MSG_BANNED); + SendNetXCmd(XD_KICK, &buf, 2); + } + else + { + size_t i, j = COM_Argc(); + char message[MAX_REASONLENGTH]; + + //Steal from the motd code so you don't have to put the reason in quotes. + strlcpy(message, COM_Argv(2), sizeof message); + for (i = 3; i < j; i++) + { + strlcat(message, " ", sizeof message); + strlcat(message, COM_Argv(i), sizeof message); + } + + WRITEUINT8(p, KICK_MSG_CUSTOM_BAN); + WRITESTRINGN(p, message, MAX_REASONLENGTH); + SendNetXCmd(XD_KICK, &buf, p - buf); + } + } + } + else + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); + +} + +static void Command_BanIP(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("banip : ban an ip address\n")); + return; + } + + if (server) // Only the server can use this, otherwise does nothing. + { + const char *address = (COM_Argv(1)); + const char *reason; + + if (COM_Argc() == 2) + reason = NULL; + else + reason = COM_Argv(2); + + + if (I_SetBanAddress && I_SetBanAddress(address, NULL)) + { + if (reason) + CONS_Printf("Banned IP address %s for: %s\n", address, reason); + else + CONS_Printf("Banned IP address %s\n", address); + + Ban_Add(reason); + D_SaveBan(); + } + else + { + return; + } + } +} + +static void Command_Kick(void) +{ + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("kick : kick a player\n")); + return; + } + + //if (!netgame) // Don't kick Tails in splitscreen! + //{ + // CONS_Printf(M_GetText("This only works in a netgame.\n")); + // return; + //} + + if (server || IsPlayerAdmin(consoleplayer)) + { + UINT8 buf[3 + MAX_REASONLENGTH]; + UINT8 *p = buf; + const SINT8 pn = nametonum(COM_Argv(1)); + + if (splitscreen && (pn == 0 || pn == 1)) + { + CONS_Printf(M_GetText("Splitscreen players cannot be kicked.\n")); + return; + } + if (pn == -1 || pn == 0) + return; + + // Special case if we are trying to kick a player who is downloading the game state: + // trigger a timeout instead of kicking them, because a kick would only + // take effect after they have finished downloading + if (server && playernode[pn] != UINT8_MAX && sendingsavegame[playernode[pn]]) + { + Net_ConnectionTimeout(playernode[pn]); + return; + } + + WRITESINT8(p, pn); + + if (COM_Argc() == 2) + { + WRITEUINT8(p, KICK_MSG_GO_AWAY); + SendNetXCmd(XD_KICK, &buf, 2); + } + else + { + size_t i, j = COM_Argc(); + char message[MAX_REASONLENGTH]; + + //Steal from the motd code so you don't have to put the reason in quotes. + strlcpy(message, COM_Argv(2), sizeof message); + for (i = 3; i < j; i++) + { + strlcat(message, " ", sizeof message); + strlcat(message, COM_Argv(i), sizeof message); + } + + WRITEUINT8(p, KICK_MSG_CUSTOM_KICK); + WRITESTRINGN(p, message, MAX_REASONLENGTH); + SendNetXCmd(XD_KICK, &buf, p - buf); + } + } + else + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); +} +#endif + +static void Got_KickCmd(UINT8 **p, INT32 playernum) +{ + INT32 pnum, msg; + char buf[3 + MAX_REASONLENGTH]; + char *reason = buf; + kickreason_t kickreason = KR_KICK; + boolean keepbody; + + pnum = READUINT8(*p); + msg = READUINT8(*p); + keepbody = (msg & KICK_MSG_KEEP_BODY) != 0; + msg &= ~KICK_MSG_KEEP_BODY; + + if (pnum == serverplayer && IsPlayerAdmin(playernum)) + { + CONS_Printf(M_GetText("Server is being shut down remotely. Goodbye!\n")); + + if (server) + COM_BufAddText("quit\n"); + + return; + } + + // Is playernum authorized to make this kick? + if (playernum != serverplayer && !IsPlayerAdmin(playernum) + && !(playernode[playernum] != UINT8_MAX && playerpernode[playernode[playernum]] == 2 + && nodetoplayer2[playernode[playernum]] == pnum)) + { + // We received a kick command from someone who isn't the + // server or admin, and who isn't in splitscreen removing + // player 2. Thus, it must be someone with a modified + // binary, trying to kick someone but without having + // authorization. + + // We deal with this by changing the kick reason to + // "consistency failure" and kicking the offending user + // instead. + + // Note: Splitscreen in netgames is broken because of + // this. Only the server has any idea of which players + // are using splitscreen on the same computer, so + // clients cannot always determine if a kick is + // legitimate. + + CONS_Alert(CONS_WARNING, M_GetText("Illegal kick command received from %s for player %d\n"), player_names[playernum], pnum); + + // In debug, print a longer message with more details. + // TODO Callum: Should we translate this? +/* + CONS_Debug(DBG_NETPLAY, + "So, you must be asking, why is this an illegal kick?\n" + "Well, let's take a look at the facts, shall we?\n" + "\n" + "playernum (this is the guy who did it), he's %d.\n" + "pnum (the guy he's trying to kick) is %d.\n" + "playernum's node is %d.\n" + "That node has %d players.\n" + "Player 2 on that node is %d.\n" + "pnum's node is %d.\n" + "That node has %d players.\n" + "Player 2 on that node is %d.\n" + "\n" + "If you think this is a bug, please report it, including all of the details above.\n", + playernum, pnum, + playernode[playernum], playerpernode[playernode[playernum]], + nodetoplayer2[playernode[playernum]], + playernode[pnum], playerpernode[playernode[pnum]], + nodetoplayer2[playernode[pnum]]); +*/ + pnum = playernum; + msg = KICK_MSG_CON_FAIL; + keepbody = true; + } + + //CONS_Printf("\x82%s ", player_names[pnum]); + + // If a verified admin banned someone, the server needs to know about it. + // If the playernum isn't zero (the server) then the server needs to record the ban. + if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN)) + { + if (I_Ban && !I_Ban(playernode[(INT32)pnum])) + CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); +#ifndef NONET + else + Ban_Add(reason); +#endif + } + + switch (msg) + { + case KICK_MSG_GO_AWAY: + if (!players[pnum].quittime) + HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false); + kickreason = KR_KICK; + break; + case KICK_MSG_PING_HIGH: + HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false); + kickreason = KR_PINGLIMIT; + break; + case KICK_MSG_CON_FAIL: + HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false); + kickreason = KR_SYNCH; + + if (M_CheckParm("-consisdump")) // Helps debugging some problems + { + INT32 i; + + CONS_Printf(M_GetText("Player kicked is #%d, dumping consistency...\n"), pnum); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + CONS_Printf("-------------------------------------\n"); + CONS_Printf("Player %d: %s\n", i, player_names[i]); + CONS_Printf("Skin: %d\n", players[i].skin); + CONS_Printf("Color: %d\n", players[i].skincolor); + CONS_Printf("Speed: %d\n",players[i].speed>>FRACBITS); + if (players[i].mo) + { + if (!players[i].mo->skin) + CONS_Printf("Mobj skin: NULL!\n"); + else + CONS_Printf("Mobj skin: %s\n", ((skin_t *)players[i].mo->skin)->name); + CONS_Printf("Position: %d, %d, %d\n", players[i].mo->x, players[i].mo->y, players[i].mo->z); + if (!players[i].mo->state) + CONS_Printf("State: S_NULL\n"); + else + CONS_Printf("State: %d\n", (statenum_t)(players[i].mo->state-states)); + } + else + CONS_Printf("Mobj: NULL\n"); + CONS_Printf("-------------------------------------\n"); + } + } + break; + case KICK_MSG_TIMEOUT: + HU_AddChatText(va("\x82*%s left the game (Connection timeout)", player_names[pnum]), false); + kickreason = KR_TIMEOUT; + break; + case KICK_MSG_PLAYER_QUIT: + if (netgame && !players[pnum].quittime) // not splitscreen/bots or soulless body + HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false); + kickreason = KR_LEAVE; + break; + case KICK_MSG_BANNED: + HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false); + kickreason = KR_BAN; + break; + case KICK_MSG_CUSTOM_KICK: + READSTRINGN(*p, reason, MAX_REASONLENGTH+1); + HU_AddChatText(va("\x82*%s has been kicked (%s)", player_names[pnum], reason), false); + kickreason = KR_KICK; + break; + case KICK_MSG_CUSTOM_BAN: + READSTRINGN(*p, reason, MAX_REASONLENGTH+1); + HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false); + kickreason = KR_BAN; + break; + } + + if (pnum == consoleplayer) + { + if (Playing()) + LUAh_GameQuit(); +#ifdef DUMPCONSISTENCY + if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); +#endif + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + if (msg == KICK_MSG_CON_FAIL) + M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING); + else if (msg == KICK_MSG_PING_HIGH) + M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING); + else if (msg == KICK_MSG_BANNED) + M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING); + else if (msg == KICK_MSG_CUSTOM_KICK) + M_StartMessage(va(M_GetText("You have been kicked\n(%s)\nPress ESC\n"), reason), NULL, MM_NOTHING); + else if (msg == KICK_MSG_CUSTOM_BAN) + M_StartMessage(va(M_GetText("You have been banned\n(%s)\nPress ESC\n"), reason), NULL, MM_NOTHING); + else + M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING); + } + else if (keepbody) + { + if (server && !demoplayback && playernode[pnum] != UINT8_MAX) + { + INT32 node = playernode[pnum]; + playerpernode[node]--; + if (playerpernode[node] <= 0) + { + nodeingame[node] = false; + Net_CloseConnection(node); + ResetNode(node); + } + } + + playernode[pnum] = UINT8_MAX; + + players[pnum].quittime = 1; + } + else + CL_RemovePlayer(pnum, kickreason); +} + +static void Command_ResendGamestate(void) +{ + SINT8 playernum; + + if (COM_Argc() == 1) + { + CONS_Printf(M_GetText("resendgamestate : resend the game state to a player\n")); + return; + } + else if (client) + { + CONS_Printf(M_GetText("Only the server can use this.\n")); + return; + } + + playernum = nametonum(COM_Argv(1)); + if (playernum == -1 || playernum == 0) + return; + + // Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + if (!HSendPacket(playernode[playernum], true, 0, 0)) + { + CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n")); + return; + } +} + +static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; +consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); + +consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done +static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; +consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); +static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; +consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); +static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; +consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "Off", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL); + +static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; +consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); +consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +// max file size to send to a player (in kilobytes) +static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; +consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); +consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); + +// Speed of file downloading (in packets per tic) +static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; +consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); + +static void Got_AddPlayer(UINT8 **p, INT32 playernum); + +// called one time at init +void D_ClientServerInit(void) +{ + DEBFILE(va("- - -== SRB2 v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n", + VERSION/100, VERSION%100, SUBVERSION)); + +#ifndef NONET + COM_AddCommand("getplayernum", Command_GetPlayerNum); + COM_AddCommand("kick", Command_Kick); + COM_AddCommand("ban", Command_Ban); + COM_AddCommand("banip", Command_BanIP); + COM_AddCommand("clearbans", Command_ClearBans); + COM_AddCommand("showbanlist", Command_ShowBan); + COM_AddCommand("reloadbans", Command_ReloadBan); + COM_AddCommand("connect", Command_connect); + COM_AddCommand("nodes", Command_Nodes); + COM_AddCommand("resendgamestate", Command_ResendGamestate); +#ifdef PACKETDROP + COM_AddCommand("drop", Command_Drop); + COM_AddCommand("droprate", Command_Droprate); +#endif +#ifdef _DEBUG + COM_AddCommand("numnodes", Command_Numnodes); +#endif +#endif + + RegisterNetXCmd(XD_KICK, Got_KickCmd); + RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); +#ifndef NONET +#ifdef DUMPCONSISTENCY + CV_RegisterVar(&cv_dumpconsistency); +#endif + Ban_Load_File(false); +#endif + + gametic = 0; + localgametic = 0; + + // do not send anything before the real begin + SV_StopServer(); + SV_ResetServer(); + if (dedicated) + SV_SpawnServer(); +} + +static void ResetNode(INT32 node) +{ + nodeingame[node] = false; + nodewaiting[node] = 0; + + nettics[node] = gametic; + supposedtics[node] = gametic; + + nodetoplayer[node] = -1; + nodetoplayer2[node] = -1; + playerpernode[node] = 0; + + sendingsavegame[node] = false; + resendingsavegame[node] = false; + savegameresendcooldown[node] = 0; +} + +void SV_ResetServer(void) +{ + INT32 i; + + // +1 because this command will be executed in com_executebuffer in + // tryruntic so gametic will be incremented, anyway maketic > gametic + // is not an issue + + maketic = gametic + 1; + neededtic = maketic; + tictoclear = maketic; + + joindelay = 0; + + for (i = 0; i < MAXNETNODES; i++) + ResetNode(i); + + for (i = 0; i < MAXPLAYERS; i++) + { + LUA_InvalidatePlayer(&players[i]); + playeringame[i] = false; + playernode[i] = UINT8_MAX; + memset(playeraddress[i], 0, sizeof(*playeraddress)); + sprintf(player_names[i], "Player %d", i + 1); + adminplayers[i] = -1; // Populate the entire adminplayers array with -1. + } + + memset(player_name_changes, 0, sizeof player_name_changes); + + mynode = 0; + cl_packetmissed = false; + cl_redownloadinggamestate = false; + + if (dedicated) + { + nodeingame[0] = true; + serverplayer = 0; + } + else + serverplayer = consoleplayer; + + if (server) + servernode = 0; + + doomcom->numslots = 0; + + // clear server_context + memset(server_context, '-', 8); + + DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); +} + +static inline void SV_GenContext(void) +{ + UINT8 i; + // generate server_context, as exactly 8 bytes of randomly mixed A-Z and a-z + // (hopefully M_Random is initialized!! if not this will be awfully silly!) + for (i = 0; i < 8; i++) + { + const char a = M_RandomKey(26*2); + if (a < 26) // uppercase + server_context[i] = 'A'+a; + else // lowercase + server_context[i] = 'a'+(a-26); + } +} + +// +// D_QuitNetGame +// Called before quitting to leave a net game +// without hanging the other players +// +void D_QuitNetGame(void) +{ + if (!netgame || !netbuffer) + return; + + DEBFILE("===========================================================================\n" + " Quitting Game, closing connection\n" + "===========================================================================\n"); + + // abort send/receive of files + CloseNetFile(); + RemoveAllLuaFileTransfers(); + waitingforluafiletransfer = false; + waitingforluafilecommand = false; + + if (server) + { + INT32 i; + + netbuffer->packettype = PT_SERVERSHUTDOWN; + for (i = 0; i < MAXNETNODES; i++) + if (nodeingame[i]) + HSendPacket(i, true, 0, 0); +#ifdef MASTERSERVER + if (serverrunning && ms_RoomId > 0) + UnregisterServer(); +#endif + } + else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]) + { + netbuffer->packettype = PT_CLIENTQUIT; + HSendPacket(servernode, true, 0, 0); + } + + D_CloseConnection(); + ClearAdminPlayers(); + + DEBFILE("===========================================================================\n" + " Log finish\n" + "===========================================================================\n"); +#ifdef DEBUGFILE + if (debugfile) + { + fclose(debugfile); + debugfile = NULL; + } +#endif +} + +// Adds a node to the game (player will follow at map change or at savegame....) +static inline void SV_AddNode(INT32 node) +{ + nettics[node] = gametic; + supposedtics[node] = gametic; + // little hack because the server connects to itself and puts + // nodeingame when connected not here + if (node) + nodeingame[node] = true; +} + +// Xcmd XD_ADDPLAYER +static void Got_AddPlayer(UINT8 **p, INT32 playernum) +{ + INT16 node, newplayernum; + boolean splitscreenplayer; + boolean rejoined; + player_t *newplayer; + + if (playernum != serverplayer && !IsPlayerAdmin(playernum)) + { + // protect against hacked/buggy client + CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]); + if (server) + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + node = READUINT8(*p); + newplayernum = READUINT8(*p); + splitscreenplayer = newplayernum & 0x80; + newplayernum &= ~0x80; + + rejoined = playeringame[newplayernum]; + + if (!rejoined) + { + // Clear player before joining, lest some things get set incorrectly + // HACK: don't do this for splitscreen, it relies on preset values + if (!splitscreen && !botingame) + CL_ClearPlayer(newplayernum); + playeringame[newplayernum] = true; + G_AddPlayer(newplayernum); + if (newplayernum+1 > doomcom->numslots) + doomcom->numslots = (INT16)(newplayernum+1); + + if (server && I_GetNodeAddress) + { + 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'; + } + } + } + + newplayer = &players[newplayernum]; + + newplayer->jointime = 0; + newplayer->quittime = 0; + + READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); + + // the server is creating my player + if (node == mynode) + { + playernode[newplayernum] = 0; // for information only + if (!splitscreenplayer) + { + consoleplayer = newplayernum; + displayplayer = newplayernum; + secondarydisplayplayer = newplayernum; + DEBFILE("spawning me\n"); + ticcmd_oldangleturn[0] = newplayer->oldrelangleturn; + } + else + { + secondarydisplayplayer = newplayernum; + DEBFILE("spawning my brother\n"); + if (botingame) + newplayer->bot = 1; + ticcmd_oldangleturn[1] = newplayer->oldrelangleturn; + } + P_ForceLocalAngle(newplayer, (angle_t)(newplayer->angleturn << 16)); + D_SendPlayerConfig(); + addedtogame = true; + + if (rejoined) + { + if (newplayer->mo) + { + newplayer->viewheight = 41*newplayer->height/48; + + if (newplayer->mo->eflags & MFE_VERTICALFLIP) + newplayer->viewz = newplayer->mo->z + newplayer->mo->height - newplayer->viewheight; + else + newplayer->viewz = newplayer->mo->z + newplayer->viewheight; + } + + // wake up the status bar + ST_Start(); + // wake up the heads up text + HU_Start(); + + if (camera.chase && !splitscreenplayer) + P_ResetCamera(newplayer, &camera); + if (camera2.chase && splitscreenplayer) + P_ResetCamera(newplayer, &camera2); + } + } + + if (netgame) + { + char joinmsg[256]; + + if (rejoined) + strcpy(joinmsg, M_GetText("\x82*%s has rejoined the game (player %d)")); + else + strcpy(joinmsg, M_GetText("\x82*%s has joined the game (player %d)")); + strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum)); + + // Merge join notification + IP to avoid clogging console/chat + if (server && cv_showjoinaddress.value && I_GetNodeAddress) + { + const char *address = I_GetNodeAddress(node); + if (address) + strcat(joinmsg, va(" (%s)", address)); + } + + HU_AddChatText(joinmsg, false); + } + + if (server && multiplayer && motd[0] != '\0') + COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); + + if (!rejoined) + LUAh_PlayerJoin(newplayernum); +} + +static boolean SV_AddWaitingPlayers(const char *name, const char *name2) +{ + INT32 node, n, newplayer = false; + UINT8 buf[2 + MAXPLAYERNAME]; + UINT8 *p; + INT32 newplayernum; + + for (node = 0; node < MAXNETNODES; node++) + { + // splitscreen can allow 2 player in one node + for (; nodewaiting[node] > 0; nodewaiting[node]--) + { + newplayer = true; + + newplayernum = FindRejoinerNum(node); + if (newplayernum == -1) + { + // search for a free playernum + // we can't use playeringame since it is not updated here + for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) + { + if (playeringame[newplayernum]) + continue; + for (n = 0; n < MAXNETNODES; n++) + if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum) + break; + if (n == MAXNETNODES) + break; + } + } + + // should never happen since we check the playernum + // before accepting the join + I_Assert(newplayernum < MAXPLAYERS); + + playernode[newplayernum] = (UINT8)node; + + p = buf + 2; + buf[0] = (UINT8)node; + buf[1] = newplayernum; + if (playerpernode[node] < 1) + { + nodetoplayer[node] = newplayernum; + WRITESTRINGN(p, name, MAXPLAYERNAME); + } + else + { + nodetoplayer2[node] = newplayernum; + buf[1] |= 0x80; + WRITESTRINGN(p, name2, MAXPLAYERNAME); + } + playerpernode[node]++; + + SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); + + DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); + } + } + + return newplayer; +} + +void CL_AddSplitscreenPlayer(void) +{ + if (cl_mode == CL_CONNECTED) + CL_SendJoin(); +} + +void CL_RemoveSplitscreenPlayer(void) +{ + if (cl_mode != CL_CONNECTED) + return; + + SendKick(secondarydisplayplayer, KICK_MSG_PLAYER_QUIT); +} + +// is there a game running +boolean Playing(void) +{ + return (server && serverrunning) || (client && cl_mode == CL_CONNECTED); +} + +boolean SV_SpawnServer(void) +{ + if (demoplayback) + G_StopDemo(); // reset engine parameter + if (metalplayback) + G_StopMetalDemo(); + + if (!serverrunning) + { + CONS_Printf(M_GetText("Starting Server....\n")); + serverrunning = true; + SV_ResetServer(); + SV_GenContext(); + if (netgame && I_NetOpenSocket) + { + I_NetOpenSocket(); +#ifdef MASTERSERVER + if (ms_RoomId > 0) + RegisterServer(); +#endif + } + + // non dedicated server just connect to itself + if (!dedicated) + CL_ConnectToServer(); + else doomcom->numslots = 1; + } + + return SV_AddWaitingPlayers(cv_playername.zstring, cv_playername2.zstring); +} + +void SV_StopServer(void) +{ + tic_t i; + + if (gamestate == GS_INTERMISSION) + Y_EndIntermission(); + gamestate = wipegamestate = GS_NULL; + + localtextcmd[0] = 0; + localtextcmd2[0] = 0; + + for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) + D_Clearticcmd(i); + + consoleplayer = 0; + cl_mode = CL_SEARCHING; + maketic = gametic+1; + neededtic = maketic; + serverrunning = false; +} + +// called at singleplayer start and stopdemo +void SV_StartSinglePlayerServer(void) +{ + server = true; + netgame = false; + multiplayer = false; + G_SetGametype(GT_COOP); + + // no more tic the game with this settings! + SV_StopServer(); + + if (splitscreen) + multiplayer = true; +} + +static void SV_SendRefuse(INT32 node, const char *reason) +{ + strcpy(netbuffer->u.serverrefuse.reason, reason); + + netbuffer->packettype = PT_SERVERREFUSE; + HSendPacket(node, true, 0, strlen(netbuffer->u.serverrefuse.reason) + 1); + Net_CloseConnection(node); +} + +// used at txtcmds received to check packetsize bound +static size_t TotalTextCmdPerTic(tic_t tic) +{ + INT32 i; + size_t total = 1; // num of textcmds in the tic (ntextcmd byte) + + for (i = 0; i < MAXPLAYERS; i++) + { + UINT8 *textcmd = D_GetExistingTextcmd(tic, i); + if ((!i || playeringame[i]) && textcmd) + total += 2 + textcmd[0]; // "+2" for size and playernum + } + + return total; +} + +/** Called when a PT_CLIENTJOIN packet is received + * + * \param node The packet sender + * + */ +static void HandleConnect(SINT8 node) +{ + char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; + INT32 rejoinernum; + INT32 i; + + rejoinernum = FindRejoinerNum(node); + + if (bannednode && bannednode[node]) + SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server.")); + else if (netbuffer->u.clientcfg._255 != 255 || + netbuffer->u.clientcfg.packetversion != PACKETVERSION) + SV_SendRefuse(node, "Incompatible packet formats."); + else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application)) + SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible."); + else if (netbuffer->u.clientcfg.version != VERSION + || netbuffer->u.clientcfg.subversion != SUBVERSION) + SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION)); + else if (!cv_allownewplayer.value && node && rejoinernum == -1) + SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment.")); + else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1) + SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value)); + else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client? + SV_SendRefuse(node, M_GetText("Too many players from\nthis node.")); + else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join? + SV_SendRefuse(node, M_GetText("No players from\nthis node.")); + else if (luafiletransfers) + SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining.")); + else if (netgame && joindelay > 2 * (tic_t)cv_joindelay.value * TICRATE) + SV_SendRefuse(node, va(M_GetText("Too many people are connecting.\nPlease wait %d seconds and then\ntry rejoining."), + (joindelay - 2 * cv_joindelay.value * TICRATE) / TICRATE)); + else + { +#ifndef NONET + boolean newnode = false; +#endif + + for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++) + { + strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); + if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) + { + SV_SendRefuse(node, "Bad player name"); + return; + } + } + + // client authorised to join + nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); + if (!nodeingame[node]) + { + gamestate_t backupstate = gamestate; +#ifndef NONET + newnode = true; +#endif + SV_AddNode(node); + + if (cv_joinnextround.value && gameaction == ga_nothing) + G_SetGamestate(GS_WAITINGPLAYERS); + if (!SV_SendServerConfig(node)) + { + G_SetGamestate(backupstate); + /// \note Shouldn't SV_SendRefuse be called before ResetNode? + ResetNode(node); + SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); + /// \todo fix this !!! + return; // restart the while + } + //if (gamestate != GS_LEVEL) // GS_INTERMISSION, etc? + // SV_SendPlayerConfigs(node); // send bare minimum player info + G_SetGamestate(backupstate); + DEBFILE("new node joined\n"); + } +#ifndef NONET + if (nodewaiting[node]) + { + if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode) + { + SV_SendSaveGame(node, false); // send a complete game state + DEBFILE("send savegame\n"); + } + SV_AddWaitingPlayers(names[0], names[1]); + joindelay += cv_joindelay.value * TICRATE; + player_joining = true; + } +#endif + } +} + +/** Called when a PT_SERVERSHUTDOWN packet is received + * + * \param node The packet sender (should be the server) + * + */ +static void HandleShutdown(SINT8 node) +{ + (void)node; + if (Playing()) + LUAh_GameQuit(); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING); +} + +/** Called when a PT_NODETIMEOUT packet is received + * + * \param node The packet sender (should be the server) + * + */ +static void HandleTimeout(SINT8 node) +{ + (void)node; + if (Playing()) + LUAh_GameQuit(); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); +} + +#ifndef NONET +/** Called when a PT_SERVERINFO packet is received + * + * \param node The packet sender + * \note What happens if the packet comes from a client or something like that? + * + */ +static void HandleServerInfo(SINT8 node) +{ + // compute ping in ms + const tic_t ticnow = I_GetTime(); + const tic_t ticthen = (tic_t)LONG(netbuffer->u.serverinfo.time); + const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; + netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); + netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; + netbuffer->u.serverinfo.application + [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; + netbuffer->u.serverinfo.gametypename + [sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0'; + + SL_InsertServer(&netbuffer->u.serverinfo, node); +} +#endif + +static void PT_WillResendGamestate(void) +{ + char tmpsave[256]; + + if (server || cl_redownloadinggamestate) + return; + + // Send back a PT_CANRECEIVEGAMESTATE packet to the server + // so they know they can start sending the game state + netbuffer->packettype = PT_CANRECEIVEGAMESTATE; + if (!HSendPacket(servernode, true, 0, 0)) + return; + + CONS_Printf(M_GetText("Reloading game state...\n")); + + sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + + // Don't get a corrupt savegame error because tmpsave already exists + if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) + I_Error("Can't delete %s\n", tmpsave); + + CL_PrepareDownloadSaveGame(tmpsave); + + cl_redownloadinggamestate = true; +} + +static void PT_CanReceiveGamestate(SINT8 node) +{ + if (client || sendingsavegame[node]) + return; + + CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]); + + SV_SendSaveGame(node, true); // Resend a complete game state + resendingsavegame[node] = true; +} + +/** Handles a packet received from a node that isn't in game + * + * \param node The packet sender + * \todo Choose a better name, as the packet can also come from the server apparently? + * \sa HandlePacketFromPlayer + * \sa GetPackets + * + */ +static void HandlePacketFromAwayNode(SINT8 node) +{ + if (node != servernode) + DEBFILE(va("Received packet from unknown host %d\n", node)); + +// macro for packets that should only be sent by the server +// if it is NOT from the server, bail out and close the connection! +#define SERVERONLY \ + if (node != servernode) \ + { \ + Net_CloseConnection(node); \ + break; \ + } + switch (netbuffer->packettype) + { + case PT_ASKINFOVIAMS: +#if 0 + if (server && serverrunning) + { + INT32 clientnode; + if (ms_RoomId < 0) // ignore if we're not actually on the MS right now + { + Net_CloseConnection(node); // and yes, close connection + return; + } + clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr); + if (clientnode != -1) + { + SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time)); + SV_SendPlayerInfo(clientnode); // Send extra info + Net_CloseConnection(clientnode); + // Don't close connection to MS... + } + else + Net_CloseConnection(node); // ...unless the IP address is not valid + } + else + Net_CloseConnection(node); // you're not supposed to get it, so ignore it +#else + Net_CloseConnection(node); +#endif + break; + + case PT_ASKINFO: + if (server && serverrunning) + { + SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); + SV_SendPlayerInfo(node); // Send extra info + } + Net_CloseConnection(node); + break; + + case PT_SERVERREFUSE: // Negative response of client join request + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + SERVERONLY + if (cl_mode == CL_WAITJOINRESPONSE) + { + // Save the reason so it can be displayed after quitting the netgame + char *reason = strdup(netbuffer->u.serverrefuse.reason); + if (!reason) + I_Error("Out of memory!\n"); + + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + + M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"), + reason), NULL, MM_NOTHING); + + free(reason); + + // Will be reset by caller. Signals refusal. + cl_mode = CL_ABORTED; + } + break; + + case PT_SERVERCFG: // Positive response of client join request + { + if (server && serverrunning && node != servernode) + { // but wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + SERVERONLY + /// \note how would this happen? and is it doing the right thing if it does? + if (cl_mode != CL_WAITJOINRESPONSE) + break; + + if (client) + { + maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); + G_SetGametype(netbuffer->u.servercfg.gametype); + modifiedgame = netbuffer->u.servercfg.modifiedgame; + memcpy(server_context, netbuffer->u.servercfg.server_context, 8); + } + + nodeingame[(UINT8)servernode] = true; + serverplayer = netbuffer->u.servercfg.serverplayer; + doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); + mynode = netbuffer->u.servercfg.clientnode; + if (serverplayer >= 0) + playernode[(UINT8)serverplayer] = servernode; + + if (netgame) +#ifndef NONET + CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); +#else + CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); +#endif + DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); + +#ifndef NONET + /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? + /// Shouldn't them be downloaded even at intermission time? + /// Also, according to HandleConnect, the server will send the savegame even during intermission... + if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || + netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) + cl_mode = CL_DOWNLOADSAVEGAME; + else +#endif + cl_mode = CL_CONNECTED; + break; + } + + // Handled in d_netfil.c + case PT_FILEFRAGMENT: + if (server) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + SERVERONLY + PT_FileFragment(); + break; + + case PT_FILEACK: + if (server) + PT_FileAck(); + break; + + case PT_FILERECEIVED: + if (server) + PT_FileReceived(); + break; + + case PT_REQUESTFILE: + if (server) + { + if (!cv_downloading.value || !PT_RequestFile(node)) + Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway + } + else + Net_CloseConnection(node); // nope + break; + + case PT_NODETIMEOUT: + case PT_CLIENTQUIT: + if (server) + Net_CloseConnection(node); + break; + + case PT_CLIENTCMD: + break; // This is not an "unknown packet" + + case PT_SERVERTICS: + // Do not remove my own server (we have just get a out of order packet) + if (node == servernode) + break; + /* FALLTHRU */ + + default: + DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); + Net_CloseConnection(node); + break; // Ignore it + + } +#undef SERVERONLY +} + +/** Handles a packet received from a node that is in game + * + * \param node The packet sender + * \todo Choose a better name + * \sa HandlePacketFromAwayNode + * \sa GetPackets + * + */ +static void HandlePacketFromPlayer(SINT8 node) +{ + INT32 netconsole; + tic_t realend, realstart; + UINT8 *pak, *txtpak, numtxtpak; +#ifndef NOMD5 + UINT8 finalmd5[16];/* Well, it's the cool thing to do? */ +#endif + + txtpak = NULL; + + if (dedicated && node == 0) + netconsole = 0; + else + netconsole = nodetoplayer[node]; +#ifdef PARANOIA + if (netconsole >= MAXPLAYERS) + I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); +#endif + + switch (netbuffer->packettype) + { +// -------------------------------------------- SERVER RECEIVE ---------- + case PT_CLIENTCMD: + case PT_CLIENT2CMD: + case PT_CLIENTMIS: + case PT_CLIENT2MIS: + case PT_NODEKEEPALIVE: + case PT_NODEKEEPALIVEMIS: + if (client) + break; + + // To save bytes, only the low byte of tic numbers are sent + // Use ExpandTics to figure out what the rest of the bytes are + realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node); + realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node); + + if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS + || netbuffer->packettype == PT_NODEKEEPALIVEMIS + || supposedtics[node] < realend) + { + supposedtics[node] = realend; + } + // Discard out of order packet + if (nettics[node] > realend) + { + DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node])); + break; + } + + // 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) + 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; + + // Copy ticcmd + G_MoveTiccmd(&netcmds[maketic%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) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); + //D_Clearticcmd(k); + + SendKick(netconsole, KICK_MSG_CON_FAIL); + break; + } + + // Splitscreen cmd + if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) + && nodetoplayer2[node] >= 0) + G_MoveTiccmd(&netcmds[maketic%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) + && !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() + && !SV_ResendingSavegameToAnyone()) + { + if (cv_resynchattempts.value) + { + // Tell the client we are about to resend them the gamestate + netbuffer->packettype = PT_WILLRESENDGAMESTATE; + HSendPacket(node, true, 0, 0); + + resendingsavegame[node] = true; + + if (cv_blamecfail.value) + CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), + netconsole+1, player_names[netconsole], + consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy)); + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + break; + } + else + { + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + break; + } + } + break; + case PT_TEXTCMD2: // splitscreen special + netconsole = nodetoplayer2[node]; + /* FALLTHRU */ + case PT_TEXTCMD: + if (client) + break; + + if (netconsole < 0 || netconsole >= MAXPLAYERS) + Net_UnAcknowledgePacket(node); + else + { + size_t j; + tic_t tic = maketic; + UINT8 *textcmd; + + // ignore if the textcmd has a reported size of zero + // this shouldn't be sent at all + if (!netbuffer->u.textcmd[0]) + { + DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", + node, netconsole)); + Net_UnAcknowledgePacket(node); + break; + } + + // ignore if the textcmd size var is actually larger than it should be + // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength + if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) + { + DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", + netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), + node, netconsole)); + Net_UnAcknowledgePacket(node); + break; + } + + // check if tic that we are making isn't too large else we cannot send it :( + // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time + j = software_MAXPACKETLENGTH + - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE + + (doomcom->numslots+1)*sizeof(ticcmd_t)); + + // search a tic that have enougth space in the ticcmd + while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), + (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) + && tic < firstticstosend + BACKUPTICS) + tic++; + + if (tic >= firstticstosend + BACKUPTICS) + { + DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " + "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), + maketic, firstticstosend, node, netconsole)); + Net_UnAcknowledgePacket(node); + break; + } + + // Make sure we have a buffer + if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); + + DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", + tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); + + M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); + textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; + } + break; + case PT_LOGIN: + if (client) + break; + +#ifndef NOMD5 + if (doomcom->datalength < 16)/* ignore partial sends */ + break; + + if (!adminpasswordset) + { + CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]); + break; + } + + // Do the final pass to compare with the sent md5 + D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", netconsole), &finalmd5); + + if (!memcmp(netbuffer->u.md5sum, finalmd5, 16)) + { + CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]); + COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately + } + else + CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]); +#endif + break; + case PT_NODETIMEOUT: + case PT_CLIENTQUIT: + if (client) + break; + + // nodeingame will be put false in the execution of kick command + // this allow to send some packets to the quitting client to have their ack back + nodewaiting[node] = 0; + if (netconsole != -1 && playeringame[netconsole]) + { + UINT8 kickmsg; + + if (netbuffer->packettype == PT_NODETIMEOUT) + kickmsg = KICK_MSG_TIMEOUT; + else + kickmsg = KICK_MSG_PLAYER_QUIT; + kickmsg |= KICK_MSG_KEEP_BODY; + + SendKick(netconsole, kickmsg); + nodetoplayer[node] = -1; + + if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 + && playeringame[(UINT8)nodetoplayer2[node]]) + { + SendKick(nodetoplayer2[node], kickmsg); + nodetoplayer2[node] = -1; + } + } + Net_CloseConnection(node); + nodeingame[node] = false; + break; + case PT_CANRECEIVEGAMESTATE: + PT_CanReceiveGamestate(node); + break; + case PT_ASKLUAFILE: + if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED) + AddLuaFileToSendQueue(node, luafiletransfers->realfilename); + break; + case PT_HASLUAFILE: + if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING) + SV_HandleLuaFileSent(node); + break; + case PT_RECEIVEDGAMESTATE: + sendingsavegame[node] = false; + resendingsavegame[node] = false; + savegameresendcooldown[node] = I_GetTime() + 15 * TICRATE; + break; +// -------------------------------------------- CLIENT RECEIVE ---------- + case PT_SERVERTICS: + // Only accept PT_SERVERTICS from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); + if (server) + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + break; + } + + realstart = netbuffer->u.serverpak.starttic; + realend = realstart + netbuffer->u.serverpak.numtics; + + if (!txtpak) + txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots + * netbuffer->u.serverpak.numtics]; + + if (realend > gametic + CLIENTBACKUPTICS) + realend = gametic + CLIENTBACKUPTICS; + cl_packetmissed = realstart > neededtic; + + if (realstart <= neededtic && realend > neededtic) + { + tic_t i, j; + pak = (UINT8 *)&netbuffer->u.serverpak.cmds; + + for (i = realstart; i < realend; i++) + { + // clear first + D_Clearticcmd(i); + + // copy the tics + pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, + netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); + + // copy the textcmds + numtxtpak = *txtpak++; + for (j = 0; j < numtxtpak; j++) + { + INT32 k = *txtpak++; // playernum + const size_t txtsize = txtpak[0]+1; + + if (i >= gametic) // Don't copy old net commands + M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); + txtpak += txtsize; + } + } + + neededtic = realend; + } + else + { + DEBFILE(va("frame not in bound: %u\n", neededtic)); + /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) + I_Error("Received an out of order PT_SERVERTICS packet!\n" + "Got tics %d-%d, needed tic %d\n\n" + "Please report this crash on the Master Board,\n" + "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ + } + break; + case PT_PING: + // Only accept PT_PING from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node); + if (server) + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + break; + } + + //Update client ping table from the server. + if (client) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; + + servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS]; + } + + break; + case PT_SERVERCFG: + break; + case PT_FILEFRAGMENT: + // Only accept PT_FILEFRAGMENT from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node); + if (server) + SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + break; + } + if (client) + PT_FileFragment(); + break; + case PT_FILEACK: + if (server) + PT_FileAck(); + break; + case PT_FILERECEIVED: + if (server) + PT_FileReceived(); + break; + case PT_WILLRESENDGAMESTATE: + PT_WillResendGamestate(); + break; + case PT_SENDINGLUAFILE: + if (client) + CL_PrepareDownloadLuaFile(); + break; + default: + DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n", + netbuffer->packettype, node)); + } // end switch +} + +/** Handles all received packets, if any + * + * \todo Add details to this description (lol) + * + */ +static void GetPackets(void) +{ + SINT8 node; // The packet sender + + player_joining = false; + + while (HGetPacket()) + { + node = (SINT8)doomcom->remotenode; + + if (netbuffer->packettype == PT_CLIENTJOIN && server) + { + HandleConnect(node); + continue; + } + if (node == servernode && client && cl_mode != CL_SEARCHING) + { + if (netbuffer->packettype == PT_SERVERSHUTDOWN) + { + HandleShutdown(node); + continue; + } + if (netbuffer->packettype == PT_NODETIMEOUT) + { + HandleTimeout(node); + continue; + } + } + +#ifndef NONET + if (netbuffer->packettype == PT_SERVERINFO) + { + HandleServerInfo(node); + continue; + } +#endif + + if (netbuffer->packettype == PT_PLAYERINFO) + continue; // We do nothing with PLAYERINFO, that's for the MS browser. + + // Packet received from someone already playing + if (nodeingame[node]) + HandlePacketFromPlayer(node); + // Packet received from someone not playing + else + HandlePacketFromAwayNode(node); + } +} + +// +// NetUpdate +// Builds ticcmds for console player, +// sends out a packet +// +// no more use random generator, because at very first tic isn't yet synchronized +// Note: It is called consistAncy on purpose. +// +static INT16 Consistancy(void) +{ + INT32 i; + UINT32 ret = 0; +#ifdef MOBJCONSISTANCY + thinker_t *th; + mobj_t *mo; +#endif + + DEBFILE(va("TIC %u ", gametic)); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + ret ^= 0xCCCC; + else if (!players[i].mo); + else + { + ret += players[i].mo->x; + ret -= players[i].mo->y; + ret += players[i].powers[pw_shield]; + ret *= i+1; + } + } + // I give up + // Coop desynching enemies is painful + if (!G_PlatformGametype()) + ret += P_GetRandSeed(); + +#ifdef MOBJCONSISTANCY + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; + + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) + { + ret -= mo->type; + ret += mo->x; + ret -= mo->y; + ret += mo->z; + ret -= mo->momx; + ret += mo->momy; + ret -= mo->momz; + ret += mo->angle; + ret -= mo->flags; + ret += mo->flags2; + ret -= mo->eflags; + if (mo->target) + { + ret += mo->target->type; + ret -= mo->target->x; + ret += mo->target->y; + ret -= mo->target->z; + ret += mo->target->momx; + ret -= mo->target->momy; + ret += mo->target->momz; + ret -= mo->target->angle; + ret += mo->target->flags; + ret -= mo->target->flags2; + ret += mo->target->eflags; + ret -= mo->target->state - states; + ret += mo->target->tics; + ret -= mo->target->sprite; + ret += mo->target->frame; + } + else + ret ^= 0x3333; + if (mo->tracer && mo->tracer->type != MT_OVERLAY) + { + ret += mo->tracer->type; + ret -= mo->tracer->x; + ret += mo->tracer->y; + ret -= mo->tracer->z; + ret += mo->tracer->momx; + ret -= mo->tracer->momy; + ret += mo->tracer->momz; + ret -= mo->tracer->angle; + ret += mo->tracer->flags; + ret -= mo->tracer->flags2; + ret += mo->tracer->eflags; + ret -= mo->tracer->state - states; + ret += mo->tracer->tics; + ret -= mo->tracer->sprite; + ret += mo->tracer->frame; + } + else + ret ^= 0xAAAA; + ret -= mo->state - states; + ret += mo->tics; + ret -= mo->sprite; + ret += mo->frame; + } + } +#endif + + DEBFILE(va("Consistancy = %u\n", (ret & 0xFFFF))); + + return (INT16)(ret & 0xFFFF); +} + +// send the client packet to the server +static void CL_SendClientCmd(void) +{ + size_t packetsize = 0; + + netbuffer->packettype = PT_CLIENTCMD; + + if (cl_packetmissed) + netbuffer->packettype++; + 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; + packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); + HSendPacket(servernode, false, 0, packetsize); + } + else if (gamestate != GS_NULL && (addedtogame || dedicated)) + { + 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); + packetsize = sizeof (client2cmd_pak); + } + else + packetsize = sizeof (clientcmd_pak); + + HSendPacket(servernode, false, 0, packetsize); + } + + if (cl_mode == CL_CONNECTED || dedicated) + { + // Send extra data if needed + if (localtextcmd[0]) + { + netbuffer->packettype = PT_TEXTCMD; + 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; + } + + // Send extra data if needed for player 2 (splitscreen) + if (localtextcmd2[0]) + { + netbuffer->packettype = PT_TEXTCMD2; + M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... + localtextcmd2[0] = 0; + } + } +} + +// send the server packet +// send tic from firstticstosend to maketic-1 +static void SV_SendTics(void) +{ + tic_t realfirsttic, lasttictosend, i; + UINT32 n; + INT32 j; + size_t packsize; + UINT8 *bufpos; + UINT8 *ntextcmd; + + // send to all client but not to me + // for each node create a packet with x tics and send it + // x is computed using supposedtics[n], max packet size and maketic + for (n = 1; n < MAXNETNODES; n++) + if (nodeingame[n]) + { + // assert supposedtics[n]>=nettics[n] + realfirsttic = supposedtics[n]; + lasttictosend = min(maketic, nettics[n] + CLIENTBACKUPTICS); + + if (realfirsttic >= lasttictosend) + { + // well we have sent all tics we will so use extrabandwidth + // to resent packet that are supposed lost (this is necessary since lost + // packet detection work when we have received packet with firsttic > neededtic + // (getpacket servertics case) + DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", + n, maketic, supposedtics[n], nettics[n])); + realfirsttic = nettics[n]; + if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) + // all tic are ok + continue; + DEBFILE(va("Sent %d anyway\n", realfirsttic)); + } + if (realfirsttic < firstticstosend) + realfirsttic = firstticstosend; + + // compute the length of the packet and cut it if too large + packsize = BASESERVERTICSSIZE; + for (i = realfirsttic; i < lasttictosend; i++) + { + packsize += sizeof (ticcmd_t) * doomcom->numslots; + packsize += TotalTextCmdPerTic(i); + + if (packsize > software_MAXPACKETLENGTH) + { + DEBFILE(va("packet too large (%s) at tic %d (should be from %d to %d)\n", + sizeu1(packsize), i, realfirsttic, lasttictosend)); + lasttictosend = i; + + // too bad: too much player have send extradata and there is too + // much data in one tic. + // To avoid it put the data on the next tic. (see getpacket + // textcmd case) but when numplayer changes the computation can be different + if (lasttictosend == realfirsttic) + { + if (packsize > MAXPACKETLENGTH) + I_Error("Too many players: can't send %s data for %d players to node %d\n" + "Well sorry nobody is perfect....\n", + sizeu1(packsize), doomcom->numslots, n); + else + { + lasttictosend++; // send it anyway! + DEBFILE("sending it anyway\n"); + } + } + break; + } + } + + // Send the tics + netbuffer->packettype = PT_SERVERTICS; + netbuffer->u.serverpak.starttic = realfirsttic; + netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic); + netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots); + bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds; + + for (i = realfirsttic; i < lasttictosend; i++) + { + bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); + } + + // add textcmds + for (i = realfirsttic; i < lasttictosend; i++) + { + ntextcmd = bufpos++; + *ntextcmd = 0; + for (j = 0; j < MAXPLAYERS; j++) + { + UINT8 *textcmd = D_GetExistingTextcmd(i, j); + INT32 size = textcmd ? textcmd[0] : 0; + + if ((!j || playeringame[j]) && size) + { + (*ntextcmd)++; + WRITEUINT8(bufpos, j); + M_Memcpy(bufpos, textcmd, size + 1); + bufpos += size + 1; + } + } + } + packsize = bufpos - (UINT8 *)&(netbuffer->u); + + HSendPacket(n, false, 0, packsize); + // when tic are too large, only one tic is sent so don't go backward! + if (lasttictosend-doomcom->extratics > realfirsttic) + supposedtics[n] = lasttictosend-doomcom->extratics; + else + supposedtics[n] = lasttictosend; + if (supposedtics[n] < nettics[n]) supposedtics[n] = nettics[n]; + } + // node 0 is me! + supposedtics[0] = maketic; +} + +// +// TryRunTics +// +static void Local_Maketic(INT32 realtics) +{ + I_OsPolling(); // I_Getevent + D_ProcessEvents(); // menu responder, cons responder, + // game responder calls HU_Responder, AM_Responder, + // and G_MapEventsToControls + if (!dedicated) rendergametic = gametic; + // translate inputs (keyboard/mouse/joystick) into game controls + G_BuildTiccmd(&localcmds, realtics, 1); + if (splitscreen || botingame) + G_BuildTiccmd(&localcmds2, realtics, 2); + + localcmds.angleturn |= TICCMD_RECEIVED; + localcmds2.angleturn |= TICCMD_RECEIVED; +} + +// create missed tic +static void SV_Maketic(void) +{ + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + // We didn't receive this tic + if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0) + { + ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i]; + ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i]; + + if (players[i].quittime) + { + // Copy the angle/aiming from the previous tic + // and empty the other inputs + memset(ticcmd, 0, sizeof(netcmds[0][0])); + ticcmd->angleturn = prevticcmd->angleturn | TICCMD_RECEIVED; + ticcmd->aiming = prevticcmd->aiming; + } + else + { + DEBFILE(va("MISS tic%4d for player %d\n", maketic, i)); + // Copy the input from the previous tic + *ticcmd = *prevticcmd; + ticcmd->angleturn &= ~TICCMD_RECEIVED; + } + } + } + + // all tic are now proceed make the next + maketic++; +} + +void TryRunTics(tic_t realtics) +{ + // the machine has lagged but it is not so bad + if (realtics > TICRATE/7) // FIXME: consistency failure!! + { + if (server) + realtics = 1; + else + realtics = TICRATE/7; + } + + if (singletics) + realtics = 1; + + if (realtics >= 1) + { + COM_BufTicker(); + if (mapchangepending) + D_MapChange(-1, 0, ultimatemode, false, 2, false, fromlevelselect); // finish the map change + } + + NetUpdate(); + + if (demoplayback) + { + neededtic = gametic + (realtics * cv_playbackspeed.value); + // start a game after a demo + maketic += realtics; + firstticstosend = maketic; + tictoclear = firstticstosend; + } + + GetPackets(); + +#ifdef DEBUGFILE + if (debugfile && (realtics || neededtic > gametic)) + { + //SoM: 3/30/2000: Need long INT32 in the format string for args 4 & 5. + //Shut up stupid warning! + fprintf(debugfile, "------------ Tryruntic: REAL:%d NEED:%d GAME:%d LOAD: %d\n", + realtics, neededtic, gametic, debugload); + debugload = 100000; + } +#endif + + if (player_joining) + return; + + if (neededtic > gametic) + { + if (advancedemo) + { + if (timedemo_quit) + COM_ImmedExecute("quit"); + else + D_StartTitle(); + } + else + // run the count * tics + while (neededtic > gametic) + { + DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic)); + + ps_tictime = I_GetTimeMicros(); + + G_Ticker((gametic % NEWTICRATERATIO) == 0); + ExtraDataTicker(); + gametic++; + consistancy[gametic%BACKUPTICS] = Consistancy(); + + ps_tictime = I_GetTimeMicros() - ps_tictime; + + // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. + if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) + break; + } + } +} + +/* +Ping Update except better: +We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. +If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. +*/ + +static INT32 pingtimeout[MAXPLAYERS]; + +static inline void PingUpdate(void) +{ + INT32 i; + boolean laggers[MAXPLAYERS]; + UINT8 numlaggers = 0; + memset(laggers, 0, sizeof(boolean) * MAXPLAYERS); + + netbuffer->packettype = PT_PING; + + //check for ping limit breakage. + if (cv_maxping.value) + { + for (i = 1; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].quittime + && (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value)) + { + if (players[i].jointime > 30 * TICRATE) + laggers[i] = true; + numlaggers++; + } + else + pingtimeout[i] = 0; + } + + //kick lagging players... unless everyone but the server's ping sucks. + //in that case, it is probably the server's fault. + if (numlaggers < D_NumPlayers() - 1) + { + for (i = 1; i < MAXPLAYERS; i++) + { + if (playeringame[i] && laggers[i]) + { + pingtimeout[i]++; + // ok your net has been bad for too long, you deserve to die. + if (pingtimeout[i] > cv_pingtimeout.value) + { + pingtimeout[i] = 0; + SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY); + } + } + /* + you aren't lagging, + but you aren't free yet. + In case you'll keep spiking, + we just make the timer go back down. (Very unstable net must still get kicked). + */ + else + pingtimeout[i] = (pingtimeout[i] == 0 ? 0 : pingtimeout[i]-1); + } + } + } + + //make the ping packet and clear server data for next one + for (i = 0; i < MAXPLAYERS; i++) + { + netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; + //server takes a snapshot of the real ping for display. + //otherwise, pings fluctuate a lot and would be odd to look at. + playerpingtable[i] = realpingtable[i] / pingmeasurecount; + realpingtable[i] = 0; //Reset each as we go. + } + + // send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked. + netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value; + + //send out our ping packets + for (i = 0; i < MAXNETNODES; i++) + if (nodeingame[i]) + HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); + + pingmeasurecount = 1; //Reset count +} + +void NetUpdate(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) + { + if (netgame && !(gametime % 35)) // update once per second. + PingUpdate(); + // update node latency values so we can take an average later. + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && playernode[i] != UINT8_MAX) + realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); + pingmeasurecount++; + } + + if (client) + maketic = neededtic; + + Local_Maketic(realtics); // make local tic, and call menu? + + if (server) + CL_SendClientCmd(); // send it + + GetPackets(); // get packet from client or from server + + // client send the command after a receive of the server + // the server send before because in single player is beter + +#ifdef MASTERSERVER + MasterClient_Ticker(); // Acking the Master Server +#endif + + if (client) + { + // If the client just finished redownloading the game state, load it + if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND) + CL_ReloadReceivedSavegame(); + + CL_SendClientCmd(); // Send tic cmd + hu_redownloadinggamestate = cl_redownloadinggamestate; + } + else + { + if (!demoplayback) + { + 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; + + if (maketic + counts >= firstticstosend + BACKUPTICS) + counts = firstticstosend+BACKUPTICS-maketic-1; + + for (i = 0; i < counts; i++) + SV_Maketic(); // Create missed tics and increment maketic + + for (; tictoclear < firstticstosend; tictoclear++) // Clear only when acknowledged + D_Clearticcmd(tictoclear); // Clear the maketic the new tic + + SV_SendTics(); + + neededtic = maketic; // The server is a client too + } + } + + 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); + } + + nowtime /= NEWTICRATERATIO; + if (nowtime > resptime) + { + resptime = nowtime; +#ifdef HAVE_THREADS + I_lock_mutex(&m_menu_mutex); +#endif + M_Ticker(); +#ifdef HAVE_THREADS + I_unlock_mutex(m_menu_mutex); +#endif + CON_Ticker(); + } + + FileSendTicker(); +} + +/** Returns the number of players playing. + * \return Number of players. Can be zero if we're running a ::dedicated + * server. + * \author Graue + */ +INT32 D_NumPlayers(void) +{ + INT32 num = 0, ix; + for (ix = 0; ix < MAXPLAYERS; ix++) + if (playeringame[ix]) + num++; + return num; +} + +tic_t GetLag(INT32 node) +{ + return gametic - nettics[node]; +} + +void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest) +{ +#ifdef NOMD5 + (void)buffer; + (void)len; + (void)salt; + memset(dest, 0, 16); +#else + char tmpbuf[256]; + const size_t sl = strlen(salt); + + if (len > 256-sl) + len = 256-sl; + + memcpy(tmpbuf, buffer, len); + memmove(&tmpbuf[len], salt, sl); + //strcpy(&tmpbuf[len], salt); + len += strlen(salt); + if (len < 256) + memset(&tmpbuf[len],0,256-len); + + // Yes, we intentionally md5 the ENTIRE buffer regardless of size... + md5_buffer(tmpbuf, 256, dest); +#endif +} From edc312066dbb7b3dc7c222c490d76f836c70eb6e Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 22:01:51 +0000 Subject: [PATCH 032/241] =?UTF-8?q?Revert=20"CL=5FRemovePlayer()=20-=20All?= =?UTF-8?q?ow=20for=20removal=20of=20non-consoleplayer=20and=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f166af4d8b7805e1ce5688cbef386f6ddc6e3ec1 --- src/r_skins.c | 5810 +++++++------------------------------------------ 1 file changed, 760 insertions(+), 5050 deletions(-) diff --git a/src/r_skins.c b/src/r_skins.c index 88b4d9387..155a64700 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -1,5 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2020 by Sonic Team Junior. // @@ -7,5117 +8,826 @@ // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file d_clisrv.c -/// \brief SRB2 Network game communication and protocol, all OS independent parts. +/// \file r_skins.c +/// \brief Loading skins -#include -#ifdef __GNUC__ -#include //for unlink -#endif - -#include "i_net.h" -#include "i_system.h" -#include "i_video.h" -#include "d_net.h" -#include "d_main.h" -#include "g_game.h" -#include "st_stuff.h" -#include "hu_stuff.h" -#include "keys.h" -#include "g_input.h" // JOY1 -#include "m_menu.h" +#include "doomdef.h" #include "console.h" -#include "d_netfil.h" -#include "byteptr.h" -#include "p_saveg.h" -#include "z_zone.h" -#include "p_local.h" -#include "m_misc.h" -#include "am_map.h" -#include "m_random.h" -#include "mserv.h" -#include "y_inter.h" +#include "g_game.h" #include "r_local.h" -#include "m_argv.h" -#include "p_setup.h" -#include "lzf.h" -#include "lua_script.h" -#include "lua_hook.h" -#include "md5.h" -#include "m_perfstats.h" +#include "st_stuff.h" +#include "w_wad.h" +#include "z_zone.h" +#include "m_misc.h" +#include "info.h" // spr2names +#include "i_video.h" // rendermode +#include "i_system.h" +#include "r_things.h" +#include "r_skins.h" +#include "p_local.h" +#include "dehacked.h" // get_number (for thok) +#include "m_cond.h" +#ifdef HWRENDER +#include "hardware/hw_md2.h" +#endif -#ifndef NONET -// cl loading screen -#include "v_video.h" -#include "f_finale.h" +INT32 numskins = 0; +skin_t skins[MAXSKINS]; + +// FIXTHIS: don't work because it must be inistilised before the config load +//#define SKINVALUES +#ifdef SKINVALUES +CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; #endif // -// NETWORKING +// P_GetSkinSprite2 +// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. +// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. // -// gametic is the tic about to (or currently being) run -// Server: -// maketic is the tic that hasn't had control made for it yet -// nettics is the tic for each node -// firstticstosend is the lowest value of nettics -// Client: -// neededtic is the tic needed by the client to run the game -// firstticstosend is used to optimize a condition -// Normally maketic >= gametic > 0 -#define PREDICTIONQUEUE BACKUPTICS -#define PREDICTIONMASK (PREDICTIONQUEUE-1) -#define MAX_REASONLENGTH 30 - -boolean server = true; // true or false but !server == client -#define client (!server) -boolean nodownload = false; -boolean serverrunning = false; -INT32 serverplayer = 0; -char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support) - -// Server specific vars -UINT8 playernode[MAXPLAYERS]; -char playeraddress[MAXPLAYERS][64]; - -// Minimum timeout for sending the savegame -// The actual timeout will be longer depending on the savegame length -tic_t jointimeout = (10*TICRATE); -static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame? -static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame? -static tic_t savegameresendcooldown[MAXNETNODES]; // How long before we can resend again? -static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout? - -// Incremented by cv_joindelay when a client joins, decremented each tic. -// If higher than cv_joindelay * 2 (3 joins in a short timespan), joins are temporarily disabled. -static tic_t joindelay = 0; - -UINT16 pingmeasurecount = 1; -UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. -UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. -SINT8 nodetoplayer[MAXNETNODES]; -SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) -UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen -boolean nodeingame[MAXNETNODES]; // set false as nodes leave game -tic_t servermaxping = 800; // server's max ping. Defaults to 800 -static tic_t nettics[MAXNETNODES]; // what tic the client have received -static tic_t supposedtics[MAXNETNODES]; // nettics prevision for smaller packet -static UINT8 nodewaiting[MAXNETNODES]; -static tic_t firstticstosend; // min of the nettics -static tic_t tictoclear = 0; // optimize d_clearticcmd -static tic_t maketic; - -static INT16 consistancy[BACKUPTICS]; - -static UINT8 player_joining = false; -UINT8 hu_redownloadinggamestate = 0; - -UINT8 adminpassmd5[16]; -boolean adminpasswordset = false; - -// Client specific -static ticcmd_t localcmds; -static ticcmd_t localcmds2; -static boolean cl_packetmissed; -// here it is for the secondary local player (splitscreen) -static UINT8 mynode; // my address pointofview server -static boolean cl_redownloadinggamestate = false; - -static UINT8 localtextcmd[MAXTEXTCMD]; -static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen -static tic_t neededtic; -SINT8 servernode = 0; // the number of the server node -/// \brief do we accept new players? -/// \todo WORK! -boolean acceptnewnode = true; - -// engine - -// Must be a power of two -#define TEXTCMD_HASH_SIZE 4 - -typedef struct textcmdplayer_s +UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) { - INT32 playernum; - UINT8 cmd[MAXTEXTCMD]; - struct textcmdplayer_s *next; -} textcmdplayer_t; + UINT8 super = 0, i = 0; -typedef struct textcmdtic_s -{ - tic_t tic; - textcmdplayer_t *playercmds[TEXTCMD_HASH_SIZE]; - struct textcmdtic_s *next; -} textcmdtic_t; - -ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; -static textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; - - -consvar_t cv_showjoinaddress = CVAR_INIT ("showjoinaddress", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; -consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); - -static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n) -{ - const size_t d = n / sizeof(ticcmd_t); - const size_t r = n % sizeof(ticcmd_t); - UINT8 *ret = dest; - - if (r) - M_Memcpy(dest, src, n); - else if (d) - G_MoveTiccmd(dest, src, d); - return ret+n; -} - -static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n) -{ - const size_t d = n / sizeof(ticcmd_t); - const size_t r = n % sizeof(ticcmd_t); - UINT8 *ret = src; - - if (r) - M_Memcpy(dest, src, n); - else if (d) - G_MoveTiccmd(dest, src, d); - return ret+n; -} - - - -// Some software don't support largest packet -// (original sersetup, not exactely, but the probability of sending a packet -// of 512 bytes is like 0.1) -UINT16 software_MAXPACKETLENGTH; - -/** Guesses the full value of a tic from its lowest byte, for a specific node - * - * \param low The lowest byte of the tic value - * \param node The node to deduce the tic for - * \return The full tic value - * - */ -tic_t ExpandTics(INT32 low, INT32 node) -{ - INT32 delta; - - delta = low - (nettics[node] & UINT8_MAX); - - if (delta >= -64 && delta <= 64) - return (nettics[node] & ~UINT8_MAX) + low; - else if (delta > 64) - return (nettics[node] & ~UINT8_MAX) - 256 + low; - else //if (delta < -64) - return (nettics[node] & ~UINT8_MAX) + 256 + low; -} - -// ----------------------------------------------------------------- -// Some extra data function for handle textcmd buffer -// ----------------------------------------------------------------- - -static void (*listnetxcmd[MAXNETXCMD])(UINT8 **p, INT32 playernum); - -void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) -{ -#ifdef PARANOIA - if (id >= MAXNETXCMD) - I_Error("Command id %d too big", id); - if (listnetxcmd[id] != 0) - I_Error("Command id %d already used", id); -#endif - listnetxcmd[id] = cmd_f; -} - -void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam) -{ - if (localtextcmd[0]+2+nparam > MAXTEXTCMD) - { - // for future reference: if (cv_debug) != debug disabled. - CONS_Alert(CONS_ERROR, M_GetText("NetXCmd buffer full, cannot add netcmd %d! (size: %d, needed: %s)\n"), id, localtextcmd[0], sizeu1(nparam)); - return; - } - localtextcmd[0]++; - localtextcmd[localtextcmd[0]] = (UINT8)id; - if (param && nparam) - { - M_Memcpy(&localtextcmd[localtextcmd[0]+1], param, nparam); - localtextcmd[0] = (UINT8)(localtextcmd[0] + (UINT8)nparam); - } -} - -// splitscreen player -void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) -{ - if (localtextcmd2[0]+2+nparam > MAXTEXTCMD) - { - I_Error("No more place in the buffer for netcmd %d\n",id); - return; - } - localtextcmd2[0]++; - localtextcmd2[localtextcmd2[0]] = (UINT8)id; - if (param && nparam) - { - M_Memcpy(&localtextcmd2[localtextcmd2[0]+1], param, nparam); - localtextcmd2[0] = (UINT8)(localtextcmd2[0] + (UINT8)nparam); - } -} - -UINT8 GetFreeXCmdSize(void) -{ - // -1 for the size and another -1 for the ID. - return (UINT8)(localtextcmd[0] - 2); -} - -// Frees all textcmd memory for the specified tic -static void D_FreeTextcmd(tic_t tic) -{ - textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdtic_t *textcmdtic = *tctprev; - - while (textcmdtic && textcmdtic->tic != tic) - { - tctprev = &textcmdtic->next; - textcmdtic = textcmdtic->next; - } - - if (textcmdtic) - { - INT32 i; - - // Remove this tic from the list. - *tctprev = textcmdtic->next; - - // Free all players. - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) - { - textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i]; - - while (textcmdplayer) - { - textcmdplayer_t *tcpnext = textcmdplayer->next; - Z_Free(textcmdplayer); - textcmdplayer = tcpnext; - } - } - - // Free this tic's own memory. - Z_Free(textcmdtic); - } -} - -// Gets the buffer for the specified ticcmd, or NULL if there isn't one -static UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) -{ - textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - while (textcmdtic && textcmdtic->tic != tic) textcmdtic = textcmdtic->next; - - // Do we have an entry for the tic? If so, look for player. - if (textcmdtic) - { - textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; - while (textcmdplayer && textcmdplayer->playernum != playernum) textcmdplayer = textcmdplayer->next; - - if (textcmdplayer) return textcmdplayer->cmd; - } - - return NULL; -} - -// Gets the buffer for the specified ticcmd, creating one if necessary -static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) -{ - textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdplayer_t *textcmdplayer, **tcpprev; - - // Look for the tic. - while (textcmdtic && textcmdtic->tic != tic) - { - tctprev = &textcmdtic->next; - textcmdtic = textcmdtic->next; - } - - // If we don't have an entry for the tic, make it. - if (!textcmdtic) - { - textcmdtic = *tctprev = Z_Calloc(sizeof (textcmdtic_t), PU_STATIC, NULL); - textcmdtic->tic = tic; - } - - tcpprev = &textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; - textcmdplayer = *tcpprev; - - // Look for the player. - while (textcmdplayer && textcmdplayer->playernum != playernum) - { - tcpprev = &textcmdplayer->next; - textcmdplayer = textcmdplayer->next; - } - - // If we don't have an entry for the player, make it. - if (!textcmdplayer) - { - textcmdplayer = *tcpprev = Z_Calloc(sizeof (textcmdplayer_t), PU_STATIC, NULL); - textcmdplayer->playernum = playernum; - } - - return textcmdplayer->cmd; -} - -static void ExtraDataTicker(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] || i == 0) - { - UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); - - if (bufferstart) - { - UINT8 *curpos = bufferstart; - UINT8 *bufferend = &curpos[curpos[0]+1]; - - curpos++; - while (curpos < bufferend) - { - if (*curpos < MAXNETXCMD && listnetxcmd[*curpos]) - { - const UINT8 id = *curpos; - curpos++; - DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i)); - (listnetxcmd[id])(&curpos, i); - DEBFILE("done\n"); - } - else - { - if (server) - { - SendKick(i, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic)); - } - CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]); - break; - } - } - } - } - - // If you are a client, you can safely forget the net commands for this tic - // If you are the server, you need to remember them until every client has been acknowledged, - // because if you need to resend a PT_SERVERTICS packet, you will need to put the commands in it - if (client) - D_FreeTextcmd(gametic); -} - -static void D_Clearticcmd(tic_t tic) -{ - INT32 i; - - D_FreeTextcmd(tic); - - for (i = 0; i < MAXPLAYERS; i++) - netcmds[tic%BACKUPTICS][i].angleturn = 0; - - DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); -} - -void D_ResetTiccmds(void) -{ - INT32 i; - - memset(&localcmds, 0, sizeof(ticcmd_t)); - memset(&localcmds2, 0, sizeof(ticcmd_t)); - - // Reset the net command list - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) - while (textcmds[i]) - D_Clearticcmd(textcmds[i]->tic); -} - -void SendKick(UINT8 playernum, UINT8 msg) -{ - UINT8 buf[2]; - - if (!(server && cv_rejointimeout.value)) - msg &= ~KICK_MSG_KEEP_BODY; - - buf[0] = playernum; - buf[1] = msg; - SendNetXCmd(XD_KICK, &buf, 2); -} - -// ----------------------------------------------------------------- -// end of extra data function -// ----------------------------------------------------------------- - -// ----------------------------------------------------------------- -// extra data function for lmps -// ----------------------------------------------------------------- - -// if extradatabit is set, after the ziped tic you find this: -// -// type | description -// ---------+-------------- -// byte | size of the extradata -// byte | the extradata (xd) bits: see XD_... -// with this byte you know what parameter folow -// if (xd & XDNAMEANDCOLOR) -// byte | color -// char[MAXPLAYERNAME] | name of the player -// endif -// if (xd & XD_WEAPON_PREF) -// byte | original weapon switch: boolean, true if use the old -// | weapon switch methode -// char[NUMWEAPONS] | the weapon switch priority -// byte | autoaim: true if use the old autoaim system -// endif -/*boolean AddLmpExtradata(UINT8 **demo_point, INT32 playernum) -{ - UINT8 *textcmd = D_GetExistingTextcmd(gametic, playernum); - - if (!textcmd) - return false; - - M_Memcpy(*demo_point, textcmd, textcmd[0]+1); - *demo_point += textcmd[0]+1; - return true; -} - -void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum) -{ - UINT8 nextra; - UINT8 *textcmd; - - if (!demo_pointer) - return; - - textcmd = D_GetTextcmd(gametic, playernum); - nextra = **demo_pointer; - M_Memcpy(textcmd, *demo_pointer, nextra + 1); - // increment demo pointer - *demo_pointer += nextra + 1; -}*/ - -// ----------------------------------------------------------------- -// end extra data function for lmps -// ----------------------------------------------------------------- - -static INT16 Consistancy(void); - -typedef enum -{ - CL_SEARCHING, - CL_DOWNLOADFILES, - CL_ASKJOIN, - CL_WAITJOINRESPONSE, - CL_DOWNLOADSAVEGAME, - CL_CONNECTED, - CL_ABORTED -} cl_mode_t; - -static void GetPackets(void); - -static cl_mode_t cl_mode = CL_SEARCHING; - -#ifndef NONET -#define SNAKE_SPEED 5 - -#define SNAKE_NUM_BLOCKS_X 20 -#define SNAKE_NUM_BLOCKS_Y 10 -#define SNAKE_BLOCK_SIZE 12 -#define SNAKE_BORDER_SIZE 12 - -#define SNAKE_MAP_WIDTH (SNAKE_NUM_BLOCKS_X * SNAKE_BLOCK_SIZE) -#define SNAKE_MAP_HEIGHT (SNAKE_NUM_BLOCKS_Y * SNAKE_BLOCK_SIZE) - -#define SNAKE_LEFT_X ((BASEVIDWIDTH - SNAKE_MAP_WIDTH) / 2 - SNAKE_BORDER_SIZE) -#define SNAKE_RIGHT_X (SNAKE_LEFT_X + SNAKE_MAP_WIDTH + SNAKE_BORDER_SIZE * 2 - 1) -#define SNAKE_BOTTOM_Y (BASEVIDHEIGHT - 48) -#define SNAKE_TOP_Y (SNAKE_BOTTOM_Y - SNAKE_MAP_HEIGHT - SNAKE_BORDER_SIZE * 2 + 1) - -enum snake_bonustype_s { - SNAKE_BONUS_NONE = 0, - SNAKE_BONUS_SLOW, - SNAKE_BONUS_FAST, - SNAKE_BONUS_GHOST, - SNAKE_BONUS_NUKE, - SNAKE_BONUS_SCISSORS, - SNAKE_BONUS_REVERSE, - SNAKE_BONUS_EGGMAN, - SNAKE_NUM_BONUSES, -}; - -static const char *snake_bonuspatches[] = { - NULL, - "DL_SLOW", - "TVSSC0", - "TVIVC0", - "TVARC0", - "DL_SCISSORS", - "TVRCC0", - "TVEGC0", -}; - -static const char *snake_backgrounds[] = { - "RVPUMICF", - "FRSTRCKF", - "TAR", - "MMFLRB4", - "RVDARKF1", - "RVZWALF1", - "RVZWALF4", - "RVZWALF5", - "RVZGRS02", - "RVZGRS04", -}; - -typedef struct snake_s -{ - boolean paused; - boolean pausepressed; - tic_t time; - tic_t nextupdate; - boolean gameover; - UINT8 background; - - UINT16 snakelength; - enum snake_bonustype_s snakebonus; - tic_t snakebonustime; - UINT8 snakex[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - UINT8 snakey[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - UINT8 snakedir[SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y]; - - UINT8 applex; - UINT8 appley; - - enum snake_bonustype_s bonustype; - UINT8 bonusx; - UINT8 bonusy; -} snake_t; - -static snake_t *snake = NULL; - -static void Snake_Initialise(void) -{ - if (!snake) - snake = malloc(sizeof(snake_t)); - - snake->paused = false; - snake->pausepressed = false; - snake->time = 0; - snake->nextupdate = SNAKE_SPEED; - snake->gameover = false; - snake->background = M_RandomKey(sizeof(snake_backgrounds) / sizeof(*snake_backgrounds)); - - snake->snakelength = 1; - snake->snakebonus = SNAKE_BONUS_NONE; - snake->snakex[0] = M_RandomKey(SNAKE_NUM_BLOCKS_X); - snake->snakey[0] = M_RandomKey(SNAKE_NUM_BLOCKS_Y); - snake->snakedir[0] = 0; - snake->snakedir[1] = 0; - - snake->applex = M_RandomKey(SNAKE_NUM_BLOCKS_X); - snake->appley = M_RandomKey(SNAKE_NUM_BLOCKS_Y); - - snake->bonustype = SNAKE_BONUS_NONE; -} - -static UINT8 Snake_GetOppositeDir(UINT8 dir) -{ - if (dir == 1 || dir == 3) - return dir + 1; - else if (dir == 2 || dir == 4) - return dir - 1; - else - return 12 + 5 - dir; -} - -static void Snake_FindFreeSlot(UINT8 *freex, UINT8 *freey, UINT8 headx, UINT8 heady) -{ - UINT8 x, y; - UINT16 i; - - do - { - x = M_RandomKey(SNAKE_NUM_BLOCKS_X); - y = M_RandomKey(SNAKE_NUM_BLOCKS_Y); - - for (i = 0; i < snake->snakelength; i++) - if (x == snake->snakex[i] && y == snake->snakey[i]) - break; - } while (i < snake->snakelength || (x == headx && y == heady) - || (x == snake->applex && y == snake->appley) - || (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy)); - - *freex = x; - *freey = y; -} - -static void Snake_Handle(void) -{ - UINT8 x, y; - UINT8 oldx, oldy; - UINT16 i; - - // Handle retry - if (snake->gameover && (PLAYER1INPUTDOWN(gc_jump) || gamekeydown[KEY_ENTER])) - { - Snake_Initialise(); - snake->pausepressed = true; // Avoid accidental pause on respawn - } - - // Handle pause - if (PLAYER1INPUTDOWN(gc_pause) || gamekeydown[KEY_ENTER]) - { - if (!snake->pausepressed) - snake->paused = !snake->paused; - snake->pausepressed = true; - } - else - snake->pausepressed = false; - - if (snake->paused) - return; - - snake->time++; - - x = snake->snakex[0]; - y = snake->snakey[0]; - oldx = snake->snakex[1]; - oldy = snake->snakey[1]; - - // Update direction - if (gamekeydown[KEY_LEFTARROW]) - { - if (snake->snakelength < 2 || x <= oldx) - snake->snakedir[0] = 1; - } - else if (gamekeydown[KEY_RIGHTARROW]) - { - if (snake->snakelength < 2 || x >= oldx) - snake->snakedir[0] = 2; - } - else if (gamekeydown[KEY_UPARROW]) - { - if (snake->snakelength < 2 || y <= oldy) - snake->snakedir[0] = 3; - } - else if (gamekeydown[KEY_DOWNARROW]) - { - if (snake->snakelength < 2 || y >= oldy) - snake->snakedir[0] = 4; - } - - if (snake->snakebonustime) - { - snake->snakebonustime--; - if (!snake->snakebonustime) - snake->snakebonus = SNAKE_BONUS_NONE; - } - - snake->nextupdate--; - if (snake->nextupdate) - return; - if (snake->snakebonus == SNAKE_BONUS_SLOW) - snake->nextupdate = SNAKE_SPEED * 2; - else if (snake->snakebonus == SNAKE_BONUS_FAST) - snake->nextupdate = SNAKE_SPEED * 2 / 3; - else - snake->nextupdate = SNAKE_SPEED; - - if (snake->gameover) - return; - - // Find new position - switch (snake->snakedir[0]) - { - case 1: - if (x > 0) - x--; - else - snake->gameover = true; - break; - case 2: - if (x < SNAKE_NUM_BLOCKS_X - 1) - x++; - else - snake->gameover = true; - break; - case 3: - if (y > 0) - y--; - else - snake->gameover = true; - break; - case 4: - if (y < SNAKE_NUM_BLOCKS_Y - 1) - y++; - else - snake->gameover = true; - break; - } - - // Check collision with snake - if (snake->snakebonus != SNAKE_BONUS_GHOST) - for (i = 1; i < snake->snakelength - 1; i++) - if (x == snake->snakex[i] && y == snake->snakey[i]) - { - if (snake->snakebonus == SNAKE_BONUS_SCISSORS) - { - snake->snakebonus = SNAKE_BONUS_NONE; - snake->snakelength = i; - S_StartSound(NULL, sfx_adderr); - } - else - snake->gameover = true; - } - - if (snake->gameover) - { - S_StartSound(NULL, sfx_lose); - return; - } - - // Check collision with apple - if (x == snake->applex && y == snake->appley) - { - if (snake->snakelength + 3 < SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y) - { - snake->snakelength++; - snake->snakex [snake->snakelength - 1] = snake->snakex [snake->snakelength - 2]; - snake->snakey [snake->snakelength - 1] = snake->snakey [snake->snakelength - 2]; - snake->snakedir[snake->snakelength - 1] = snake->snakedir[snake->snakelength - 2]; - } - - // Spawn new apple - Snake_FindFreeSlot(&snake->applex, &snake->appley, x, y); - - // Spawn new bonus - if (!(snake->snakelength % 5)) - { - do - { - snake->bonustype = M_RandomKey(SNAKE_NUM_BONUSES - 1) + 1; - } while (snake->snakelength > SNAKE_NUM_BLOCKS_X * SNAKE_NUM_BLOCKS_Y * 3 / 4 - && (snake->bonustype == SNAKE_BONUS_EGGMAN || snake->bonustype == SNAKE_BONUS_FAST || snake->bonustype == SNAKE_BONUS_REVERSE)); - - Snake_FindFreeSlot(&snake->bonusx, &snake->bonusy, x, y); - } - - S_StartSound(NULL, sfx_s3k6b); - } - - if (snake->snakelength > 1 && snake->snakedir[0]) - { - UINT8 dir = snake->snakedir[0]; - - oldx = snake->snakex[1]; - oldy = snake->snakey[1]; - - // Move - for (i = snake->snakelength - 1; i > 0; i--) - { - snake->snakex[i] = snake->snakex[i - 1]; - snake->snakey[i] = snake->snakey[i - 1]; - snake->snakedir[i] = snake->snakedir[i - 1]; - } - - // Handle corners - if (x < oldx && dir == 3) - dir = 5; - else if (x > oldx && dir == 3) - dir = 6; - else if (x < oldx && dir == 4) - dir = 7; - else if (x > oldx && dir == 4) - dir = 8; - else if (y < oldy && dir == 1) - dir = 9; - else if (y < oldy && dir == 2) - dir = 10; - else if (y > oldy && dir == 1) - dir = 11; - else if (y > oldy && dir == 2) - dir = 12; - snake->snakedir[1] = dir; - } - - snake->snakex[0] = x; - snake->snakey[0] = y; - - // Check collision with bonus - if (snake->bonustype != SNAKE_BONUS_NONE && x == snake->bonusx && y == snake->bonusy) - { - S_StartSound(NULL, sfx_ncchip); - - switch (snake->bonustype) - { - case SNAKE_BONUS_SLOW: - snake->snakebonus = SNAKE_BONUS_SLOW; - snake->snakebonustime = 20 * TICRATE; - break; - case SNAKE_BONUS_FAST: - snake->snakebonus = SNAKE_BONUS_FAST; - snake->snakebonustime = 20 * TICRATE; - break; - case SNAKE_BONUS_GHOST: - snake->snakebonus = SNAKE_BONUS_GHOST; - snake->snakebonustime = 10 * TICRATE; - break; - case SNAKE_BONUS_NUKE: - for (i = 0; i < snake->snakelength; i++) - { - snake->snakex [i] = snake->snakex [0]; - snake->snakey [i] = snake->snakey [0]; - snake->snakedir[i] = snake->snakedir[0]; - } - - S_StartSound(NULL, sfx_bkpoof); - break; - case SNAKE_BONUS_SCISSORS: - snake->snakebonus = SNAKE_BONUS_SCISSORS; - snake->snakebonustime = 60 * TICRATE; - break; - case SNAKE_BONUS_REVERSE: - for (i = 0; i < (snake->snakelength + 1) / 2; i++) - { - UINT16 i2 = snake->snakelength - 1 - i; - UINT8 tmpx = snake->snakex [i]; - UINT8 tmpy = snake->snakey [i]; - UINT8 tmpdir = snake->snakedir[i]; - - // Swap first segment with last segment - snake->snakex [i] = snake->snakex [i2]; - snake->snakey [i] = snake->snakey [i2]; - snake->snakedir[i] = Snake_GetOppositeDir(snake->snakedir[i2]); - snake->snakex [i2] = tmpx; - snake->snakey [i2] = tmpy; - snake->snakedir[i2] = Snake_GetOppositeDir(tmpdir); - } - - snake->snakedir[0] = 0; - - S_StartSound(NULL, sfx_gravch); - break; - default: - if (snake->snakebonus != SNAKE_BONUS_GHOST) - { - snake->gameover = true; - S_StartSound(NULL, sfx_lose); - } - } - - snake->bonustype = SNAKE_BONUS_NONE; - } -} - -static void Snake_Draw(void) -{ - INT16 i; - - // Background - V_DrawFlatFill( - SNAKE_LEFT_X + SNAKE_BORDER_SIZE, - SNAKE_TOP_Y + SNAKE_BORDER_SIZE, - SNAKE_MAP_WIDTH, - SNAKE_MAP_HEIGHT, - W_GetNumForName(snake_backgrounds[snake->background]) - ); - - // Borders - V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Top - V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_TOP_Y, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Right - V_DrawFill(SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, SNAKE_BORDER_SIZE + SNAKE_MAP_WIDTH, SNAKE_BORDER_SIZE, 242); // Bottom - V_DrawFill(SNAKE_LEFT_X, SNAKE_TOP_Y + SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE, SNAKE_BORDER_SIZE + SNAKE_MAP_HEIGHT, 242); // Left - - // Apple - V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->applex * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->appley * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - FRACUNIT / 4, - 0, - W_CachePatchLongName("DL_APPLE", PU_HUDGFX), - NULL - ); - - // Bonus - if (snake->bonustype != SNAKE_BONUS_NONE) - V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->bonusx * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 ) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->bonusy * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2 + 4) * FRACUNIT, - FRACUNIT / 2, - 0, - W_CachePatchLongName(snake_bonuspatches[snake->bonustype], PU_HUDGFX), - NULL - ); - - // Snake - if (!snake->gameover || snake->time % 8 < 8 / 2) // Blink if game over - { - for (i = snake->snakelength - 1; i >= 0; i--) - { - const char *patchname; - UINT8 dir = snake->snakedir[i]; - - if (i == 0) // Head - { - switch (dir) - { - case 1: patchname = "DL_SNAKEHEAD_L"; break; - case 2: patchname = "DL_SNAKEHEAD_R"; break; - case 3: patchname = "DL_SNAKEHEAD_T"; break; - case 4: patchname = "DL_SNAKEHEAD_B"; break; - default: patchname = "DL_SNAKEHEAD_M"; - } - } - else // Body - { - switch (dir) - { - case 1: patchname = "DL_SNAKEBODY_L"; break; - case 2: patchname = "DL_SNAKEBODY_R"; break; - case 3: patchname = "DL_SNAKEBODY_T"; break; - case 4: patchname = "DL_SNAKEBODY_B"; break; - case 5: patchname = "DL_SNAKEBODY_LT"; break; - case 6: patchname = "DL_SNAKEBODY_RT"; break; - case 7: patchname = "DL_SNAKEBODY_LB"; break; - case 8: patchname = "DL_SNAKEBODY_RB"; break; - case 9: patchname = "DL_SNAKEBODY_TL"; break; - case 10: patchname = "DL_SNAKEBODY_TR"; break; - case 11: patchname = "DL_SNAKEBODY_BL"; break; - case 12: patchname = "DL_SNAKEBODY_BR"; break; - default: patchname = "DL_SNAKEBODY_B"; - } - } - - V_DrawFixedPatch( - (SNAKE_LEFT_X + SNAKE_BORDER_SIZE + snake->snakex[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - (SNAKE_TOP_Y + SNAKE_BORDER_SIZE + snake->snakey[i] * SNAKE_BLOCK_SIZE + SNAKE_BLOCK_SIZE / 2) * FRACUNIT, - i == 0 && dir == 0 ? FRACUNIT / 5 : FRACUNIT / 2, - snake->snakebonus == SNAKE_BONUS_GHOST ? V_TRANSLUCENT : 0, - W_CachePatchLongName(patchname, PU_HUDGFX), - NULL - ); - } - } - - // Length - V_DrawString(SNAKE_RIGHT_X + 4, SNAKE_TOP_Y, V_MONOSPACE, va("%u", snake->snakelength)); - - // Bonus - if (snake->snakebonus != SNAKE_BONUS_NONE - && (snake->snakebonustime >= 3 * TICRATE || snake->time % 4 < 4 / 2)) - V_DrawFixedPatch( - (SNAKE_RIGHT_X + 10) * FRACUNIT, - (SNAKE_TOP_Y + 24) * FRACUNIT, - FRACUNIT / 2, - 0, - W_CachePatchLongName(snake_bonuspatches[snake->snakebonus], PU_HUDGFX), - NULL - ); -} - -// -// CL_DrawConnectionStatus -// -// Keep the local client informed of our status. -// -static inline void CL_DrawConnectionStatus(void) -{ - INT32 ccstime = I_GetTime(); - - // Draw background fade - if (!menuactive) // menu already draws its own fade - V_DrawFadeScreen(0xFF00, 16); // force default - - // Draw the bottom box. - M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort"); - - if (cl_mode != CL_DOWNLOADFILES) - { - INT32 i, animtime = ((ccstime / 4) & 15) + 16; - UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96; - // 15 pal entries total. - const char *cltext; - - if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1)) - for (i = 0; i < 16; ++i) - V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15)); - - switch (cl_mode) - { - case CL_DOWNLOADSAVEGAME: - if (lastfilenum != -1) - { - UINT32 currentsize = fileneeded[lastfilenum].currentsize; - UINT32 totalsize = fileneeded[lastfilenum].totalsize; - INT32 dldlength; - - cltext = M_GetText("Downloading game state..."); - Net_GetNetStat(); - - dldlength = (INT32)((currentsize/(double)totalsize) * 256); - if (dldlength > 256) - dldlength = 256; - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); - - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va(" %4uK/%4uK",currentsize>>10,totalsize>>10)); - - V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va("%3.1fK/s ", ((double)getbps)/1024)); - } - else - cltext = M_GetText("Waiting to download game state..."); - break; - case CL_ASKJOIN: - case CL_WAITJOINRESPONSE: - cltext = M_GetText("Requesting to join..."); - break; - default: - cltext = M_GetText("Connecting to server..."); - break; - } - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, cltext); - } - else - { - if (lastfilenum != -1) - { - INT32 dldlength; - static char tempname[28]; - fileneeded_t *file = &fileneeded[lastfilenum]; - char *filename = file->filename; - - Snake_Draw(); - - Net_GetNetStat(); - dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); - if (dldlength > 256) - dldlength = 256; - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96); - - memset(tempname, 0, sizeof(tempname)); - // offset filename to just the name only part - filename += strlen(filename) - nameonlylength(filename); - - if (strlen(filename) > sizeof(tempname)-1) // too long to display fully - { - size_t endhalfpos = strlen(filename)-10; - // display as first 14 chars + ... + last 10 chars - // which should add up to 27 if our math(s) is correct - snprintf(tempname, sizeof(tempname), "%.14s...%.10s", filename, filename+endhalfpos); - } - else // we can copy the whole thing in safely - { - strncpy(tempname, filename, sizeof(tempname)-1); - } - - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, - va(M_GetText("Downloading \"%s\""), tempname)); - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10)); - V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE, - va("%3.1fK/s ", ((double)getbps)/1024)); - } - else - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, - M_GetText("Waiting to download files...")); - } -} -#endif - -/** Sends a special packet to declare how many players in local - * Used only in arbitratrenetstart() - * Sends a PT_CLIENTJOIN packet to the server - * - * \return True if the packet was successfully sent - * \todo Improve the description... - * Because to be honest, I have no idea what arbitratrenetstart is... - * Is it even used...? - * - */ -static boolean CL_SendJoin(void) -{ - UINT8 localplayers = 1; - if (netgame) - CONS_Printf(M_GetText("Sending join request...\n")); - netbuffer->packettype = PT_CLIENTJOIN; - - if (splitscreen || botingame) - localplayers++; - netbuffer->u.clientcfg.localplayers = localplayers; - netbuffer->u.clientcfg._255 = 255; - netbuffer->u.clientcfg.packetversion = PACKETVERSION; - netbuffer->u.clientcfg.version = VERSION; - netbuffer->u.clientcfg.subversion = SUBVERSION; - strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, - sizeof netbuffer->u.clientcfg.application); - - CleanupPlayerName(consoleplayer, cv_playername.zstring); - if (splitscreen) - CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */ - - strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); - strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME); - - return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); -} - -static INT32 FindRejoinerNum(SINT8 node) -{ - char strippednodeaddress[64]; - const char *nodeaddress; - char *port; - INT32 i; - - // Make sure there is no dead dress before proceeding to the stripping - if (!I_GetNodeAddress) - return -1; - nodeaddress = I_GetNodeAddress(node); - if (!nodeaddress) - return -1; - - // Strip the address of its port - strcpy(strippednodeaddress, nodeaddress); - port = strchr(strippednodeaddress, ':'); - if (port) - *port = '\0'; - - // Check if any player matches the stripped address - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX - && !strcmp(playeraddress[i], strippednodeaddress)) - return i; - } - - return -1; -} - -static void SV_SendServerInfo(INT32 node, tic_t servertime) -{ - UINT8 *p; - - netbuffer->packettype = PT_SERVERINFO; - netbuffer->u.serverinfo._255 = 255; - netbuffer->u.serverinfo.packetversion = PACKETVERSION; - netbuffer->u.serverinfo.version = VERSION; - netbuffer->u.serverinfo.subversion = SUBVERSION; - strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION, - sizeof netbuffer->u.serverinfo.application); - // return back the time value so client can compute their ping - netbuffer->u.serverinfo.time = (tic_t)LONG(servertime); - netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime); - - netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); - netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; - - if (!node || FindRejoinerNum(node) != -1) - netbuffer->u.serverinfo.refusereason = 0; - else if (!cv_allownewplayer.value) - netbuffer->u.serverinfo.refusereason = 1; - else if (D_NumPlayers() >= cv_maxplayers.value) - netbuffer->u.serverinfo.refusereason = 2; - else - netbuffer->u.serverinfo.refusereason = 0; - - strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], - sizeof netbuffer->u.serverinfo.gametypename); - netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; - netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); - netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated; - strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, - MAXSERVERNAME); - strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); - - M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16); - - memset(netbuffer->u.serverinfo.maptitle, 0, sizeof netbuffer->u.serverinfo.maptitle); - - if (mapheaderinfo[gamemap-1] && *mapheaderinfo[gamemap-1]->lvlttl) - { - char *read = mapheaderinfo[gamemap-1]->lvlttl, *writ = netbuffer->u.serverinfo.maptitle; - while (writ < (netbuffer->u.serverinfo.maptitle+32) && *read != '\0') - { - if (!(*read & 0x80)) - { - *writ = toupper(*read); - writ++; - } - read++; - } - *writ = '\0'; - //strncpy(netbuffer->u.serverinfo.maptitle, (char *)mapheaderinfo[gamemap-1]->lvlttl, 33); - } - else - strncpy(netbuffer->u.serverinfo.maptitle, "UNKNOWN", 32); - - if (mapheaderinfo[gamemap-1] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - netbuffer->u.serverinfo.iszone = 1; - else - netbuffer->u.serverinfo.iszone = 0; - - if (mapheaderinfo[gamemap-1]) - netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum; - - p = PutFileNeeded(); - - HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); -} - -static void SV_SendPlayerInfo(INT32 node) -{ - UINT8 i; - netbuffer->packettype = PT_PLAYERINFO; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - { - netbuffer->u.playerinfo[i].num = 255; // This slot is empty. - continue; - } - - netbuffer->u.playerinfo[i].num = i; - strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); - netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; - - //fetch IP address - //No, don't do that, you fuckface. - memset(netbuffer->u.playerinfo[i].address, 0, 4); - - if (G_GametypeHasTeams()) - { - if (!players[i].ctfteam) - netbuffer->u.playerinfo[i].team = 255; - else - netbuffer->u.playerinfo[i].team = (UINT8)players[i].ctfteam; - } - else - { - if (players[i].spectator) - netbuffer->u.playerinfo[i].team = 255; - else - netbuffer->u.playerinfo[i].team = 0; - } - - netbuffer->u.playerinfo[i].score = LONG(players[i].score); - netbuffer->u.playerinfo[i].timeinserver = SHORT((UINT16)(players[i].jointime / TICRATE)); - netbuffer->u.playerinfo[i].skin = (UINT8)(players[i].skin -#ifdef DEVELOP // it's safe to do this only because PLAYERINFO isn't read by the game itself - % 3 -#endif - ); - - // Extra data - netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor; - - if (players[i].pflags & PF_TAGIT) - netbuffer->u.playerinfo[i].data |= 0x20; - - if (players[i].gotflag) - netbuffer->u.playerinfo[i].data |= 0x40; - - if (players[i].powers[pw_super]) - netbuffer->u.playerinfo[i].data |= 0x80; - } - - HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); -} - -/** Sends a PT_SERVERCFG packet - * - * \param node The destination - * \return True if the packet was successfully sent - * - */ -static boolean SV_SendServerConfig(INT32 node) -{ - boolean waspacketsent; - - netbuffer->packettype = PT_SERVERCFG; - - netbuffer->u.servercfg.version = VERSION; - netbuffer->u.servercfg.subversion = SUBVERSION; - - netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer; - netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots); - netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic); - netbuffer->u.servercfg.clientnode = (UINT8)node; - netbuffer->u.servercfg.gamestate = (UINT8)gamestate; - netbuffer->u.servercfg.gametype = (UINT8)gametype; - netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; - - memcpy(netbuffer->u.servercfg.server_context, server_context, 8); - - { - const size_t len = sizeof (serverconfig_pak); - -#ifdef DEBUGFILE - if (debugfile) - { - fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n", - sizeu1(len), node); - } -#endif - - waspacketsent = HSendPacket(node, true, 0, len); - } - -#ifdef DEBUGFILE - if (debugfile) - { - if (waspacketsent) - { - fprintf(debugfile, "ServerConfig Packet was sent\n"); - } - else - { - fprintf(debugfile, "ServerConfig Packet could not be sent right now\n"); - } - } -#endif - - return waspacketsent; -} - -#ifndef NONET -#define SAVEGAMESIZE (768*1024) - -static boolean SV_ResendingSavegameToAnyone(void) -{ - INT32 i; - - for (i = 0; i < MAXNETNODES; i++) - if (resendingsavegame[i]) - return true; - return false; -} - -static void SV_SendSaveGame(INT32 node, boolean resending) -{ - size_t length, compressedlen; - UINT8 *savebuffer; - UINT8 *compressedsave; - UINT8 *buffertosend; - - // first save it in a malloced buffer - savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!savebuffer) - { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); - return; - } - - // Leave room for the uncompressed length. - save_p = savebuffer + sizeof(UINT32); - - P_SaveNetGame(resending); - - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } - - // Allocate space for compressed save: one byte fewer than for the - // uncompressed data to ensure that the compression is worthwhile. - compressedsave = malloc(length - 1); - if (!compressedsave) - { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); - return; - } - - // Attempt to compress it. - if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) - { - // Compressing succeeded; send compressed data - - free(savebuffer); - - // State that we're compressed. - buffertosend = compressedsave; - WRITEUINT32(compressedsave, length - sizeof(UINT32)); - length = compressedlen + sizeof(UINT32); - } - else - { - // Compression failed to make it smaller; send original - - free(compressedsave); - - // State that we're not compressed - buffertosend = savebuffer; - WRITEUINT32(savebuffer, 0); - } - - AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0); - save_p = NULL; - - // Remember when we started sending the savegame so we can handle timeouts - sendingsavegame[node] = true; - freezetimeout[node] = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte -} - -#ifdef DUMPCONSISTENCY -#define TMPSAVENAME "badmath.sav" -static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -static void SV_SavedGame(void) -{ - size_t length; - UINT8 *savebuffer; - char tmpsave[256]; - - if (!cv_dumpconsistency.value) - return; - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - // first save it in a malloced buffer - save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!save_p) - { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); - return; - } - - P_SaveNetGame(false); - - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } - - // then save it! - if (!FIL_WriteFile(tmpsave, savebuffer, length)) - CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); - - free(savebuffer); - save_p = NULL; -} - -#undef TMPSAVENAME -#endif -#define TMPSAVENAME "$$$.sav" - - -static void CL_LoadReceivedSavegame(boolean reloading) -{ - UINT8 *savebuffer = NULL; - size_t length, decompressedlen; - char tmpsave[256]; - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - length = FIL_ReadFile(tmpsave, &savebuffer); - - CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); - if (!length) - { - I_Error("Can't read savegame sent"); - return; - } - - save_p = savebuffer; - - // Decompress saved game if necessary. - decompressedlen = READUINT32(save_p); - if(decompressedlen > 0) - { - UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); - lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); - Z_Free(savebuffer); - save_p = savebuffer = decompressedbuffer; - } - - paused = false; - demoplayback = false; - titlemapinaction = TITLEMAP_OFF; - titledemo = false; - automapactive = false; - - // load a base level - if (P_LoadNetGame(reloading)) - { - const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; - CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); - if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, "")) - { - CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl); - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - CONS_Printf(M_GetText(" Zone")); - if (actnum > 0) - CONS_Printf(" %2d", actnum); - } - CONS_Printf("\"\n"); - } - else - { - CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); - Z_Free(savebuffer); - save_p = NULL; - if (unlink(tmpsave) == -1) - CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); - return; - } - - // done - Z_Free(savebuffer); - save_p = NULL; - if (unlink(tmpsave) == -1) - CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); - consistancy[gametic%BACKUPTICS] = Consistancy(); - CON_ToggleOff(); - - // Tell the server we have received and reloaded the gamestate - // so they know they can resume the game - netbuffer->packettype = PT_RECEIVEDGAMESTATE; - HSendPacket(servernode, true, 0, 0); -} - -static void CL_ReloadReceivedSavegame(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - { -#ifdef HAVE_BLUA - LUA_InvalidatePlayer(&players[i]); -#endif - sprintf(player_names[i], "Player %d", i + 1); - } - - CL_LoadReceivedSavegame(true); - - if (neededtic < gametic) - neededtic = gametic; - maketic = neededtic; - - ticcmd_oldangleturn[0] = players[consoleplayer].oldrelangleturn; - P_ForceLocalAngle(&players[consoleplayer], (angle_t)(players[consoleplayer].angleturn << 16)); - if (splitscreen) - { - ticcmd_oldangleturn[1] = players[secondarydisplayplayer].oldrelangleturn; - P_ForceLocalAngle(&players[secondarydisplayplayer], (angle_t)(players[secondarydisplayplayer].angleturn << 16)); - } - - camera.subsector = R_PointInSubsector(camera.x, camera.y); - camera2.subsector = R_PointInSubsector(camera2.x, camera2.y); - - cl_redownloadinggamestate = false; - - CONS_Printf(M_GetText("Game state reloaded\n")); -} -#endif - -#ifndef NONET -static void SendAskInfo(INT32 node) -{ - const tic_t asktime = I_GetTime(); - netbuffer->packettype = PT_ASKINFO; - netbuffer->u.askinfo.version = VERSION; - netbuffer->u.askinfo.time = (tic_t)LONG(asktime); - - // Even if this never arrives due to the host being firewalled, we've - // now allowed traffic from the host to us in, so once the MS relays - // our address to the host, it'll be able to speak to us. - HSendPacket(node, false, 0, sizeof (askinfo_pak)); -} - -serverelem_t serverlist[MAXSERVERLIST]; -UINT32 serverlistcount = 0; - -#define FORCECLOSE 0x8000 - -static void SL_ClearServerList(INT32 connectedserver) -{ - UINT32 i; - - for (i = 0; i < serverlistcount; i++) - if (connectedserver != serverlist[i].node) - { - Net_CloseConnection(serverlist[i].node|FORCECLOSE); - serverlist[i].node = 0; - } - serverlistcount = 0; -} - -static UINT32 SL_SearchServer(INT32 node) -{ - UINT32 i; - for (i = 0; i < serverlistcount; i++) - if (serverlist[i].node == node) - return i; - - return UINT32_MAX; -} - -static void SL_InsertServer(serverinfo_pak* info, SINT8 node) -{ - UINT32 i; - - // search if not already on it - i = SL_SearchServer(node); - if (i == UINT32_MAX) - { - // not found add it - if (serverlistcount >= MAXSERVERLIST) - return; // list full - - if (info->_255 != 255) - return;/* old packet format */ - - if (info->packetversion != PACKETVERSION) - return;/* old new packet format */ - - if (info->version != VERSION) - return; // Not same version. - - if (info->subversion != SUBVERSION) - return; // Close, but no cigar. - - if (strcmp(info->application, SRB2APPLICATION)) - return;/* that's a different mod */ - - i = serverlistcount++; - } - - serverlist[i].info = *info; - serverlist[i].node = node; - - // resort server list - M_SortServerList(); -} - -#if defined (MASTERSERVER) && defined (HAVE_THREADS) -struct Fetch_servers_ctx -{ - int room; - int id; -}; - -static void -Fetch_servers_thread (struct Fetch_servers_ctx *ctx) -{ - msg_server_t *server_list; - - server_list = GetShortServersList(ctx->room, ctx->id); - - if (server_list) - { - I_lock_mutex(&ms_QueryId_mutex); - { - if (ctx->id != ms_QueryId) - { - free(server_list); - server_list = NULL; - } - } - I_unlock_mutex(ms_QueryId_mutex); - - if (server_list) - { - I_lock_mutex(&m_menu_mutex); - { - if (m_waiting_mode == M_WAITING_SERVERS) - m_waiting_mode = M_NOT_WAITING; - } - I_unlock_mutex(m_menu_mutex); - - I_lock_mutex(&ms_ServerList_mutex); - { - ms_ServerList = server_list; - } - I_unlock_mutex(ms_ServerList_mutex); - } - } - - free(ctx); -} -#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ - -void CL_QueryServerList (msg_server_t *server_list) -{ - INT32 i; - - for (i = 0; server_list[i].header.buffer[0]; i++) - { - // Make sure MS version matches our own, to - // thwart nefarious servers who lie to the MS. - - /* lol bruh, that version COMES from the servers */ - //if (strcmp(version, server_list[i].version) == 0) - { - INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port); - if (node == -1) - break; // no more node free - SendAskInfo(node); - // Force close the connection so that servers can't eat - // up nodes forever if we never get a reply back from them - // (usually when they've not forwarded their ports). - // - // Don't worry, we'll get in contact with the working - // servers again when they send SERVERINFO to us later! - // - // (Note: as a side effect this probably means every - // server in the list will probably be using the same node (e.g. node 1), - // not that it matters which nodes they use when - // the connections are closed afterwards anyway) - // -- Monster Iestyn 12/11/18 - Net_CloseConnection(node|FORCECLOSE); - } - } -} - -void CL_UpdateServerList(boolean internetsearch, INT32 room) -{ - (void)internetsearch; - (void)room; - - SL_ClearServerList(0); - - if (!netgame && I_NetOpenSocket) - { - if (I_NetOpenSocket()) - { - netgame = true; - multiplayer = true; - } - } - - // search for local servers - if (netgame) - SendAskInfo(BROADCASTADDR); - -#ifdef MASTERSERVER - if (internetsearch) - { -#ifdef HAVE_THREADS - struct Fetch_servers_ctx *ctx; - - ctx = malloc(sizeof *ctx); - - /* This called from M_Refresh so I don't use a mutex */ - m_waiting_mode = M_WAITING_SERVERS; - - I_lock_mutex(&ms_QueryId_mutex); - { - ctx->id = ms_QueryId; - } - I_unlock_mutex(ms_QueryId_mutex); - - ctx->room = room; - - I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx); -#else - msg_server_t *server_list; - - server_list = GetShortServersList(room, 0); - - if (server_list) - { - CL_QueryServerList(server_list); - free(server_list); - } -#endif - } -#endif/*MASTERSERVER*/ -} - -#endif // ifndef NONET - -/** Called by CL_ServerConnectionTicker - * - * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. - * \return False if the connection was aborted - * \sa CL_ServerConnectionTicker - * \sa CL_ConnectToServer - * - */ -static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) -{ -#ifndef NONET - INT32 i; - - // serverlist is updated by GetPacket function - if (serverlistcount > 0) - { - // this can be a responce to our broadcast request - if (servernode == -1 || servernode >= MAXNETNODES) - { - i = 0; - servernode = serverlist[i].node; - CONS_Printf(M_GetText("Found, ")); - } - else - { - i = SL_SearchServer(servernode); - if (i < 0) - return true; - } - - // Quit here rather than downloading files and being refused later. - if (serverlist[i].info.refusereason) - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - if (serverlist[i].info.refusereason == 1) - M_StartMessage(M_GetText("The server is not accepting\njoins for the moment.\n\nPress ESC\n"), NULL, MM_NOTHING); - else if (serverlist[i].info.refusereason == 2) - M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING); - else - M_StartMessage(M_GetText("You can't join.\nI don't know why,\nbut you can't join.\n\nPress ESC\n"), NULL, MM_NOTHING); - return false; - } - - if (client) - { - D_ParseFileneeded(serverlist[i].info.fileneedednum, - serverlist[i].info.fileneeded); - CONS_Printf(M_GetText("Checking files...\n")); - i = CL_CheckFiles(); - if (i == 3) // too many files - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have too many WAD files loaded\n" - "to add ones the server is using.\n" - "Please restart SRB2 before connecting.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - else if (i == 2) // cannot join for some reason - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have the wrong addons loaded.\n\n" - "To play on this server, restart\n" - "the game and don't load any addons.\n" - "SRB2 will automatically add\n" - "everything you need when you join.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - else if (i == 1) - cl_mode = CL_ASKJOIN; - else - { - // must download something - // can we, though? - if (!CL_CheckDownloadable()) // nope! - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You cannot connect to this server\n" - "because you cannot download the files\n" - "that you are missing from the server.\n\n" - "See the console or log file for\n" - "more details.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - // no problem if can't send packet, we will retry later - if (CL_SendFileRequest()) - { - cl_mode = CL_DOWNLOADFILES; -#ifndef NONET - Snake_Initialise(); -#endif - } - } - } - else - cl_mode = CL_ASKJOIN; // files need not be checked for the server. - - return true; - } - - // Ask the info to the server (askinfo packet) - if (*asksent + NEWTICRATE < I_GetTime()) - { - SendAskInfo(servernode); - *asksent = I_GetTime(); - } -#else - (void)asksent; - // No netgames, so we skip this state. - cl_mode = CL_ASKJOIN; -#endif // ifndef NONET/else - - return true; -} - -/** Called by CL_ConnectToServer - * - * \param tmpsave The name of the gamestate file??? - * \param oldtic Used for knowing when to poll events and redraw - * \param asksent ??? - * \return False if the connection was aborted - * \sa CL_ServerConnectionSearchTicker - * \sa CL_ConnectToServer - * - */ -static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic_t *asksent) -{ - boolean waitmore; - INT32 i; - -#ifdef NONET - (void)tmpsave; -#endif - - switch (cl_mode) - { - case CL_SEARCHING: - if (!CL_ServerConnectionSearchTicker(asksent)) - return false; - break; - - case CL_DOWNLOADFILES: - waitmore = false; - for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status == FS_DOWNLOADING - || fileneeded[i].status == FS_REQUESTED) - { - waitmore = true; - break; - } - if (waitmore) - break; // exit the case - -#ifndef NONET - if (snake) - { - free(snake); - snake = NULL; - } -#endif - - cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now - /* FALLTHRU */ - - case CL_ASKJOIN: - CL_LoadServerFiles(); -#ifndef NONET - // prepare structures to save the file - // WARNING: this can be useless in case of server not in GS_LEVEL - // but since the network layer doesn't provide ordered packets... - CL_PrepareDownloadSaveGame(tmpsave); -#endif - if (CL_SendJoin()) - cl_mode = CL_WAITJOINRESPONSE; - break; - -#ifndef NONET - case CL_DOWNLOADSAVEGAME: - // At this state, the first (and only) needed file is the gamestate - if (fileneeded[0].status == FS_FOUND) - { - // Gamestate is now handled within CL_LoadReceivedSavegame() - CL_LoadReceivedSavegame(false); - cl_mode = CL_CONNECTED; - } // don't break case continue to CL_CONNECTED - else - break; -#endif - - case CL_WAITJOINRESPONSE: - case CL_CONNECTED: - default: - break; - - // Connection closed by cancel, timeout or refusal. - case CL_ABORTED: - cl_mode = CL_SEARCHING; - return false; - - } - - GetPackets(); - Net_AckTicker(); - - // Call it only once by tic - if (*oldtic != I_GetTime()) - { - I_OsPolling(); - for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) - G_MapEventsToControls(&events[eventtail]); - - if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1]) - { - CONS_Printf(M_GetText("Network game synchronization aborted.\n")); -// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); - -#ifndef NONET - if (snake) - { - free(snake); - snake = NULL; - } -#endif - - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - memset(gamekeydown, 0, NUMKEYS); - return false; - } -#ifndef NONET - else if (cl_mode == CL_DOWNLOADFILES && snake) - Snake_Handle(); -#endif - - if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME)) - FileReceiveTicker(); - - // why are these here? this is for servers, we're a client - //if (key == 's' && server) - // doomcom->numnodes = (INT16)pnumnodes; - //FileSendTicker(); - *oldtic = I_GetTime(); - -#ifndef NONET - if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) - { - if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME) - { - F_MenuPresTicker(true); // title sky - F_TitleScreenTicker(true); - F_TitleScreenDrawer(); - } - CL_DrawConnectionStatus(); - I_UpdateNoVsync(); // page flip or blit buffer - if (moviemode) - M_SaveFrame(); - S_UpdateSounds(); - S_UpdateClosedCaptions(); - } -#else - CON_Drawer(); - I_UpdateNoVsync(); -#endif - } - else - I_Sleep(); - - return true; -} - -/** Use adaptive send using net_bandwidth and stat.sendbytes - * - * \todo Better description... - * - */ -static void CL_ConnectToServer(void) -{ - INT32 pnumnodes, nodewaited = doomcom->numnodes, i; - tic_t oldtic; -#ifndef NONET - tic_t asksent; - char tmpsave[256]; - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - lastfilenum = -1; -#endif - - cl_mode = CL_SEARCHING; - -#ifndef NONET - // Don't get a corrupt savegame error because tmpsave already exists - if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) - I_Error("Can't delete %s\n", tmpsave); -#endif - - if (netgame) - { - if (servernode < 0 || servernode >= MAXNETNODES) - CONS_Printf(M_GetText("Searching for a server...\n")); - else - CONS_Printf(M_GetText("Contacting the server...\n")); - } - - if (gamestate == GS_INTERMISSION) - Y_EndIntermission(); // clean up intermission graphics etc - - DEBFILE(va("waiting %d nodes\n", doomcom->numnodes)); - G_SetGamestate(GS_WAITINGPLAYERS); - wipegamestate = GS_WAITINGPLAYERS; - - ClearAdminPlayers(); - pnumnodes = 1; - oldtic = I_GetTime() - 1; -#ifndef NONET - asksent = (tic_t) - TICRATE; - - i = SL_SearchServer(servernode); - - if (i != -1) - { - char *gametypestr = serverlist[i].info.gametypename; - CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); - gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0'; - CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); - CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100, - serverlist[i].info.version%100, serverlist[i].info.subversion); - } - SL_ClearServerList(servernode); -#endif - - do - { - // If the connection was aborted for some reason, leave -#ifndef NONET - if (!CL_ServerConnectionTicker(tmpsave, &oldtic, &asksent)) -#else - if (!CL_ServerConnectionTicker((char*)NULL, &oldtic, (tic_t *)NULL)) -#endif - return; - - if (server) - { - pnumnodes = 0; - for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i]) - pnumnodes++; - } - } - while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); - - DEBFILE(va("Synchronisation Finished\n")); - - displayplayer = consoleplayer; -} - -#ifndef NONET -typedef struct banreason_s -{ - char *reason; - struct banreason_s *prev; //-1 - struct banreason_s *next; //+1 -} banreason_t; - -static banreason_t *reasontail = NULL; //last entry, use prev -static banreason_t *reasonhead = NULL; //1st entry, use next - -static void Command_ShowBan(void) //Print out ban list -{ - size_t i; - const char *address, *mask; - banreason_t *reasonlist = reasonhead; - - if (I_GetBanAddress) - CONS_Printf(M_GetText("Ban List:\n")); - else - return; - - for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) - { - if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) - CONS_Printf("%s: %s ", sizeu1(i+1), address); - else - CONS_Printf("%s: %s/%s ", sizeu1(i+1), address, mask); - - if (reasonlist && reasonlist->reason) - CONS_Printf("(%s)\n", reasonlist->reason); - else - CONS_Printf("\n"); - - if (reasonlist) reasonlist = reasonlist->next; - } - - if (i == 0 && !address) - CONS_Printf(M_GetText("(empty)\n")); -} - -void D_SaveBan(void) -{ - FILE *f; - size_t i; - banreason_t *reasonlist = reasonhead; - const char *address, *mask; - - if (!reasonhead) - return; - - f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "w"); - - if (!f) - { - CONS_Alert(CONS_WARNING, M_GetText("Could not save ban list into ban.txt\n")); - return; - } - - for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++) - { - if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL) - fprintf(f, "%s 0", address); - else - fprintf(f, "%s %s", address, mask); - - if (reasonlist && reasonlist->reason) - fprintf(f, " %s\n", reasonlist->reason); - else - fprintf(f, " %s\n", "NA"); - - if (reasonlist) reasonlist = reasonlist->next; - } - - fclose(f); -} - -static void Ban_Add(const char *reason) -{ - banreason_t *reasonlist = malloc(sizeof(*reasonlist)); - - if (!reasonlist) - return; - if (!reason) - reason = "NA"; - - reasonlist->next = NULL; - reasonlist->reason = Z_StrDup(reason); - if ((reasonlist->prev = reasontail) == NULL) - reasonhead = reasonlist; - else - reasontail->next = reasonlist; - reasontail = reasonlist; -} - -static void Command_ClearBans(void) -{ - banreason_t *temp; - - if (!I_ClearBans) - return; - - I_ClearBans(); - D_SaveBan(); - reasontail = NULL; - while (reasonhead) - { - temp = reasonhead->next; - Z_Free(reasonhead->reason); - free(reasonhead); - reasonhead = temp; - } -} - -static void Ban_Load_File(boolean warning) -{ - FILE *f; - size_t i; - const char *address, *mask; - char buffer[MAX_WADPATH]; - - f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); - - if (!f) - { - if (warning) - CONS_Alert(CONS_WARNING, M_GetText("Could not open ban.txt for ban list\n")); - return; - } - - if (I_ClearBans) - Command_ClearBans(); - else - { - fclose(f); - return; - } - - for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++) - { - address = strtok(buffer, " \t\r\n"); - mask = strtok(NULL, " \t\r\n"); - - I_SetBanAddress(address, mask); - - Ban_Add(strtok(NULL, "\r\n")); - } - - fclose(f); -} - -static void Command_ReloadBan(void) //recheck ban.txt -{ - Ban_Load_File(true); -} - -static void Command_connect(void) -{ - if (COM_Argc() < 2 || *COM_Argv(1) == 0) - { - CONS_Printf(M_GetText( - "Connect (port): connect to a server\n" - "Connect ANY: connect to the first lan server found\n" - //"Connect SELF: connect to your own server.\n" - )); - return; - } - - if (Playing() || titledemo) - { - CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); - return; - } - - // modified game check: no longer handled - // we don't request a restart unless the filelist differs - - server = false; -/* - if (!stricmp(COM_Argv(1), "self")) - { - servernode = 0; - server = true; - /// \bug should be but... - //SV_SpawnServer(); - } - else -*/ - { - // used in menu to connect to a server in the list - if (netgame && !stricmp(COM_Argv(1), "node")) - { - servernode = (SINT8)atoi(COM_Argv(2)); - } - else if (netgame) - { - CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n")); - return; - } - else if (I_NetOpenSocket) - { - I_NetOpenSocket(); - netgame = true; - multiplayer = true; - - if (!stricmp(COM_Argv(1), "any")) - servernode = BROADCASTADDR; - else if (I_NetMakeNodewPort) - { - if (COM_Argc() >= 3) // address AND port - servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2)); - else // address only, or address:port - servernode = I_NetMakeNode(COM_Argv(1)); - } - else - { - CONS_Alert(CONS_ERROR, M_GetText("There is no server identification with this network driver\n")); - D_CloseConnection(); - return; - } - } - else - CONS_Alert(CONS_ERROR, M_GetText("There is no network driver\n")); - } - - splitscreen = false; - SplitScreen_OnChange(); - botingame = false; - botskin = 0; - CL_ConnectToServer(); -} -#endif - -static void ResetNode(INT32 node); - -// -// CL_ClearPlayer -// -// Clears the player data so that a future client can use this slot -// -void CL_ClearPlayer(INT32 playernum) -{ - if (players[playernum].mo) - P_RemoveMobj(players[playernum].mo); - memset(&players[playernum], 0, sizeof (player_t)); - memset(playeraddress[playernum], 0, sizeof(*playeraddress)); -} - -// -// CL_RemovePlayer -// -// Removes a player from the current game -// -static void CL_RemovePlayer(INT32 playernum, kickreason_t reason) -{ - // Sanity check: exceptional cases (i.e. c-fails) can cause multiple - // kick commands to be issued for the same player. - if (!playeringame[playernum]) - return; - - if (server && !demoplayback && playernode[playernum] != UINT8_MAX) - { - INT32 node = playernode[playernum]; - playerpernode[node]--; - if (playerpernode[node] <= 0) - { - nodeingame[node] = false; - Net_CloseConnection(node); - ResetNode(node); - } - } - - if (gametyperules & GTR_TEAMFLAGS) - P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! - - // If in a special stage, redistribute the player's spheres across - // the remaining players. - if (G_IsSpecialStage(gamemap)) - { - INT32 i, count, sincrement, spheres, rincrement, rings; - - for (i = 0, count = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - count++; - } - - count--; - sincrement = spheres = players[playernum].spheres; - rincrement = rings = players[playernum].rings; - - if (count) - { - sincrement /= count; - rincrement /= count; - } - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && i != playernum) - { - if (spheres < 2*sincrement) - { - P_GivePlayerSpheres(&players[i], spheres); - spheres = 0; - } - else - { - P_GivePlayerSpheres(&players[i], sincrement); - spheres -= sincrement; - } - - if (rings < 2*rincrement) - { - P_GivePlayerRings(&players[i], rings); - rings = 0; - } - else - { - P_GivePlayerRings(&players[i], rincrement); - rings -= rincrement; - } - } - } - } - - LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting - - // don't look through someone's view who isn't there - if (playernum == displayplayer) - { - // Call ViewpointSwitch hooks here. - // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true); - displayplayer = consoleplayer; - } - - // Reset player data - CL_ClearPlayer(playernum); - - // remove avatar of player - playeringame[playernum] = false; - playernode[playernum] = UINT8_MAX; - while (!playeringame[doomcom->numslots-1] && doomcom->numslots > 1) - doomcom->numslots--; - - // Reset the name - sprintf(player_names[playernum], "Player %d", playernum+1); - - player_name_changes[playernum] = 0; - - if (IsPlayerAdmin(playernum)) - { - RemoveAdminPlayer(playernum); // don't stay admin after you're gone - } - - LUA_InvalidatePlayer(&players[playernum]); - - if (G_TagGametype()) //Check if you still have a game. Location flexible. =P - P_CheckSurvivors(); - else if (gametyperules & GTR_RACE) - P_CheckRacers(); -} - -void CL_Reset(void) -{ - if (metalrecording) - G_StopMetalRecording(false); - if (metalplayback) - G_StopMetalDemo(); - if (demorecording) - G_CheckDemoStatus(); - - // reset client/server code - DEBFILE(va("\n-=-=-=-=-=-=-= Client reset =-=-=-=-=-=-=-\n\n")); - - if (servernode > 0 && servernode < MAXNETNODES) - { - nodeingame[(UINT8)servernode] = false; - Net_CloseConnection(servernode); - } - D_CloseConnection(); // netgame = false - multiplayer = false; - servernode = 0; - server = true; - doomcom->numnodes = 1; - doomcom->numslots = 1; - SV_StopServer(); - SV_ResetServer(); - CV_RevertNetVars(); - - // make sure we don't leave any fileneeded gunk over from a failed join - fileneedednum = 0; - memset(fileneeded, 0, sizeof(fileneeded)); - - // D_StartTitle should get done now, but the calling function will handle it -} - -#ifndef NONET -static void Command_GetPlayerNum(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - if (serverplayer == i) - CONS_Printf(M_GetText("num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); - else - CONS_Printf(M_GetText("\x82num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]); - } -} - -SINT8 nametonum(const char *name) -{ - INT32 playernum, i; - - if (!strcmp(name, "0")) + if (!skin) return 0; - playernum = (SINT8)atoi(name); + if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + return 0; - if (playernum < 0 || playernum >= MAXPLAYERS) - return -1; - - if (playernum) + while (!skin->sprites[spr2].numframes + && spr2 != SPR2_STND + && ++i < 32) // recursion limiter { - if (playeringame[playernum]) - return (SINT8)playernum; - else - return -1; + if (spr2 & FF_SPR2SUPER) + { + super = FF_SPR2SUPER; + spr2 &= ~FF_SPR2SUPER; + continue; + } + + switch(spr2) + { + // Normal special cases. + case SPR2_JUMP: + spr2 = ((player + ? player->charflags + : skin->flags) + & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; + break; + case SPR2_TIRE: + spr2 = ((player + ? player->charability + : skin->ability) + == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; + break; + // Use the handy list, that's what it's there for! + default: + spr2 = spr2defaults[spr2]; + break; + } + + spr2 |= super; } - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && !stricmp(player_names[i], name)) - return (SINT8)i; + if (i >= 32) // probably an infinite loop... + return 0; - CONS_Printf(M_GetText("There is no player named \"%s\"\n"), name); + return spr2; +} +static void Sk_SetDefaultValue(skin_t *skin) +{ + INT32 i; + // + // set default skin values + // + memset(skin, 0, sizeof (skin_t)); + snprintf(skin->name, + sizeof skin->name, "skin %u", (UINT32)(skin-skins)); + skin->name[sizeof skin->name - 1] = '\0'; + skin->wadnum = INT16_MAX; + + skin->flags = 0; + + strcpy(skin->realname, "Someone"); + strcpy(skin->hudname, "???"); + + skin->starttranscolor = 96; + skin->prefcolor = SKINCOLOR_GREEN; + skin->supercolor = SKINCOLOR_SUPERGOLD1; + skin->prefoppositecolor = 0; // use tables + + skin->normalspeed = 36<runspeed = 28<thrustfactor = 5; + skin->accelstart = 96; + skin->acceleration = 40; + + skin->ability = CA_NONE; + skin->ability2 = CA2_SPINDASH; + skin->jumpfactor = FRACUNIT; + skin->actionspd = 30<mindash = 15<maxdash = 70<radius = mobjinfo[MT_PLAYER].radius; + skin->height = mobjinfo[MT_PLAYER].height; + skin->spinheight = FixedMul(skin->height, 2*FRACUNIT/3); + + skin->shieldscale = FRACUNIT; + skin->camerascale = FRACUNIT; + + skin->thokitem = -1; + skin->spinitem = -1; + skin->revitem = -1; + skin->followitem = 0; + + skin->highresscale = FRACUNIT; + skin->contspeed = 17; + skin->contangle = 0; + + skin->availability = 0; + + for (i = 0; i < sfx_skinsoundslot0; i++) + if (S_sfx[i].skinsound != -1) + skin->soundsid[S_sfx[i].skinsound] = i; +} + +// +// Initialize the basic skins +// +void R_InitSkins(void) +{ +#ifdef SKINVALUES + INT32 i; + + for (i = 0; i <= MAXSKINS; i++) + { + skin_cons_t[i].value = 0; + skin_cons_t[i].strvalue = NULL; + } +#endif + + // no default skin! + numskins = 0; +} + +UINT32 R_GetSkinAvailabilities(void) +{ + INT32 s; + UINT32 response = 0; + + for (s = 0; s < MAXSKINS; s++) + { + if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) + response |= (1 << s); + } + return response; +} + +// returns true if available in circumstances, otherwise nope +// warning don't use with an invalid skinnum other than -1 which always returns true +boolean R_SkinUsable(INT32 playernum, INT32 skinnum) +{ + return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... + || (!skins[skinnum].availability) + || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) + || (modeattacking) // If you have someone else's run you might as well take a look + || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. + || (netgame && (cv_forceskin.value == skinnum)) // Force 2. + || (metalrecording && skinnum == 5) // Force 3. + || players[playernum].bot //Force (player is a bot) + ); +} + +// returns true if the skin name is found (loaded from pwad) +// warning return -1 if not found +INT32 R_SkinAvailable(const char *name) +{ + INT32 i; + + for (i = 0; i < numskins; i++) + { + // search in the skin list + if (stricmp(skins[i].name,name)==0) + return i; + } return -1; } -/** Lists all players and their player numbers. - * - * \sa Command_GetPlayerNum - */ -static void Command_Nodes(void) +// network code calls this when a 'skin change' is received +void SetPlayerSkin(INT32 playernum, const char *skinname) { - INT32 i; - size_t maxlen = 0; - const char *address; + INT32 i = R_SkinAvailable(skinname); + player_t *player = &players[playernum]; - for (i = 0; i < MAXPLAYERS; i++) + if ((i != -1) && R_SkinUsable(playernum, i)) { - const size_t plen = strlen(player_names[i]); - if (playeringame[i] && plen > maxlen) - maxlen = plen; + SetPlayerSkinByNum(playernum, i); + return; } - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]); + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); - if (playernode[i] != UINT8_MAX) - { - CONS_Printf(" - node %.2d", playernode[i]); - if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL) - CONS_Printf(" - %s", address); - } - - if (IsPlayerAdmin(i)) - CONS_Printf(M_GetText(" (verified admin)")); - - if (players[i].spectator) - CONS_Printf(M_GetText(" (spectator)")); - - CONS_Printf("\n"); - } - } + SetPlayerSkinByNum(playernum, 0); } -static void Command_Ban(void) +// Same as SetPlayerSkin, but uses the skin #. +// network code calls this when a 'skin change' is received +void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) { - if (COM_Argc() < 2) + player_t *player = &players[playernum]; + skin_t *skin = &skins[skinnum]; + UINT16 newcolor = 0; + + if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists! { - CONS_Printf(M_GetText("Ban : ban and kick a player\n")); - return; - } + player->skin = skinnum; - if (!netgame) // Don't kick Tails in splitscreen! - { - CONS_Printf(M_GetText("This only works in a netgame.\n")); - return; - } + player->camerascale = skin->camerascale; + player->shieldscale = skin->shieldscale; - if (server || IsPlayerAdmin(consoleplayer)) - { - UINT8 buf[3 + MAX_REASONLENGTH]; - UINT8 *p = buf; - const SINT8 pn = nametonum(COM_Argv(1)); - const INT32 node = playernode[(INT32)pn]; + player->charability = (UINT8)skin->ability; + player->charability2 = (UINT8)skin->ability2; - if (pn == -1 || pn == 0) - return; + player->charflags = (UINT32)skin->flags; - WRITEUINT8(p, pn); + player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; + player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; + player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; + player->followitem = skin->followitem; - if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff. + player->powers[pw_shield] &= SH_STACK; + + player->actionspd = skin->actionspd; + player->mindash = skin->mindash; + player->maxdash = skin->maxdash; + + player->normalspeed = skin->normalspeed; + player->runspeed = skin->runspeed; + player->thrustfactor = skin->thrustfactor; + player->accelstart = skin->accelstart; + player->acceleration = skin->acceleration; + + player->jumpfactor = skin->jumpfactor; + + player->height = skin->height; + player->spinheight = skin->spinheight; + + if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) { - CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); - WRITEUINT8(p, KICK_MSG_GO_AWAY); - SendNetXCmd(XD_KICK, &buf, 2); + if (playernum == consoleplayer) + CV_StealthSetValue(&cv_playercolor, skin->prefcolor); + else if (playernum == secondarydisplayplayer) + CV_StealthSetValue(&cv_playercolor2, skin->prefcolor); + player->skincolor = newcolor = skin->prefcolor; + if (player->bot && botingame) + { + botskin = (UINT8)(skinnum + 1); + botcolor = skin->prefcolor; + } } - else + + if (player->followmobj) { - if (server) // only the server is allowed to do this right now + P_RemoveMobj(player->followmobj); + P_SetTarget(&player->followmobj, NULL); + } + + if (player->mo) + { + fixed_t radius = FixedMul(skin->radius, player->mo->scale); + if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { - Ban_Add(COM_Argv(2)); - D_SaveBan(); // save the ban list + skin = &skins[DEFAULTNIGHTSSKIN]; + player->followitem = skin->followitem; + if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) + newcolor = skin->prefcolor; // will be updated in thinker to flashing + } + player->mo->skin = skin; + if (newcolor) + player->mo->color = newcolor; + P_SetScale(player->mo, player->mo->scale); + player->mo->radius = radius; + + P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames + } + return; + } + + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); + SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin +} + +// +// Add skins from a pwad, each skin preceded by 'S_SKIN' marker +// + +// Does the same is in w_wad, but check only for +// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2.. +// for wad editors that don't like multiple resources of the same name) +// +static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + const char *S_SKIN = "S_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) + return i; + } + return INT16_MAX; // not found +} + +#define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value) + +// turn _ into spaces and . into katana dot +#define SYMBOLCONVERT(name) for (value = name; *value; value++)\ + {\ + if (*value == '_') *value = ' ';\ + else if (*value == '.') *value = '\x1E';\ + } + +// +// Patch skins from a pwad, each skin preceded by 'P_SKIN' marker +// + +// Does the same is in w_wad, but check only for +// the first 6 characters (this is so we can have P_SKIN1, P_SKIN2.. +// for wad editors that don't like multiple resources of the same name) +// +static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + 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,P_SKIN,6)==0) + return i; + } + return INT16_MAX; // not found +} + +static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin) +{ + UINT16 newlastlump; + UINT8 sprite2; + + *lump += 1; // start after S_SKIN + *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END + + // old wadding practices die hard -- stop at S_SKIN (or P_SKIN) or S_START if they come before S_END. + newlastlump = W_CheckForSkinMarkerInPwad(wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + newlastlump = W_CheckForPatchSkinMarkerInPwad(wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + newlastlump = W_CheckNumForNamePwad("S_START",wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + + // ...and let's handle super, too + newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,*lump); + if (newlastlump < *lastlump) + { + newlastlump++; + // load all sprite sets we are aware of... for super! + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); + + newlastlump--; + *lastlump = newlastlump; // okay, make the normal sprite set loading end there + } + + // load all sprite sets we are aware of... for normal stuff. + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + 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]); +} + +// returns whether found appropriate property +static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) +{ + // custom translation table + if (!stricmp(stoken, "startcolor")) + skin->starttranscolor = atoi(value); + +#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); + // character type identification + FULLPROCESS(flags) + FULLPROCESS(ability) + FULLPROCESS(ability2) + + FULLPROCESS(thokitem) + FULLPROCESS(spinitem) + FULLPROCESS(revitem) + FULLPROCESS(followitem) +#undef FULLPROCESS + +#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<field = atoi(value); + GETINT(thrustfactor) + GETINT(accelstart) + GETINT(acceleration) + GETINT(contspeed) + GETINT(contangle) +#undef GETINT + +#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) \ +{ \ + UINT16 color = R_GetColorByName(value); \ + skin->field = (color ? color : SKINCOLOR_GREEN); \ +} + GETSKINCOLOR(prefcolor) + GETSKINCOLOR(prefoppositecolor) +#undef GETSKINCOLOR + else if (!stricmp(stoken, "supercolor")) + { + UINT16 color = R_GetSuperColorByName(value); + skin->supercolor = (color ? color : SKINCOLOR_SUPERGOLD1); + } + +#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value)); + GETFLOAT(jumpfactor) + GETFLOAT(highresscale) + GETFLOAT(shieldscale) + GETFLOAT(camerascale) +#undef GETFLOAT + +#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \ + strupr(value); \ + if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \ + skin->flags |= (SF_##field); \ + else \ + skin->flags &= ~(SF_##field); \ +} + // parameters for individual character flags + // these are uppercase so they can be concatenated with SF_ + // 1, true, yes are all valid values + GETFLAG(SUPER) + GETFLAG(NOSUPERSPIN) + GETFLAG(NOSPINDASHDUST) + GETFLAG(HIRES) + GETFLAG(NOSKID) + GETFLAG(NOSPEEDADJUST) + GETFLAG(RUNONWATER) + GETFLAG(NOJUMPSPIN) + GETFLAG(NOJUMPDAMAGE) + GETFLAG(STOMPDAMAGE) + GETFLAG(MARIODAMAGE) + GETFLAG(MACHINE) + GETFLAG(DASHMODE) + GETFLAG(FASTEDGE) + GETFLAG(MULTIABILITY) + GETFLAG(NONIGHTSROTATION) + GETFLAG(NONIGHTSSUPER) +#undef GETFLAG + + else // let's check if it's a sound, otherwise error out + { + boolean found = false; + sfxenum_t i; + size_t stokenadjust; + + // Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.) + if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS* + stokenadjust = 2; + else // sfx_* + stokenadjust = 4; + + // Remove the prefix. (We can affect this directly since we're not going to use it again.) + if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS* + value += 2; + else // sfx_* + value += 4; + + // copy name of sounds that are remapped + // for this skin + for (i = 0; i < sfx_skinsoundslot0; i++) + { + if (!S_sfx[i].name) + continue; + if (S_sfx[i].skinsound != -1 + && !stricmp(S_sfx[i].name, + stoken + stokenadjust)) + { + skin->soundsid[S_sfx[i].skinsound] = + S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true); + found = true; + } + } + return found; + } + return true; +} + +// +// Find skin sprites, sounds & optional status bar face, & add them +// +void R_AddSkins(UINT16 wadnum) +{ + UINT16 lump, lastlump = 0; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean hudname, realname; + + // + // search for all skin markers in pwad + // + + while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + { + // advance by default + lastlump = lump + 1; + + if (numskins >= MAXSKINS) + { + CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS); + continue; // so we know how many skins couldn't be added + } + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("R_AddSkins: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + // set defaults + skin = &skins[numskins]; + Sk_SetDefaultValue(skin); + skin->wadnum = wadnum; + hudname = realname = false; + // parse + 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 } - if (COM_Argc() == 2) - { - WRITEUINT8(p, KICK_MSG_BANNED); - SendNetXCmd(XD_KICK, &buf, 2); - } - else - { - size_t i, j = COM_Argc(); - char message[MAX_REASONLENGTH]; + value = strtok(NULL, "\r\n= "); - //Steal from the motd code so you don't have to put the reason in quotes. - strlcpy(message, COM_Argv(2), sizeof message); - for (i = 3; i < j; i++) + if (!value) + I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. + // Others can't go in there because we don't want them to be patchable. + if (!stricmp(stoken, "name")) + { + INT32 skinnum = R_SkinAvailable(value); + strlwr(value); + if (skinnum == -1) + STRBUFCPY(skin->name, value); + // the skin name must uniquely identify a single skin + // if the name is already used I make the name 'namex' + // using the default skin name's number set above + else { - strlcat(message, " ", sizeof message); - strlcat(message, COM_Argv(i), sizeof message); + const size_t stringspace = + strlen(value) + sizeof (numskins) + 1; + char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL); + snprintf(value2, stringspace, + "%s%d", value, numskins); + value2[stringspace - 1] = '\0'; + if (R_SkinAvailable(value2) == -1) + // I'm lazy so if NEW name is already used I leave the 'skin x' + // default skin name set in Sk_SetDefaultValue + STRBUFCPY(skin->name, value2); + Z_Free(value2); } - WRITEUINT8(p, KICK_MSG_CUSTOM_BAN); - WRITESTRINGN(p, message, MAX_REASONLENGTH); - SendNetXCmd(XD_KICK, &buf, p - buf); - } - } - } - else - CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); - -} - -static void Command_BanIP(void) -{ - if (COM_Argc() < 2) - { - CONS_Printf(M_GetText("banip : ban an ip address\n")); - return; - } - - if (server) // Only the server can use this, otherwise does nothing. - { - const char *address = (COM_Argv(1)); - const char *reason; - - if (COM_Argc() == 2) - reason = NULL; - else - reason = COM_Argv(2); - - - if (I_SetBanAddress && I_SetBanAddress(address, NULL)) - { - if (reason) - CONS_Printf("Banned IP address %s for: %s\n", address, reason); - else - CONS_Printf("Banned IP address %s\n", address); - - Ban_Add(reason); - D_SaveBan(); - } - else - { - return; - } - } -} - -static void Command_Kick(void) -{ - if (COM_Argc() < 2) - { - CONS_Printf(M_GetText("kick : kick a player\n")); - return; - } - - //if (!netgame) // Don't kick Tails in splitscreen! - //{ - // CONS_Printf(M_GetText("This only works in a netgame.\n")); - // return; - //} - - if (server || IsPlayerAdmin(consoleplayer)) - { - UINT8 buf[3 + MAX_REASONLENGTH]; - UINT8 *p = buf; - const SINT8 pn = nametonum(COM_Argv(1)); - - if (splitscreen && (pn == 0 || pn == 1)) - { - CONS_Printf(M_GetText("Splitscreen players cannot be kicked.\n")); - return; - } - if (pn == -1 || pn == 0) - return; - - // Special case if we are trying to kick a player who is downloading the game state: - // trigger a timeout instead of kicking them, because a kick would only - // take effect after they have finished downloading - if (server && playernode[pn] != UINT8_MAX && sendingsavegame[playernode[pn]]) - { - Net_ConnectionTimeout(playernode[pn]); - return; - } - - WRITESINT8(p, pn); - - if (COM_Argc() == 2) - { - WRITEUINT8(p, KICK_MSG_GO_AWAY); - SendNetXCmd(XD_KICK, &buf, 2); - } - else - { - size_t i, j = COM_Argc(); - char message[MAX_REASONLENGTH]; - - //Steal from the motd code so you don't have to put the reason in quotes. - strlcpy(message, COM_Argv(2), sizeof message); - for (i = 3; i < j; i++) - { - strlcat(message, " ", sizeof message); - strlcat(message, COM_Argv(i), sizeof message); - } - - WRITEUINT8(p, KICK_MSG_CUSTOM_KICK); - WRITESTRINGN(p, message, MAX_REASONLENGTH); - SendNetXCmd(XD_KICK, &buf, p - buf); - } - } - else - CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); -} -#endif - -static void Got_KickCmd(UINT8 **p, INT32 playernum) -{ - INT32 pnum, msg; - char buf[3 + MAX_REASONLENGTH]; - char *reason = buf; - kickreason_t kickreason = KR_KICK; - boolean keepbody; - - pnum = READUINT8(*p); - msg = READUINT8(*p); - keepbody = (msg & KICK_MSG_KEEP_BODY) != 0; - msg &= ~KICK_MSG_KEEP_BODY; - - if (pnum == serverplayer && IsPlayerAdmin(playernum)) - { - CONS_Printf(M_GetText("Server is being shut down remotely. Goodbye!\n")); - - if (server) - COM_BufAddText("quit\n"); - - return; - } - - // Is playernum authorized to make this kick? - if (playernum != serverplayer && !IsPlayerAdmin(playernum) - && !(playernode[playernum] != UINT8_MAX && playerpernode[playernode[playernum]] == 2 - && nodetoplayer2[playernode[playernum]] == pnum)) - { - // We received a kick command from someone who isn't the - // server or admin, and who isn't in splitscreen removing - // player 2. Thus, it must be someone with a modified - // binary, trying to kick someone but without having - // authorization. - - // We deal with this by changing the kick reason to - // "consistency failure" and kicking the offending user - // instead. - - // Note: Splitscreen in netgames is broken because of - // this. Only the server has any idea of which players - // are using splitscreen on the same computer, so - // clients cannot always determine if a kick is - // legitimate. - - CONS_Alert(CONS_WARNING, M_GetText("Illegal kick command received from %s for player %d\n"), player_names[playernum], pnum); - - // In debug, print a longer message with more details. - // TODO Callum: Should we translate this? -/* - CONS_Debug(DBG_NETPLAY, - "So, you must be asking, why is this an illegal kick?\n" - "Well, let's take a look at the facts, shall we?\n" - "\n" - "playernum (this is the guy who did it), he's %d.\n" - "pnum (the guy he's trying to kick) is %d.\n" - "playernum's node is %d.\n" - "That node has %d players.\n" - "Player 2 on that node is %d.\n" - "pnum's node is %d.\n" - "That node has %d players.\n" - "Player 2 on that node is %d.\n" - "\n" - "If you think this is a bug, please report it, including all of the details above.\n", - playernum, pnum, - playernode[playernum], playerpernode[playernode[playernum]], - nodetoplayer2[playernode[playernum]], - playernode[pnum], playerpernode[playernode[pnum]], - nodetoplayer2[playernode[pnum]]); -*/ - pnum = playernum; - msg = KICK_MSG_CON_FAIL; - keepbody = true; - } - - //CONS_Printf("\x82%s ", player_names[pnum]); - - // If a verified admin banned someone, the server needs to know about it. - // If the playernum isn't zero (the server) then the server needs to record the ban. - if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN)) - { - if (I_Ban && !I_Ban(playernode[(INT32)pnum])) - CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n")); -#ifndef NONET - else - Ban_Add(reason); -#endif - } - - switch (msg) - { - case KICK_MSG_GO_AWAY: - if (!players[pnum].quittime) - HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false); - kickreason = KR_KICK; - break; - case KICK_MSG_PING_HIGH: - HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false); - kickreason = KR_PINGLIMIT; - break; - case KICK_MSG_CON_FAIL: - HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false); - kickreason = KR_SYNCH; - - if (M_CheckParm("-consisdump")) // Helps debugging some problems - { - INT32 i; - - CONS_Printf(M_GetText("Player kicked is #%d, dumping consistency...\n"), pnum); - - for (i = 0; i < MAXPLAYERS; i++) + // copy to hudname and fullname as a default. + if (!realname) { - if (!playeringame[i]) - continue; - CONS_Printf("-------------------------------------\n"); - CONS_Printf("Player %d: %s\n", i, player_names[i]); - CONS_Printf("Skin: %d\n", players[i].skin); - CONS_Printf("Color: %d\n", players[i].skincolor); - CONS_Printf("Speed: %d\n",players[i].speed>>FRACBITS); - if (players[i].mo) + STRBUFCPY(skin->realname, skin->name); + for (value = skin->realname; *value; value++) { - if (!players[i].mo->skin) - CONS_Printf("Mobj skin: NULL!\n"); - else - CONS_Printf("Mobj skin: %s\n", ((skin_t *)players[i].mo->skin)->name); - CONS_Printf("Position: %d, %d, %d\n", players[i].mo->x, players[i].mo->y, players[i].mo->z); - if (!players[i].mo->state) - CONS_Printf("State: S_NULL\n"); - else - CONS_Printf("State: %d\n", (statenum_t)(players[i].mo->state-states)); + if (*value == '_') *value = ' '; // turn _ into spaces. + else if (*value == '.') *value = '\x1E'; // turn . into katana dot. } + } + if (!hudname) + { + HUDNAMEWRITE(skin->name); + strupr(skin->hudname); + SYMBOLCONVERT(skin->hudname) + } + } + else if (!stricmp(stoken, "realname")) + { // Display name (eg. "Knuckles") + realname = true; + STRBUFCPY(skin->realname, value); + SYMBOLCONVERT(skin->realname) + if (!hudname) + HUDNAMEWRITE(skin->realname); + } + else if (!stricmp(stoken, "hudname")) + { // Life icon name (eg. "K.T.E") + hudname = true; + HUDNAMEWRITE(value); + SYMBOLCONVERT(skin->hudname) + if (!realname) + STRBUFCPY(skin->realname, skin->hudname); + } + else if (!stricmp(stoken, "availability")) + { + skin->availability = atoi(value); + if (skin->availability >= MAXUNLOCKABLES) + skin->availability = 0; + } + else if (!R_ProcessPatchableFields(skin, stoken, value)) + CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); + +next_token: + stoken = strtok(NULL, "\r\n= "); + } + free(buf2); + + // Add sprites + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + //ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere + + R_FlushTranslationColormapCache(); + + if (!skin->availability) // Safe to print... + CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); +#ifdef SKINVALUES + skin_cons_t[numskins].value = numskins; + skin_cons_t[numskins].strvalue = skin->name; +#endif + +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_AddPlayerModel(numskins); +#endif + + numskins++; + } + return; +} + +// +// Patch skin sprites +// +void R_PatchSkins(UINT16 wadnum) +{ + UINT16 lump, lastlump = 0; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean noskincomplain, realname, hudname; + + // + // search for all skin patch markers in pwad + // + + while ((lump = W_CheckForPatchSkinMarkerInPwad(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_PatchSkins: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + skin = NULL; + noskincomplain = realname = hudname = 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_PatchSkins: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + if (!skin) // Get the name! + { + if (!stricmp(stoken, "name")) + { + strlwr(value); + skinnum = R_SkinAvailable(value); + if (skinnum != -1) + skin = &skins[skinnum]; else - CONS_Printf("Mobj: NULL\n"); - CONS_Printf("-------------------------------------\n"); - } - } - break; - case KICK_MSG_TIMEOUT: - HU_AddChatText(va("\x82*%s left the game (Connection timeout)", player_names[pnum]), false); - kickreason = KR_TIMEOUT; - break; - case KICK_MSG_PLAYER_QUIT: - if (netgame && !players[pnum].quittime) // not splitscreen/bots or soulless body - HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false); - kickreason = KR_LEAVE; - break; - case KICK_MSG_BANNED: - HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false); - kickreason = KR_BAN; - break; - case KICK_MSG_CUSTOM_KICK: - READSTRINGN(*p, reason, MAX_REASONLENGTH+1); - HU_AddChatText(va("\x82*%s has been kicked (%s)", player_names[pnum], reason), false); - kickreason = KR_KICK; - break; - case KICK_MSG_CUSTOM_BAN: - READSTRINGN(*p, reason, MAX_REASONLENGTH+1); - HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false); - kickreason = KR_BAN; - break; - } - - if (pnum == consoleplayer) - { - if (Playing()) - LUAh_GameQuit(); -#ifdef DUMPCONSISTENCY - if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); -#endif - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - if (msg == KICK_MSG_CON_FAIL) - M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING); - else if (msg == KICK_MSG_PING_HIGH) - M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING); - else if (msg == KICK_MSG_BANNED) - M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING); - else if (msg == KICK_MSG_CUSTOM_KICK) - M_StartMessage(va(M_GetText("You have been kicked\n(%s)\nPress ESC\n"), reason), NULL, MM_NOTHING); - else if (msg == KICK_MSG_CUSTOM_BAN) - M_StartMessage(va(M_GetText("You have been banned\n(%s)\nPress ESC\n"), reason), NULL, MM_NOTHING); - else - M_StartMessage(M_GetText("You have been kicked by the server\n\nPress ESC\n"), NULL, MM_NOTHING); - } - else if (keepbody) - { - if (server && !demoplayback && playernode[pnum] != UINT8_MAX) - { - INT32 node = playernode[pnum]; - playerpernode[node]--; - if (playerpernode[node] <= 0) - { - nodeingame[node] = false; - Net_CloseConnection(node); - ResetNode(node); - } - } - - playernode[pnum] = UINT8_MAX; - - players[pnum].quittime = 1; - } - else - CL_RemovePlayer(pnum, kickreason); -} - -static void Command_ResendGamestate(void) -{ - SINT8 playernum; - - if (COM_Argc() == 1) - { - CONS_Printf(M_GetText("resendgamestate : resend the game state to a player\n")); - return; - } - else if (client) - { - CONS_Printf(M_GetText("Only the server can use this.\n")); - return; - } - - playernum = nametonum(COM_Argv(1)); - if (playernum == -1 || playernum == 0) - return; - - // Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on - netbuffer->packettype = PT_WILLRESENDGAMESTATE; - if (!HSendPacket(playernode[playernum], true, 0, 0)) - { - CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n")); - return; - } -} - -static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; -consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); - -consvar_t cv_allownewplayer = CVAR_INIT ("allowjoin", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); -consvar_t cv_joinnextround = CVAR_INIT ("joinnextround", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); /// \todo not done -static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_maxplayers = CVAR_INIT ("maxplayers", "8", CV_SAVE|CV_NETVAR, maxplayers_cons_t, NULL); -static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_joindelay = CVAR_INIT ("joindelay", "10", CV_SAVE|CV_NETVAR, joindelay_cons_t, NULL); -static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}}; -consvar_t cv_rejointimeout = CVAR_INIT ("rejointimeout", "Off", CV_SAVE|CV_NETVAR|CV_FLOAT, rejointimeout_cons_t, NULL); - -static CV_PossibleValue_t resynchattempts_cons_t[] = {{1, "MIN"}, {20, "MAX"}, {0, "No"}, {0, NULL}}; -consvar_t cv_resynchattempts = CVAR_INIT ("resynchattempts", "10", CV_SAVE|CV_NETVAR, resynchattempts_cons_t, NULL); -consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -// max file size to send to a player (in kilobytes) -static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; -consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL); -consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); - -// Speed of file downloading (in packets per tic) -static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; -consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); - -static void Got_AddPlayer(UINT8 **p, INT32 playernum); - -// called one time at init -void D_ClientServerInit(void) -{ - DEBFILE(va("- - -== SRB2 v%d.%.2d.%d "VERSIONSTRING" debugfile ==- - -\n", - VERSION/100, VERSION%100, SUBVERSION)); - -#ifndef NONET - COM_AddCommand("getplayernum", Command_GetPlayerNum); - COM_AddCommand("kick", Command_Kick); - COM_AddCommand("ban", Command_Ban); - COM_AddCommand("banip", Command_BanIP); - COM_AddCommand("clearbans", Command_ClearBans); - COM_AddCommand("showbanlist", Command_ShowBan); - COM_AddCommand("reloadbans", Command_ReloadBan); - COM_AddCommand("connect", Command_connect); - COM_AddCommand("nodes", Command_Nodes); - COM_AddCommand("resendgamestate", Command_ResendGamestate); -#ifdef PACKETDROP - COM_AddCommand("drop", Command_Drop); - COM_AddCommand("droprate", Command_Droprate); -#endif -#ifdef _DEBUG - COM_AddCommand("numnodes", Command_Numnodes); -#endif -#endif - - RegisterNetXCmd(XD_KICK, Got_KickCmd); - RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); -#ifndef NONET -#ifdef DUMPCONSISTENCY - CV_RegisterVar(&cv_dumpconsistency); -#endif - Ban_Load_File(false); -#endif - - gametic = 0; - localgametic = 0; - - // do not send anything before the real begin - SV_StopServer(); - SV_ResetServer(); - if (dedicated) - SV_SpawnServer(); -} - -static void ResetNode(INT32 node) -{ - nodeingame[node] = false; - nodewaiting[node] = 0; - - nettics[node] = gametic; - supposedtics[node] = gametic; - - nodetoplayer[node] = -1; - nodetoplayer2[node] = -1; - playerpernode[node] = 0; - - sendingsavegame[node] = false; - resendingsavegame[node] = false; - savegameresendcooldown[node] = 0; -} - -void SV_ResetServer(void) -{ - INT32 i; - - // +1 because this command will be executed in com_executebuffer in - // tryruntic so gametic will be incremented, anyway maketic > gametic - // is not an issue - - maketic = gametic + 1; - neededtic = maketic; - tictoclear = maketic; - - joindelay = 0; - - for (i = 0; i < MAXNETNODES; i++) - ResetNode(i); - - for (i = 0; i < MAXPLAYERS; i++) - { - LUA_InvalidatePlayer(&players[i]); - playeringame[i] = false; - playernode[i] = UINT8_MAX; - memset(playeraddress[i], 0, sizeof(*playeraddress)); - sprintf(player_names[i], "Player %d", i + 1); - adminplayers[i] = -1; // Populate the entire adminplayers array with -1. - } - - memset(player_name_changes, 0, sizeof player_name_changes); - - mynode = 0; - cl_packetmissed = false; - cl_redownloadinggamestate = false; - - if (dedicated) - { - nodeingame[0] = true; - serverplayer = 0; - } - else - serverplayer = consoleplayer; - - if (server) - servernode = 0; - - doomcom->numslots = 0; - - // clear server_context - memset(server_context, '-', 8); - - DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); -} - -static inline void SV_GenContext(void) -{ - UINT8 i; - // generate server_context, as exactly 8 bytes of randomly mixed A-Z and a-z - // (hopefully M_Random is initialized!! if not this will be awfully silly!) - for (i = 0; i < 8; i++) - { - const char a = M_RandomKey(26*2); - if (a < 26) // uppercase - server_context[i] = 'A'+a; - else // lowercase - server_context[i] = 'a'+(a-26); - } -} - -// -// D_QuitNetGame -// Called before quitting to leave a net game -// without hanging the other players -// -void D_QuitNetGame(void) -{ - if (!netgame || !netbuffer) - return; - - DEBFILE("===========================================================================\n" - " Quitting Game, closing connection\n" - "===========================================================================\n"); - - // abort send/receive of files - CloseNetFile(); - RemoveAllLuaFileTransfers(); - waitingforluafiletransfer = false; - waitingforluafilecommand = false; - - if (server) - { - INT32 i; - - netbuffer->packettype = PT_SERVERSHUTDOWN; - for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i]) - HSendPacket(i, true, 0, 0); -#ifdef MASTERSERVER - if (serverrunning && ms_RoomId > 0) - UnregisterServer(); -#endif - } - else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]) - { - netbuffer->packettype = PT_CLIENTQUIT; - HSendPacket(servernode, true, 0, 0); - } - - D_CloseConnection(); - ClearAdminPlayers(); - - DEBFILE("===========================================================================\n" - " Log finish\n" - "===========================================================================\n"); -#ifdef DEBUGFILE - if (debugfile) - { - fclose(debugfile); - debugfile = NULL; - } -#endif -} - -// Adds a node to the game (player will follow at map change or at savegame....) -static inline void SV_AddNode(INT32 node) -{ - nettics[node] = gametic; - supposedtics[node] = gametic; - // little hack because the server connects to itself and puts - // nodeingame when connected not here - if (node) - nodeingame[node] = true; -} - -// Xcmd XD_ADDPLAYER -static void Got_AddPlayer(UINT8 **p, INT32 playernum) -{ - INT16 node, newplayernum; - boolean splitscreenplayer; - boolean rejoined; - player_t *newplayer; - - if (playernum != serverplayer && !IsPlayerAdmin(playernum)) - { - // protect against hacked/buggy client - CONS_Alert(CONS_WARNING, M_GetText("Illegal add player command received from %s\n"), player_names[playernum]); - if (server) - SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - return; - } - - node = READUINT8(*p); - newplayernum = READUINT8(*p); - splitscreenplayer = newplayernum & 0x80; - newplayernum &= ~0x80; - - rejoined = playeringame[newplayernum]; - - if (!rejoined) - { - // Clear player before joining, lest some things get set incorrectly - // HACK: don't do this for splitscreen, it relies on preset values - if (!splitscreen && !botingame) - CL_ClearPlayer(newplayernum); - playeringame[newplayernum] = true; - G_AddPlayer(newplayernum); - if (newplayernum+1 > doomcom->numslots) - doomcom->numslots = (INT16)(newplayernum+1); - - if (server && I_GetNodeAddress) - { - 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'; - } - } - } - - newplayer = &players[newplayernum]; - - newplayer->jointime = 0; - newplayer->quittime = 0; - - READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); - - // the server is creating my player - if (node == mynode) - { - playernode[newplayernum] = 0; // for information only - if (!splitscreenplayer) - { - consoleplayer = newplayernum; - displayplayer = newplayernum; - secondarydisplayplayer = newplayernum; - DEBFILE("spawning me\n"); - ticcmd_oldangleturn[0] = newplayer->oldrelangleturn; - } - else - { - secondarydisplayplayer = newplayernum; - DEBFILE("spawning my brother\n"); - if (botingame) - newplayer->bot = 1; - ticcmd_oldangleturn[1] = newplayer->oldrelangleturn; - } - P_ForceLocalAngle(newplayer, (angle_t)(newplayer->angleturn << 16)); - D_SendPlayerConfig(); - addedtogame = true; - - if (rejoined) - { - if (newplayer->mo) - { - newplayer->viewheight = 41*newplayer->height/48; - - if (newplayer->mo->eflags & MFE_VERTICALFLIP) - newplayer->viewz = newplayer->mo->z + newplayer->mo->height - newplayer->viewheight; - else - newplayer->viewz = newplayer->mo->z + newplayer->viewheight; - } - - // wake up the status bar - ST_Start(); - // wake up the heads up text - HU_Start(); - - if (camera.chase && !splitscreenplayer) - P_ResetCamera(newplayer, &camera); - if (camera2.chase && splitscreenplayer) - P_ResetCamera(newplayer, &camera2); - } - } - - if (netgame) - { - char joinmsg[256]; - - if (rejoined) - strcpy(joinmsg, M_GetText("\x82*%s has rejoined the game (player %d)")); - else - strcpy(joinmsg, M_GetText("\x82*%s has joined the game (player %d)")); - strcpy(joinmsg, va(joinmsg, player_names[newplayernum], newplayernum)); - - // Merge join notification + IP to avoid clogging console/chat - if (server && cv_showjoinaddress.value && I_GetNodeAddress) - { - const char *address = I_GetNodeAddress(node); - if (address) - strcat(joinmsg, va(" (%s)", address)); - } - - HU_AddChatText(joinmsg, false); - } - - if (server && multiplayer && motd[0] != '\0') - COM_BufAddText(va("sayto %d %s\n", newplayernum, motd)); - - if (!rejoined) - LUAh_PlayerJoin(newplayernum); -} - -static boolean SV_AddWaitingPlayers(const char *name, const char *name2) -{ - INT32 node, n, newplayer = false; - UINT8 buf[2 + MAXPLAYERNAME]; - UINT8 *p; - INT32 newplayernum; - - for (node = 0; node < MAXNETNODES; node++) - { - // splitscreen can allow 2 player in one node - for (; nodewaiting[node] > 0; nodewaiting[node]--) - { - newplayer = true; - - newplayernum = FindRejoinerNum(node); - if (newplayernum == -1) - { - // search for a free playernum - // we can't use playeringame since it is not updated here - for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) - { - if (playeringame[newplayernum]) - continue; - for (n = 0; n < MAXNETNODES; n++) - if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum) - break; - if (n == MAXNETNODES) - break; - } - } - - // should never happen since we check the playernum - // before accepting the join - I_Assert(newplayernum < MAXPLAYERS); - - playernode[newplayernum] = (UINT8)node; - - p = buf + 2; - buf[0] = (UINT8)node; - buf[1] = newplayernum; - if (playerpernode[node] < 1) - { - nodetoplayer[node] = newplayernum; - WRITESTRINGN(p, name, MAXPLAYERNAME); - } - else - { - nodetoplayer2[node] = newplayernum; - buf[1] |= 0x80; - WRITESTRINGN(p, name2, MAXPLAYERNAME); - } - playerpernode[node]++; - - SendNetXCmd(XD_ADDPLAYER, &buf, p - buf); - - DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); - } - } - - return newplayer; -} - -void CL_AddSplitscreenPlayer(void) -{ - if (cl_mode == CL_CONNECTED) - CL_SendJoin(); -} - -void CL_RemoveSplitscreenPlayer(void) -{ - if (cl_mode != CL_CONNECTED) - return; - - SendKick(secondarydisplayplayer, KICK_MSG_PLAYER_QUIT); -} - -// is there a game running -boolean Playing(void) -{ - return (server && serverrunning) || (client && cl_mode == CL_CONNECTED); -} - -boolean SV_SpawnServer(void) -{ - if (demoplayback) - G_StopDemo(); // reset engine parameter - if (metalplayback) - G_StopMetalDemo(); - - if (!serverrunning) - { - CONS_Printf(M_GetText("Starting Server....\n")); - serverrunning = true; - SV_ResetServer(); - SV_GenContext(); - if (netgame && I_NetOpenSocket) - { - I_NetOpenSocket(); -#ifdef MASTERSERVER - if (ms_RoomId > 0) - RegisterServer(); -#endif - } - - // non dedicated server just connect to itself - if (!dedicated) - CL_ConnectToServer(); - else doomcom->numslots = 1; - } - - return SV_AddWaitingPlayers(cv_playername.zstring, cv_playername2.zstring); -} - -void SV_StopServer(void) -{ - tic_t i; - - if (gamestate == GS_INTERMISSION) - Y_EndIntermission(); - gamestate = wipegamestate = GS_NULL; - - localtextcmd[0] = 0; - localtextcmd2[0] = 0; - - for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++) - D_Clearticcmd(i); - - consoleplayer = 0; - cl_mode = CL_SEARCHING; - maketic = gametic+1; - neededtic = maketic; - serverrunning = false; -} - -// called at singleplayer start and stopdemo -void SV_StartSinglePlayerServer(void) -{ - server = true; - netgame = false; - multiplayer = false; - G_SetGametype(GT_COOP); - - // no more tic the game with this settings! - SV_StopServer(); - - if (splitscreen) - multiplayer = true; -} - -static void SV_SendRefuse(INT32 node, const char *reason) -{ - strcpy(netbuffer->u.serverrefuse.reason, reason); - - netbuffer->packettype = PT_SERVERREFUSE; - HSendPacket(node, true, 0, strlen(netbuffer->u.serverrefuse.reason) + 1); - Net_CloseConnection(node); -} - -// used at txtcmds received to check packetsize bound -static size_t TotalTextCmdPerTic(tic_t tic) -{ - INT32 i; - size_t total = 1; // num of textcmds in the tic (ntextcmd byte) - - for (i = 0; i < MAXPLAYERS; i++) - { - UINT8 *textcmd = D_GetExistingTextcmd(tic, i); - if ((!i || playeringame[i]) && textcmd) - total += 2 + textcmd[0]; // "+2" for size and playernum - } - - return total; -} - -/** Called when a PT_CLIENTJOIN packet is received - * - * \param node The packet sender - * - */ -static void HandleConnect(SINT8 node) -{ - char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; - INT32 rejoinernum; - INT32 i; - - rejoinernum = FindRejoinerNum(node); - - if (bannednode && bannednode[node]) - SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server.")); - else if (netbuffer->u.clientcfg._255 != 255 || - netbuffer->u.clientcfg.packetversion != PACKETVERSION) - SV_SendRefuse(node, "Incompatible packet formats."); - else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION, - sizeof netbuffer->u.clientcfg.application)) - SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible."); - else if (netbuffer->u.clientcfg.version != VERSION - || netbuffer->u.clientcfg.subversion != SUBVERSION) - SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION)); - else if (!cv_allownewplayer.value && node && rejoinernum == -1) - SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment.")); - else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1) - SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value)); - else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client? - SV_SendRefuse(node, M_GetText("Too many players from\nthis node.")); - else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join? - SV_SendRefuse(node, M_GetText("No players from\nthis node.")); - else if (luafiletransfers) - SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining.")); - else if (netgame && joindelay > 2 * (tic_t)cv_joindelay.value * TICRATE) - SV_SendRefuse(node, va(M_GetText("Too many people are connecting.\nPlease wait %d seconds and then\ntry rejoining."), - (joindelay - 2 * cv_joindelay.value * TICRATE) / TICRATE)); - else - { -#ifndef NONET - boolean newnode = false; -#endif - - for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++) - { - strlcpy(names[i], netbuffer->u.clientcfg.names[i], MAXPLAYERNAME + 1); - if (!EnsurePlayerNameIsGood(names[i], rejoinernum)) - { - SV_SendRefuse(node, "Bad player name"); - return; - } - } - - // client authorised to join - nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); - if (!nodeingame[node]) - { - gamestate_t backupstate = gamestate; -#ifndef NONET - newnode = true; -#endif - SV_AddNode(node); - - if (cv_joinnextround.value && gameaction == ga_nothing) - G_SetGamestate(GS_WAITINGPLAYERS); - if (!SV_SendServerConfig(node)) - { - G_SetGamestate(backupstate); - /// \note Shouldn't SV_SendRefuse be called before ResetNode? - ResetNode(node); - SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); - /// \todo fix this !!! - return; // restart the while - } - //if (gamestate != GS_LEVEL) // GS_INTERMISSION, etc? - // SV_SendPlayerConfigs(node); // send bare minimum player info - G_SetGamestate(backupstate); - DEBFILE("new node joined\n"); - } -#ifndef NONET - if (nodewaiting[node]) - { - if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && newnode) - { - SV_SendSaveGame(node, false); // send a complete game state - DEBFILE("send savegame\n"); - } - SV_AddWaitingPlayers(names[0], names[1]); - joindelay += cv_joindelay.value * TICRATE; - player_joining = true; - } -#endif - } -} - -/** Called when a PT_SERVERSHUTDOWN packet is received - * - * \param node The packet sender (should be the server) - * - */ -static void HandleShutdown(SINT8 node) -{ - (void)node; - if (Playing()) - LUAh_GameQuit(); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING); -} - -/** Called when a PT_NODETIMEOUT packet is received - * - * \param node The packet sender (should be the server) - * - */ -static void HandleTimeout(SINT8 node) -{ - (void)node; - if (Playing()) - LUAh_GameQuit(); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); -} - -#ifndef NONET -/** Called when a PT_SERVERINFO packet is received - * - * \param node The packet sender - * \note What happens if the packet comes from a client or something like that? - * - */ -static void HandleServerInfo(SINT8 node) -{ - // compute ping in ms - const tic_t ticnow = I_GetTime(); - const tic_t ticthen = (tic_t)LONG(netbuffer->u.serverinfo.time); - const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE; - netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff); - netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0; - netbuffer->u.serverinfo.application - [sizeof netbuffer->u.serverinfo.application - 1] = '\0'; - netbuffer->u.serverinfo.gametypename - [sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0'; - - SL_InsertServer(&netbuffer->u.serverinfo, node); -} -#endif - -static void PT_WillResendGamestate(void) -{ - char tmpsave[256]; - - if (server || cl_redownloadinggamestate) - return; - - // Send back a PT_CANRECEIVEGAMESTATE packet to the server - // so they know they can start sending the game state - netbuffer->packettype = PT_CANRECEIVEGAMESTATE; - if (!HSendPacket(servernode, true, 0, 0)) - return; - - CONS_Printf(M_GetText("Reloading game state...\n")); - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - - // Don't get a corrupt savegame error because tmpsave already exists - if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) - I_Error("Can't delete %s\n", tmpsave); - - CL_PrepareDownloadSaveGame(tmpsave); - - cl_redownloadinggamestate = true; -} - -static void PT_CanReceiveGamestate(SINT8 node) -{ - if (client || sendingsavegame[node]) - return; - - CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]); - - SV_SendSaveGame(node, true); // Resend a complete game state - resendingsavegame[node] = true; -} - -/** Handles a packet received from a node that isn't in game - * - * \param node The packet sender - * \todo Choose a better name, as the packet can also come from the server apparently? - * \sa HandlePacketFromPlayer - * \sa GetPackets - * - */ -static void HandlePacketFromAwayNode(SINT8 node) -{ - if (node != servernode) - DEBFILE(va("Received packet from unknown host %d\n", node)); - -// macro for packets that should only be sent by the server -// if it is NOT from the server, bail out and close the connection! -#define SERVERONLY \ - if (node != servernode) \ - { \ - Net_CloseConnection(node); \ - break; \ - } - switch (netbuffer->packettype) - { - case PT_ASKINFOVIAMS: -#if 0 - if (server && serverrunning) - { - INT32 clientnode; - if (ms_RoomId < 0) // ignore if we're not actually on the MS right now - { - Net_CloseConnection(node); // and yes, close connection - return; - } - clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr); - if (clientnode != -1) - { - SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time)); - SV_SendPlayerInfo(clientnode); // Send extra info - Net_CloseConnection(clientnode); - // Don't close connection to MS... - } - else - Net_CloseConnection(node); // ...unless the IP address is not valid - } - else - Net_CloseConnection(node); // you're not supposed to get it, so ignore it -#else - Net_CloseConnection(node); -#endif - break; - - case PT_ASKINFO: - if (server && serverrunning) - { - SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); - SV_SendPlayerInfo(node); // Send extra info - } - Net_CloseConnection(node); - break; - - case PT_SERVERREFUSE: // Negative response of client join request - if (server && serverrunning) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - if (cl_mode == CL_WAITJOINRESPONSE) - { - // Save the reason so it can be displayed after quitting the netgame - char *reason = strdup(netbuffer->u.serverrefuse.reason); - if (!reason) - I_Error("Out of memory!\n"); - - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - - M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"), - reason), NULL, MM_NOTHING); - - free(reason); - - // Will be reset by caller. Signals refusal. - cl_mode = CL_ABORTED; - } - break; - - case PT_SERVERCFG: // Positive response of client join request - { - if (server && serverrunning && node != servernode) - { // but wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - /// \note how would this happen? and is it doing the right thing if it does? - if (cl_mode != CL_WAITJOINRESPONSE) - break; - - if (client) - { - maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); - G_SetGametype(netbuffer->u.servercfg.gametype); - modifiedgame = netbuffer->u.servercfg.modifiedgame; - memcpy(server_context, netbuffer->u.servercfg.server_context, 8); - } - - nodeingame[(UINT8)servernode] = true; - serverplayer = netbuffer->u.servercfg.serverplayer; - doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); - mynode = netbuffer->u.servercfg.clientnode; - if (serverplayer >= 0) - playernode[(UINT8)serverplayer] = servernode; - - if (netgame) -#ifndef NONET - CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); -#else - CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); -#endif - DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); - -#ifndef NONET - /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? - /// Shouldn't them be downloaded even at intermission time? - /// Also, according to HandleConnect, the server will send the savegame even during intermission... - if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || - netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) - cl_mode = CL_DOWNLOADSAVEGAME; - else -#endif - cl_mode = CL_CONNECTED; - break; - } - - // Handled in d_netfil.c - case PT_FILEFRAGMENT: - if (server) - { // But wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - SERVERONLY - PT_FileFragment(); - break; - - case PT_FILEACK: - if (server) - PT_FileAck(); - break; - - case PT_FILERECEIVED: - if (server) - PT_FileReceived(); - break; - - case PT_REQUESTFILE: - if (server) - { - if (!cv_downloading.value || !PT_RequestFile(node)) - Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway - } - else - Net_CloseConnection(node); // nope - break; - - case PT_NODETIMEOUT: - case PT_CLIENTQUIT: - if (server) - Net_CloseConnection(node); - break; - - case PT_CLIENTCMD: - break; // This is not an "unknown packet" - - case PT_SERVERTICS: - // Do not remove my own server (we have just get a out of order packet) - if (node == servernode) - break; - /* FALLTHRU */ - - default: - DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); - Net_CloseConnection(node); - break; // Ignore it - - } -#undef SERVERONLY -} - -/** Handles a packet received from a node that is in game - * - * \param node The packet sender - * \todo Choose a better name - * \sa HandlePacketFromAwayNode - * \sa GetPackets - * - */ -static void HandlePacketFromPlayer(SINT8 node) -{ - INT32 netconsole; - tic_t realend, realstart; - UINT8 *pak, *txtpak, numtxtpak; -#ifndef NOMD5 - UINT8 finalmd5[16];/* Well, it's the cool thing to do? */ -#endif - - txtpak = NULL; - - if (dedicated && node == 0) - netconsole = 0; - else - netconsole = nodetoplayer[node]; -#ifdef PARANOIA - if (netconsole >= MAXPLAYERS) - I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); -#endif - - switch (netbuffer->packettype) - { -// -------------------------------------------- SERVER RECEIVE ---------- - case PT_CLIENTCMD: - case PT_CLIENT2CMD: - case PT_CLIENTMIS: - case PT_CLIENT2MIS: - case PT_NODEKEEPALIVE: - case PT_NODEKEEPALIVEMIS: - if (client) - break; - - // To save bytes, only the low byte of tic numbers are sent - // Use ExpandTics to figure out what the rest of the bytes are - realstart = ExpandTics(netbuffer->u.clientpak.client_tic, node); - realend = ExpandTics(netbuffer->u.clientpak.resendfrom, node); - - if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS - || netbuffer->packettype == PT_NODEKEEPALIVEMIS - || supposedtics[node] < realend) - { - supposedtics[node] = realend; - } - // Discard out of order packet - if (nettics[node] > realend) - { - DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node])); - break; - } - - // 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) - 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; - - // Copy ticcmd - G_MoveTiccmd(&netcmds[maketic%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) - { - CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); - //D_Clearticcmd(k); - - SendKick(netconsole, KICK_MSG_CON_FAIL); - break; - } - - // Splitscreen cmd - if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) - && nodetoplayer2[node] >= 0) - G_MoveTiccmd(&netcmds[maketic%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) - && !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() - && !SV_ResendingSavegameToAnyone()) - { - if (cv_resynchattempts.value) - { - // Tell the client we are about to resend them the gamestate - netbuffer->packettype = PT_WILLRESENDGAMESTATE; - HSendPacket(node, true, 0, 0); - - resendingsavegame[node] = true; - - if (cv_blamecfail.value) - CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), - netconsole+1, player_names[netconsole], - consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy)); - DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - break; - } - else - { - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - break; - } - } - break; - case PT_TEXTCMD2: // splitscreen special - netconsole = nodetoplayer2[node]; - /* FALLTHRU */ - case PT_TEXTCMD: - if (client) - break; - - if (netconsole < 0 || netconsole >= MAXPLAYERS) - Net_UnAcknowledgePacket(node); - else - { - size_t j; - tic_t tic = maketic; - UINT8 *textcmd; - - // ignore if the textcmd has a reported size of zero - // this shouldn't be sent at all - if (!netbuffer->u.textcmd[0]) - { - DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n", - node, netconsole)); - Net_UnAcknowledgePacket(node); - break; - } - - // ignore if the textcmd size var is actually larger than it should be - // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength - if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) - { - DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", - netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), - node, netconsole)); - Net_UnAcknowledgePacket(node); - break; - } - - // check if tic that we are making isn't too large else we cannot send it :( - // doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time - j = software_MAXPACKETLENGTH - - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE - + (doomcom->numslots+1)*sizeof(ticcmd_t)); - - // search a tic that have enougth space in the ticcmd - while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), - (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) - && tic < firstticstosend + BACKUPTICS) - tic++; - - if (tic >= firstticstosend + BACKUPTICS) - { - DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " - "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), - maketic, firstticstosend, node, netconsole)); - Net_UnAcknowledgePacket(node); - break; - } - - // Make sure we have a buffer - if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); - - DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", - tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); - - M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); - textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; - } - break; - case PT_LOGIN: - if (client) - break; - -#ifndef NOMD5 - if (doomcom->datalength < 16)/* ignore partial sends */ - break; - - if (!adminpasswordset) - { - CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[netconsole]); - break; - } - - // Do the final pass to compare with the sent md5 - D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", netconsole), &finalmd5); - - if (!memcmp(netbuffer->u.md5sum, finalmd5, 16)) - { - CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[netconsole]); - COM_BufInsertText(va("promote %d\n", netconsole)); // do this immediately - } - else - CONS_Printf(M_GetText("Password from %s failed.\n"), player_names[netconsole]); -#endif - break; - case PT_NODETIMEOUT: - case PT_CLIENTQUIT: - if (client) - break; - - // nodeingame will be put false in the execution of kick command - // this allow to send some packets to the quitting client to have their ack back - nodewaiting[node] = 0; - if (netconsole != -1 && playeringame[netconsole]) - { - UINT8 kickmsg; - - if (netbuffer->packettype == PT_NODETIMEOUT) - kickmsg = KICK_MSG_TIMEOUT; - else - kickmsg = KICK_MSG_PLAYER_QUIT; - kickmsg |= KICK_MSG_KEEP_BODY; - - SendKick(netconsole, kickmsg); - nodetoplayer[node] = -1; - - if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 - && playeringame[(UINT8)nodetoplayer2[node]]) - { - SendKick(nodetoplayer2[node], kickmsg); - nodetoplayer2[node] = -1; - } - } - Net_CloseConnection(node); - nodeingame[node] = false; - break; - case PT_CANRECEIVEGAMESTATE: - PT_CanReceiveGamestate(node); - break; - case PT_ASKLUAFILE: - if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED) - AddLuaFileToSendQueue(node, luafiletransfers->realfilename); - break; - case PT_HASLUAFILE: - if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING) - SV_HandleLuaFileSent(node); - break; - case PT_RECEIVEDGAMESTATE: - sendingsavegame[node] = false; - resendingsavegame[node] = false; - savegameresendcooldown[node] = I_GetTime() + 15 * TICRATE; - break; -// -------------------------------------------- CLIENT RECEIVE ---------- - case PT_SERVERTICS: - // Only accept PT_SERVERTICS from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - - realstart = netbuffer->u.serverpak.starttic; - realend = realstart + netbuffer->u.serverpak.numtics; - - if (!txtpak) - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; - - if (realend > gametic + CLIENTBACKUPTICS) - realend = gametic + CLIENTBACKUPTICS; - cl_packetmissed = realstart > neededtic; - - if (realstart <= neededtic && realend > neededtic) - { - tic_t i, j; - pak = (UINT8 *)&netbuffer->u.serverpak.cmds; - - for (i = realstart; i < realend; i++) - { - // clear first - D_Clearticcmd(i); - - // copy the tics - pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, - netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); - - // copy the textcmds - numtxtpak = *txtpak++; - for (j = 0; j < numtxtpak; j++) { - INT32 k = *txtpak++; // playernum - const size_t txtsize = txtpak[0]+1; - - if (i >= gametic) // Don't copy old net commands - M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); - txtpak += txtsize; - } - } - - neededtic = realend; - } - else - { - DEBFILE(va("frame not in bound: %u\n", neededtic)); - /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) - I_Error("Received an out of order PT_SERVERTICS packet!\n" - "Got tics %d-%d, needed tic %d\n\n" - "Please report this crash on the Master Board,\n" - "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ - } - break; - case PT_PING: - // Only accept PT_PING from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - - //Update client ping table from the server. - if (client) - { - UINT8 i; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; - - servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS]; - } - - break; - case PT_SERVERCFG: - break; - case PT_FILEFRAGMENT: - // Only accept PT_FILEFRAGMENT from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node); - if (server) - SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); - break; - } - if (client) - PT_FileFragment(); - break; - case PT_FILEACK: - if (server) - PT_FileAck(); - break; - case PT_FILERECEIVED: - if (server) - PT_FileReceived(); - break; - case PT_WILLRESENDGAMESTATE: - PT_WillResendGamestate(); - break; - case PT_SENDINGLUAFILE: - if (client) - CL_PrepareDownloadLuaFile(); - break; - default: - DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n", - netbuffer->packettype, node)); - } // end switch -} - -/** Handles all received packets, if any - * - * \todo Add details to this description (lol) - * - */ -static void GetPackets(void) -{ - SINT8 node; // The packet sender - - player_joining = false; - - while (HGetPacket()) - { - node = (SINT8)doomcom->remotenode; - - if (netbuffer->packettype == PT_CLIENTJOIN && server) - { - HandleConnect(node); - continue; - } - if (node == servernode && client && cl_mode != CL_SEARCHING) - { - if (netbuffer->packettype == PT_SERVERSHUTDOWN) - { - HandleShutdown(node); - continue; - } - if (netbuffer->packettype == PT_NODETIMEOUT) - { - HandleTimeout(node); - continue; - } - } - -#ifndef NONET - if (netbuffer->packettype == PT_SERVERINFO) - { - HandleServerInfo(node); - continue; - } -#endif - - if (netbuffer->packettype == PT_PLAYERINFO) - continue; // We do nothing with PLAYERINFO, that's for the MS browser. - - // Packet received from someone already playing - if (nodeingame[node]) - HandlePacketFromPlayer(node); - // Packet received from someone not playing - else - HandlePacketFromAwayNode(node); - } -} - -// -// NetUpdate -// Builds ticcmds for console player, -// sends out a packet -// -// no more use random generator, because at very first tic isn't yet synchronized -// Note: It is called consistAncy on purpose. -// -static INT16 Consistancy(void) -{ - INT32 i; - UINT32 ret = 0; -#ifdef MOBJCONSISTANCY - thinker_t *th; - mobj_t *mo; -#endif - - DEBFILE(va("TIC %u ", gametic)); - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - ret ^= 0xCCCC; - else if (!players[i].mo); - else - { - ret += players[i].mo->x; - ret -= players[i].mo->y; - ret += players[i].powers[pw_shield]; - ret *= i+1; - } - } - // I give up - // Coop desynching enemies is painful - if (!G_PlatformGametype()) - ret += P_GetRandSeed(); - -#ifdef MOBJCONSISTANCY - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo = (mobj_t *)th; - - if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) - { - ret -= mo->type; - ret += mo->x; - ret -= mo->y; - ret += mo->z; - ret -= mo->momx; - ret += mo->momy; - ret -= mo->momz; - ret += mo->angle; - ret -= mo->flags; - ret += mo->flags2; - ret -= mo->eflags; - if (mo->target) - { - ret += mo->target->type; - ret -= mo->target->x; - ret += mo->target->y; - ret -= mo->target->z; - ret += mo->target->momx; - ret -= mo->target->momy; - ret += mo->target->momz; - ret -= mo->target->angle; - ret += mo->target->flags; - ret -= mo->target->flags2; - ret += mo->target->eflags; - ret -= mo->target->state - states; - ret += mo->target->tics; - ret -= mo->target->sprite; - ret += mo->target->frame; - } - else - ret ^= 0x3333; - if (mo->tracer && mo->tracer->type != MT_OVERLAY) - { - ret += mo->tracer->type; - ret -= mo->tracer->x; - ret += mo->tracer->y; - ret -= mo->tracer->z; - ret += mo->tracer->momx; - ret -= mo->tracer->momy; - ret += mo->tracer->momz; - ret -= mo->tracer->angle; - ret += mo->tracer->flags; - ret -= mo->tracer->flags2; - ret += mo->tracer->eflags; - ret -= mo->tracer->state - states; - ret += mo->tracer->tics; - ret -= mo->tracer->sprite; - ret += mo->tracer->frame; - } - else - ret ^= 0xAAAA; - ret -= mo->state - states; - ret += mo->tics; - ret -= mo->sprite; - ret += mo->frame; - } - } -#endif - - DEBFILE(va("Consistancy = %u\n", (ret & 0xFFFF))); - - return (INT16)(ret & 0xFFFF); -} - -// send the client packet to the server -static void CL_SendClientCmd(void) -{ - size_t packetsize = 0; - - netbuffer->packettype = PT_CLIENTCMD; - - if (cl_packetmissed) - netbuffer->packettype++; - 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; - packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); - HSendPacket(servernode, false, 0, packetsize); - } - else if (gamestate != GS_NULL && (addedtogame || dedicated)) - { - 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); - packetsize = sizeof (client2cmd_pak); - } - else - packetsize = sizeof (clientcmd_pak); - - HSendPacket(servernode, false, 0, packetsize); - } - - if (cl_mode == CL_CONNECTED || dedicated) - { - // Send extra data if needed - if (localtextcmd[0]) - { - netbuffer->packettype = PT_TEXTCMD; - 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; - } - - // Send extra data if needed for player 2 (splitscreen) - if (localtextcmd2[0]) - { - netbuffer->packettype = PT_TEXTCMD2; - M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); - // All extra data have been sent - if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... - localtextcmd2[0] = 0; - } - } -} - -// send the server packet -// send tic from firstticstosend to maketic-1 -static void SV_SendTics(void) -{ - tic_t realfirsttic, lasttictosend, i; - UINT32 n; - INT32 j; - size_t packsize; - UINT8 *bufpos; - UINT8 *ntextcmd; - - // send to all client but not to me - // for each node create a packet with x tics and send it - // x is computed using supposedtics[n], max packet size and maketic - for (n = 1; n < MAXNETNODES; n++) - if (nodeingame[n]) - { - // assert supposedtics[n]>=nettics[n] - realfirsttic = supposedtics[n]; - lasttictosend = min(maketic, nettics[n] + CLIENTBACKUPTICS); - - if (realfirsttic >= lasttictosend) - { - // well we have sent all tics we will so use extrabandwidth - // to resent packet that are supposed lost (this is necessary since lost - // packet detection work when we have received packet with firsttic > neededtic - // (getpacket servertics case) - DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n", - n, maketic, supposedtics[n], nettics[n])); - realfirsttic = nettics[n]; - if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3) - // all tic are ok - continue; - DEBFILE(va("Sent %d anyway\n", realfirsttic)); - } - if (realfirsttic < firstticstosend) - realfirsttic = firstticstosend; - - // compute the length of the packet and cut it if too large - packsize = BASESERVERTICSSIZE; - for (i = realfirsttic; i < lasttictosend; i++) - { - packsize += sizeof (ticcmd_t) * doomcom->numslots; - packsize += TotalTextCmdPerTic(i); - - if (packsize > software_MAXPACKETLENGTH) - { - DEBFILE(va("packet too large (%s) at tic %d (should be from %d to %d)\n", - sizeu1(packsize), i, realfirsttic, lasttictosend)); - lasttictosend = i; - - // too bad: too much player have send extradata and there is too - // much data in one tic. - // To avoid it put the data on the next tic. (see getpacket - // textcmd case) but when numplayer changes the computation can be different - if (lasttictosend == realfirsttic) - { - if (packsize > MAXPACKETLENGTH) - I_Error("Too many players: can't send %s data for %d players to node %d\n" - "Well sorry nobody is perfect....\n", - sizeu1(packsize), doomcom->numslots, n); - else - { - lasttictosend++; // send it anyway! - DEBFILE("sending it anyway\n"); - } - } - break; - } - } - - // Send the tics - netbuffer->packettype = PT_SERVERTICS; - netbuffer->u.serverpak.starttic = realfirsttic; - netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic); - netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots); - bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds; - - for (i = realfirsttic; i < lasttictosend; i++) - { - bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); - } - - // add textcmds - for (i = realfirsttic; i < lasttictosend; i++) - { - ntextcmd = bufpos++; - *ntextcmd = 0; - for (j = 0; j < MAXPLAYERS; j++) - { - UINT8 *textcmd = D_GetExistingTextcmd(i, j); - INT32 size = textcmd ? textcmd[0] : 0; - - if ((!j || playeringame[j]) && size) - { - (*ntextcmd)++; - WRITEUINT8(bufpos, j); - M_Memcpy(bufpos, textcmd, size + 1); - bufpos += size + 1; + CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + noskincomplain = true; } } } - packsize = bufpos - (UINT8 *)&(netbuffer->u); + else // Get the properties! + { + // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. + if (!stricmp(stoken, "realname")) + { // Display name (eg. "Knuckles") + realname = true; + STRBUFCPY(skin->realname, value); + SYMBOLCONVERT(skin->realname) + if (!hudname) + HUDNAMEWRITE(skin->realname); + } + else if (!stricmp(stoken, "hudname")) + { // Life icon name (eg. "K.T.E") + hudname = true; + HUDNAMEWRITE(value); + SYMBOLCONVERT(skin->hudname) + if (!realname) + STRBUFCPY(skin->realname, skin->hudname); + } + else if (!R_ProcessPatchableFields(skin, stoken, value)) + CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); + } - HSendPacket(n, false, 0, packsize); - // when tic are too large, only one tic is sent so don't go backward! - if (lasttictosend-doomcom->extratics > realfirsttic) - supposedtics[n] = lasttictosend-doomcom->extratics; - else - supposedtics[n] = lasttictosend; - if (supposedtics[n] < nettics[n]) supposedtics[n] = nettics[n]; + if (!skin) + break; + +next_token: + stoken = strtok(NULL, "\r\n= "); } - // node 0 is me! - supposedtics[0] = maketic; -} + free(buf2); -// -// TryRunTics -// -static void Local_Maketic(INT32 realtics) -{ - I_OsPolling(); // I_Getevent - D_ProcessEvents(); // menu responder, cons responder, - // game responder calls HU_Responder, AM_Responder, - // and G_MapEventsToControls - if (!dedicated) rendergametic = gametic; - // translate inputs (keyboard/mouse/joystick) into game controls - G_BuildTiccmd(&localcmds, realtics, 1); - if (splitscreen || botingame) - G_BuildTiccmd(&localcmds2, realtics, 2); - - localcmds.angleturn |= TICCMD_RECEIVED; - localcmds2.angleturn |= TICCMD_RECEIVED; -} - -// create missed tic -static void SV_Maketic(void) -{ - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) + if (!skin) // Didn't include a name parameter? What a waste. + { + if (!noskincomplain) + CONS_Debug(DBG_SETUP, "R_PatchSkins: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename); continue; - - // We didn't receive this tic - if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0) - { - ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i]; - ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i]; - - if (players[i].quittime) - { - // Copy the angle/aiming from the previous tic - // and empty the other inputs - memset(ticcmd, 0, sizeof(netcmds[0][0])); - ticcmd->angleturn = prevticcmd->angleturn | TICCMD_RECEIVED; - ticcmd->aiming = prevticcmd->aiming; - } - else - { - DEBFILE(va("MISS tic%4d for player %d\n", maketic, i)); - // Copy the input from the previous tic - *ticcmd = *prevticcmd; - ticcmd->angleturn &= ~TICCMD_RECEIVED; - } - } - } - - // all tic are now proceed make the next - maketic++; -} - -void TryRunTics(tic_t realtics) -{ - // the machine has lagged but it is not so bad - if (realtics > TICRATE/7) // FIXME: consistency failure!! - { - if (server) - realtics = 1; - else - realtics = TICRATE/7; - } - - if (singletics) - realtics = 1; - - if (realtics >= 1) - { - COM_BufTicker(); - if (mapchangepending) - D_MapChange(-1, 0, ultimatemode, false, 2, false, fromlevelselect); // finish the map change - } - - NetUpdate(); - - if (demoplayback) - { - neededtic = gametic + (realtics * cv_playbackspeed.value); - // start a game after a demo - maketic += realtics; - firstticstosend = maketic; - tictoclear = firstticstosend; - } - - GetPackets(); - -#ifdef DEBUGFILE - if (debugfile && (realtics || neededtic > gametic)) - { - //SoM: 3/30/2000: Need long INT32 in the format string for args 4 & 5. - //Shut up stupid warning! - fprintf(debugfile, "------------ Tryruntic: REAL:%d NEED:%d GAME:%d LOAD: %d\n", - realtics, neededtic, gametic, debugload); - debugload = 100000; - } -#endif - - if (player_joining) - return; - - if (neededtic > gametic) - { - if (advancedemo) - { - if (timedemo_quit) - COM_ImmedExecute("quit"); - else - D_StartTitle(); - } - else - // run the count * tics - while (neededtic > gametic) - { - DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic)); - - ps_tictime = I_GetTimeMicros(); - - G_Ticker((gametic % NEWTICRATERATIO) == 0); - ExtraDataTicker(); - gametic++; - consistancy[gametic%BACKUPTICS] = Consistancy(); - - ps_tictime = I_GetTimeMicros() - ps_tictime; - - // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. - if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) - break; - } - } -} - -/* -Ping Update except better: -We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out. -If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave. -*/ - -static INT32 pingtimeout[MAXPLAYERS]; - -static inline void PingUpdate(void) -{ - INT32 i; - boolean laggers[MAXPLAYERS]; - UINT8 numlaggers = 0; - memset(laggers, 0, sizeof(boolean) * MAXPLAYERS); - - netbuffer->packettype = PT_PING; - - //check for ping limit breakage. - if (cv_maxping.value) - { - for (i = 1; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].quittime - && (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value)) - { - if (players[i].jointime > 30 * TICRATE) - laggers[i] = true; - numlaggers++; - } - else - pingtimeout[i] = 0; } - //kick lagging players... unless everyone but the server's ping sucks. - //in that case, it is probably the server's fault. - if (numlaggers < D_NumPlayers() - 1) - { - for (i = 1; i < MAXPLAYERS; i++) - { - if (playeringame[i] && laggers[i]) - { - pingtimeout[i]++; - // ok your net has been bad for too long, you deserve to die. - if (pingtimeout[i] > cv_pingtimeout.value) - { - pingtimeout[i] = 0; - SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY); - } - } - /* - you aren't lagging, - but you aren't free yet. - In case you'll keep spiking, - we just make the timer go back down. (Very unstable net must still get kicked). - */ - else - pingtimeout[i] = (pingtimeout[i] == 0 ? 0 : pingtimeout[i]-1); - } - } + // Patch sprites + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + //ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere + + R_FlushTranslationColormapCache(); + + if (!skin->availability) // Safe to print... + CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); } - - //make the ping packet and clear server data for next one - for (i = 0; i < MAXPLAYERS; i++) - { - netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; - //server takes a snapshot of the real ping for display. - //otherwise, pings fluctuate a lot and would be odd to look at. - playerpingtable[i] = realpingtable[i] / pingmeasurecount; - realpingtable[i] = 0; //Reset each as we go. - } - - // send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked. - netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value; - - //send out our ping packets - for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i]) - HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); - - pingmeasurecount = 1; //Reset count + return; } -void NetUpdate(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) - { - if (netgame && !(gametime % 35)) // update once per second. - PingUpdate(); - // update node latency values so we can take an average later. - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && playernode[i] != UINT8_MAX) - realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i])); - pingmeasurecount++; - } - - if (client) - maketic = neededtic; - - Local_Maketic(realtics); // make local tic, and call menu? - - if (server) - CL_SendClientCmd(); // send it - - GetPackets(); // get packet from client or from server - - // client send the command after a receive of the server - // the server send before because in single player is beter - -#ifdef MASTERSERVER - MasterClient_Ticker(); // Acking the Master Server -#endif - - if (client) - { - // If the client just finished redownloading the game state, load it - if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND) - CL_ReloadReceivedSavegame(); - - CL_SendClientCmd(); // Send tic cmd - hu_redownloadinggamestate = cl_redownloadinggamestate; - } - else - { - if (!demoplayback) - { - 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; - - if (maketic + counts >= firstticstosend + BACKUPTICS) - counts = firstticstosend+BACKUPTICS-maketic-1; - - for (i = 0; i < counts; i++) - SV_Maketic(); // Create missed tics and increment maketic - - for (; tictoclear < firstticstosend; tictoclear++) // Clear only when acknowledged - D_Clearticcmd(tictoclear); // Clear the maketic the new tic - - SV_SendTics(); - - neededtic = maketic; // The server is a client too - } - } - - 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); - } - - nowtime /= NEWTICRATERATIO; - if (nowtime > resptime) - { - resptime = nowtime; -#ifdef HAVE_THREADS - I_lock_mutex(&m_menu_mutex); -#endif - M_Ticker(); -#ifdef HAVE_THREADS - I_unlock_mutex(m_menu_mutex); -#endif - CON_Ticker(); - } - - FileSendTicker(); -} - -/** Returns the number of players playing. - * \return Number of players. Can be zero if we're running a ::dedicated - * server. - * \author Graue - */ -INT32 D_NumPlayers(void) -{ - INT32 num = 0, ix; - for (ix = 0; ix < MAXPLAYERS; ix++) - if (playeringame[ix]) - num++; - return num; -} - -tic_t GetLag(INT32 node) -{ - return gametic - nettics[node]; -} - -void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest) -{ -#ifdef NOMD5 - (void)buffer; - (void)len; - (void)salt; - memset(dest, 0, 16); -#else - char tmpbuf[256]; - const size_t sl = strlen(salt); - - if (len > 256-sl) - len = 256-sl; - - memcpy(tmpbuf, buffer, len); - memmove(&tmpbuf[len], salt, sl); - //strcpy(&tmpbuf[len], salt); - len += strlen(salt); - if (len < 256) - memset(&tmpbuf[len],0,256-len); - - // Yes, we intentionally md5 the ENTIRE buffer regardless of size... - md5_buffer(tmpbuf, 256, dest); -#endif -} +#undef HUDNAMEWRITE +#undef SYMBOLCONVERT From 079fe9ba7e488e880561318e1200e8630289d117 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:08:16 -0500 Subject: [PATCH 033/241] Command_Kick() - Allow removal of non-consoleplayer/secondaryviewplayer player instances (e.g. player bots) --- src/d_clisrv.c | 66 ++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4fdc7e7ee..88b4d9387 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1595,7 +1595,9 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i < MAXPLAYERS; i++) { +#ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[i]); +#endif sprintf(player_names[i], "Player %d", i + 1); } @@ -2258,15 +2260,11 @@ void D_SaveBan(void) size_t i; banreason_t *reasonlist = reasonhead; const char *address, *mask; - const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt"); if (!reasonhead) - { - remove(path); return; - } - f = fopen(path, "w"); + f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "w"); if (!f) { @@ -2310,14 +2308,16 @@ static void Ban_Add(const char *reason) reasontail = reasonlist; } -static void Ban_Clear(void) +static void Command_ClearBans(void) { banreason_t *temp; + if (!I_ClearBans) + return; + I_ClearBans(); - + D_SaveBan(); reasontail = NULL; - while (reasonhead) { temp = reasonhead->next; @@ -2327,15 +2327,6 @@ static void Ban_Clear(void) } } -static void Command_ClearBans(void) -{ - if (!I_ClearBans) - return; - - Ban_Clear(); - D_SaveBan(); -} - static void Ban_Load_File(boolean warning) { FILE *f; @@ -2343,9 +2334,6 @@ static void Ban_Load_File(boolean warning) const char *address, *mask; char buffer[MAX_WADPATH]; - if (!I_ClearBans) - return; - f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); if (!f) @@ -2355,7 +2343,13 @@ static void Ban_Load_File(boolean warning) return; } - Ban_Clear(); + if (I_ClearBans) + Command_ClearBans(); + else + { + fclose(f); + return; + } for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++) { @@ -2815,11 +2809,11 @@ static void Command_Kick(void) return; } - if (!netgame) // Don't kick Tails in splitscreen! - { - CONS_Printf(M_GetText("This only works in a netgame.\n")); - return; - } + //if (!netgame) // Don't kick Tails in splitscreen! + //{ + // CONS_Printf(M_GetText("This only works in a netgame.\n")); + // return; + //} if (server || IsPlayerAdmin(consoleplayer)) { @@ -2827,9 +2821,14 @@ static void Command_Kick(void) UINT8 *p = buf; const SINT8 pn = nametonum(COM_Argv(1)); + if (splitscreen && (pn == 0 || pn == 1)) + { + CONS_Printf(M_GetText("Splitscreen players cannot be kicked.\n")); + return; + } if (pn == -1 || pn == 0) return; - + // Special case if we are trying to kick a player who is downloading the game state: // trigger a timeout instead of kicking them, because a kick would only // take effect after they have finished downloading @@ -3032,7 +3031,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (pnum == consoleplayer) { - LUAh_GameQuit(false); + if (Playing()) + LUAh_GameQuit(); #ifdef DUMPCONSISTENCY if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); #endif @@ -3732,7 +3732,8 @@ static void HandleConnect(SINT8 node) static void HandleShutdown(SINT8 node) { (void)node; - LUAh_GameQuit(false); + if (Playing()) + LUAh_GameQuit(); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -3747,7 +3748,8 @@ static void HandleShutdown(SINT8 node) static void HandleTimeout(SINT8 node) { (void)node; - LUAh_GameQuit(false); + if (Playing()) + LUAh_GameQuit(); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -4850,14 +4852,14 @@ void TryRunTics(tic_t realtics) { DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic)); - ps_tictime = I_GetPreciseTime(); + ps_tictime = I_GetTimeMicros(); G_Ticker((gametic % NEWTICRATERATIO) == 0); ExtraDataTicker(); gametic++; consistancy[gametic%BACKUPTICS] = Consistancy(); - ps_tictime = I_GetPreciseTime() - ps_tictime; + ps_tictime = I_GetTimeMicros() - ps_tictime; // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) From a68fee3303b0804cd35c186c4d89b858b790c385 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:22:38 -0500 Subject: [PATCH 034/241] oops --- src/p_inter.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 778ec703b..8190f5cfa 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1387,6 +1387,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->bot && player->bot != 3) return; + + // Initialize my junk + junk.tags.tags = NULL; + junk.tags.count = 0; Tag_FSet(&junk.tags, LE_AXE); EV_DoElevator(&junk, bridgeFall, false); From 56e9b99f283923855efc6cf621d988700c305634 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 22:28:01 +0000 Subject: [PATCH 035/241] Revert "Add conditions for new player bot type" This reverts commit 4b9a95a53837166a080b200b34982ce867a31ffd --- src/p_enemy.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 38df59855..203e04af1 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -743,7 +743,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if (player->mo->health <= 0) continue; // dead - if (player->bot && player->bot != 3) + if (player->bot) continue; // ignore bots if (player->quittime) @@ -1834,7 +1834,7 @@ void A_SnailerThink(mobj_t *actor) fixed_t dist; fixed_t dx, dy; - dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); + dist = R_PointToDist2(0, 0, actor->x - actor->target->x, actor->y - actor->target->y); if (an > ANGLE_45 && an <= ANGLE_90) // fire at 45 degrees to the left { @@ -3924,6 +3924,10 @@ void A_BossDeath(mobj_t *mo) } else { + // Initialize my junk + junk.tags.tags = NULL; + junk.tags.count = 0; + // Bring the egg trap up to the surface // Incredibly shitty code ahead Tag_FSet(&junk.tags, LE_CAPSULE0); @@ -4053,6 +4057,10 @@ bossjustdie: } case MT_KOOPA: { + // Initialize my junk + junk.tags.tags = NULL; + junk.tags.count = 0; + Tag_FSet(&junk.tags, LE_KOOPA); EV_DoCeiling(&junk, raiseToHighest); return; From 161e1c42cb6bed9ca7af062df4f7fd091f0299b7 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:29:15 -0500 Subject: [PATCH 036/241] Update p_enemy.c --- 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 203e04af1..637eba83f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -743,7 +743,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if (player->mo->health <= 0) continue; // dead - if (player->bot) + if (player->bot && player->bot != 3) continue; // ignore bots if (player->quittime) From 759ff44dfd366bfd42ae252d90f78a1e85b947c2 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 22:32:02 +0000 Subject: [PATCH 037/241] Revert "Add conditions for new player bot type" This reverts commit b995e3cb75b67116d51583c1ae85debf25013621 --- src/p_user.c | 125 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 48 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 2466310bb..a70dceb8b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1189,7 +1189,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) if (!player) return; - if (player->bot && player->bot != 3) + if (player->bot) player = &players[consoleplayer]; if (!player->mo) @@ -1234,7 +1234,7 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres) if (!player) return; - if (player->bot && player->bot != 3) + if (player->bot) player = &players[consoleplayer]; if (!player->mo) @@ -1261,7 +1261,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) if (!player) return; - if (player->bot && player->bot != 3) + if (player->bot) player = &players[consoleplayer]; if (gamestate == GS_LEVEL) @@ -1341,7 +1341,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) // Transformation animation P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1); - if (giverings) + if (giverings && player->rings < 50) player->rings = 50; // Just in case. @@ -1367,7 +1367,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) { UINT32 oldscore; - if (player->bot && player->bot != 3) + if (player->bot) player = &players[consoleplayer]; // NiGHTS does it different! @@ -1491,10 +1491,10 @@ void P_PlayLivesJingle(player_t *player) if (player && !P_IsLocalPlayer(player)) return; - if (use1upSound || cv_1upsound.value) - S_StartSound(NULL, sfx_oneup); - else if (mariomode) + if (mariomode) S_StartSound(NULL, sfx_marioa); + else if (use1upSound || cv_1upsound.value) + S_StartSound(NULL, sfx_oneup); else { P_PlayJingle(player, JT_1UP); @@ -2329,7 +2329,8 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) P_MobjCheckWater(player->mo); if (player->pflags & PF_SPINNING) { - if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) + if (!(player->pflags & PF_STARTDASH) && player->panim != PA_ROLL && player->panim != PA_ETC + && player->panim != PA_ABILITY && player->panim != PA_ABILITY2) { P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_spin); @@ -2612,10 +2613,10 @@ static void P_CheckBustableBlocks(player_t *player) if ((netgame || multiplayer) && player->spectator) return; - + oldx = player->mo->x; oldy = player->mo->y; - + if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways { P_UnsetThingPosition(player->mo); @@ -2634,7 +2635,7 @@ static void P_CheckBustableBlocks(player_t *player) if (!node->m_sector->ffloors) continue; - + for (rover = node->m_sector->ffloors; rover; rover = rover->next) { if (!P_PlayerCanBust(player, rover)) @@ -2992,7 +2993,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) player->powers[pw_spacetime] = 0; // Underwater audio cues - if (P_IsLocalPlayer(player) && !player->bot && player->bot != 3) + if (P_IsLocalPlayer(player) && !player->bot) { if ((player->powers[pw_underwater] == 25*TICRATE + 1) || (player->powers[pw_underwater] == 20*TICRATE + 1) @@ -4525,6 +4526,9 @@ void P_DoJump(player_t *player, boolean soundandstate) player->pflags |= P_GetJumpFlags(player);; + if (player->charflags & SF_NOJUMPDAMAGE) + player->pflags &= ~PF_SPINNING; + if (soundandstate) { if (!player->spectator) @@ -5020,7 +5024,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN) && ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && !(player->charflags & SF_NOSHIELDABILITY)) { if ((lockonshield = P_LookForEnemies(player, false, false))) { @@ -5043,7 +5047,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player)) // Spin button effects + if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player))) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5491,7 +5495,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; } } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super]) + else if ((!(player->charflags & SF_NOSHIELDABILITY)) && ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super] && !LUAh_ShieldSpecial(player))) P_DoJumpShield(player); } @@ -5920,7 +5924,7 @@ static void P_3dMovement(player_t *player) player->rmomy = player->mo->momy - player->cmomy; // Calculates player's speed based on distance-of-a-line formula - player->speed = P_AproxDistance(player->rmomx, player->rmomy); + player->speed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); // Monster Iestyn - 04-11-13 // Quadrants are stupid, excessive and broken, let's do this a much simpler way! @@ -5953,6 +5957,22 @@ static void P_3dMovement(player_t *player) acceleration = 96 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * 40; topspeed = normalspd; } + else if (player->bot) + { // Bot steals player 1's stats + normalspd = FixedMul(players[consoleplayer].normalspeed, player->mo->scale); + thrustfactor = players[consoleplayer].thrustfactor; + acceleration = players[consoleplayer].accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * players[consoleplayer].acceleration; + + if (player->powers[pw_tailsfly]) + topspeed = normalspd/2; + else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER)) + { + topspeed = normalspd/2; + acceleration = 2*acceleration/3; + } + else + topspeed = normalspd; + } else { if (player->powers[pw_super] || player->powers[pw_sneakers]) @@ -7736,6 +7756,11 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale)); P_SetObjectMomZ(flame, 3*FRACUNIT, false); + if (!(gametyperules & GTR_FRIENDLY)) + { + P_SetMobjState(flame, S_TEAM_SPINFIRE1); + flame->color = player->mo->color; + } } #undef limitangle #undef numangles @@ -7763,6 +7788,11 @@ void P_ElementalFire(player_t *player, boolean cropcircle) flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + if (!(gametyperules & GTR_FRIENDLY)) + { + P_SetMobjState(flame, S_TEAM_SPINFIRE1); + flame->color = player->mo->color; + } flame->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others P_XYMovement(flame); @@ -8589,12 +8619,6 @@ void P_MovePlayer(player_t *player) player->climbing--; } - if (!player->climbing) - { - player->lastsidehit = -1; - player->lastlinehit = -1; - } - // Make sure you're not teetering when you shouldn't be. if (player->panim == PA_EDGE && (player->mo->momx || player->mo->momy || player->mo->momz)) @@ -8619,6 +8643,7 @@ void P_MovePlayer(player_t *player) P_DoFiring(player, cmd); { + boolean atspinheight = false; fixed_t oldheight = player->mo->height; // Less height while spinning. Good for spinning under things...? @@ -8628,32 +8653,35 @@ void P_MovePlayer(player_t *player) || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) + { player->mo->height = P_GetPlayerSpinHeight(player); + atspinheight = true; + } else player->mo->height = P_GetPlayerHeight(player); if (player->mo->eflags & MFE_VERTICALFLIP && player->mo->height != oldheight) // adjust z height for reverse gravity, similar to how it's done for scaling player->mo->z -= player->mo->height - oldheight; - } - // Crush test... - if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) - && !(player->mo->flags & MF_NOCLIP)) - { - if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SPINNING)) + // Crush test... + if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) + && !(player->mo->flags & MF_NOCLIP)) { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - } - else if (player->mo->ceilingz - player->mo->floorz < player->mo->height) - { - if ((netgame || multiplayer) && player->spectator) - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators - else - P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED); + if (!atspinheight) + { + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + } + else if (player->mo->ceilingz - player->mo->floorz < player->mo->height) + { + if ((netgame || multiplayer) && player->spectator) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators + else + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED); - if (player->playerstate == PST_DEAD) - return; + if (player->playerstate == PST_DEAD) + return; + } } } @@ -9469,11 +9497,11 @@ static void P_DeathThink(player_t *player) if (player->deadtimer < INT32_MAX) player->deadtimer++; - if (player->bot && player->bot != 3) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already + if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already goto notrealplayer; // continue logic - if (!(netgame || multiplayer) && player->lives <= 0 && player ==&players[consoleplayer]) //Extra players in SP can't be allowed to continue or end game + if (!(netgame || multiplayer) && player->lives <= 0) { if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_SPIN || cmd->buttons & BT_JUMP) && (!continuesInSession || player->continues > 0)) G_UseContinue(); @@ -11452,7 +11480,7 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } - if (player->bot && player->bot != 3) + if (player->bot) { if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD) { @@ -11466,7 +11494,6 @@ void P_PlayerThink(player_t *player) } } -#ifdef SEENAMES if (netgame && player == &players[displayplayer] && !(leveltime % (TICRATE/5))) { seenplayer = NULL; @@ -11491,7 +11518,6 @@ void P_PlayerThink(player_t *player) } } } -#endif if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj)) { @@ -12562,13 +12588,16 @@ void P_PlayerAfterThink(player_t *player) player->powers[pw_carry] = CR_NONE; else { - P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); + if (tails->player) + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); + else + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true); player->mo->momx = tails->momx; player->mo->momy = tails->momy; player->mo->momz = tails->momz; } - if (G_CoopGametype() && (!tails->player || tails->player->bot != 1)) + if (G_CoopGametype() && tails->player && tails->player->bot != 1) { player->mo->angle = tails->angle; @@ -12583,7 +12612,7 @@ void P_PlayerAfterThink(player_t *player) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); - if ((tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) + if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) tails->player->powers[pw_tailsfly] = 0; } else From 6103d7a51e2e7905d5298f5fde80be3554d1751f Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:41:16 -0500 Subject: [PATCH 038/241] Update p_user.c --- src/p_user.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index a70dceb8b..9e86e2d73 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -777,7 +777,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) UINT8 oldmare, oldmarelap, oldmarebonuslap; // Bots can't be NiGHTSerized, silly!1 :P - if (player->bot) + if (player->bot && player->bot != 3) return; if (player->powers[pw_carry] != CR_NIGHTSMODE) @@ -1189,7 +1189,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) if (!player) return; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; if (!player->mo) @@ -1234,7 +1234,7 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres) if (!player) return; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; if (!player->mo) @@ -1261,7 +1261,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) if (!player) return; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; if (gamestate == GS_LEVEL) @@ -1367,7 +1367,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) { UINT32 oldscore; - if (player->bot) + if (player->bot && player->bot != 3) player = &players[consoleplayer]; // NiGHTS does it different! @@ -5957,7 +5957,7 @@ static void P_3dMovement(player_t *player) acceleration = 96 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * 40; topspeed = normalspd; } - else if (player->bot) + else if (player->bot && player->bot != 3) { // Bot steals player 1's stats normalspd = FixedMul(players[consoleplayer].normalspeed, player->mo->scale); thrustfactor = players[consoleplayer].thrustfactor; @@ -9497,11 +9497,11 @@ static void P_DeathThink(player_t *player) if (player->deadtimer < INT32_MAX) player->deadtimer++; - if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already + if (player->bot && player->bot != 3) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already goto notrealplayer; // continue logic - if (!(netgame || multiplayer) && player->lives <= 0) + if (!(netgame || multiplayer) && player->lives <= 0 && player == &players[consoleplayer]) //Extra players in SP can't be allowed to continue or end game { if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_SPIN || cmd->buttons & BT_JUMP) && (!continuesInSession || player->continues > 0)) G_UseContinue(); @@ -11480,7 +11480,7 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } - if (player->bot) + if (player->bot && player->bot != 3) { if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD) { From 00462323c3fe6dda7ece834cfa92431525f54e85 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 22:42:35 +0000 Subject: [PATCH 039/241] Revert "Implementation of lua function P_AddPlayer()" This reverts commit 5e8313e157ab0bef4f2e2a346906aa1a6efdd58b --- src/lua_baselib.c | 89 +++++------------------------------------------ 1 file changed, 8 insertions(+), 81 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9bc8813a2..c5f847be6 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -155,6 +155,8 @@ static const struct { {META_PIVOTLIST, "spriteframepivot_t[]"}, {META_FRAMEPIVOT, "spriteframepivot_t"}, + {META_TAGLIST, "taglist"}, + {META_MOBJ, "mobj_t"}, {META_MAPTHING, "mapthing_t"}, @@ -163,6 +165,8 @@ static const struct { {META_SKIN, "skin_t"}, {META_POWERS, "player_t.powers"}, {META_SOUNDSID, "skin_t.soundsid"}, + {META_SKINSPRITES, "skin_t.sprites"}, + {META_SKINSPRITESLIST, "skin_t.sprites[]"}, {META_VERTEX, "vertex_t"}, {META_LINE, "line_t"}, @@ -184,6 +188,9 @@ static const struct { {META_CVAR, "consvar_t"}, {META_SECTORLINES, "sector_t.lines"}, +#ifdef MUTABLE_TAGS + {META_SECTORTAGLIST, "sector_t.taglist"}, +#endif {META_SIDENUM, "line_t.sidenum"}, {META_LINEARGS, "line_t.args"}, {META_LINESTRINGARGS, "line_t.stringargs"}, @@ -2632,7 +2639,7 @@ static int lib_rSkinUsable(lua_State *L) else // skin name { const char *skinname = luaL_checkstring(L, 2); - if (R_SkinAvailable(skinname) >= 0) + i = R_SkinAvailable(skinname); if (i == -1) return luaL_error(L, "skin %s (argument 2) is not loaded", skinname); } @@ -3400,85 +3407,6 @@ static int lib_gAddGametype(lua_State *L) return 0; } -// Bot adding function! -// Partly lifted from Got_AddPlayer -static int lib_gAddPlayer(lua_State *L) -{ - INT16 i, newplayernum, botcount = 1; - player_t *newplayer; - INT8 skinnum = 0, bot; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - break; - - if (players[i].bot) - botcount++; // How many of us are there already? - } - if (i >= MAXPLAYERS) - { - lua_pushnil(L); - return 1; - } - - - newplayernum = i; - - //if (!splitscreen && !botingame) - CL_ClearPlayer(newplayernum); - - playeringame[newplayernum] = true; - G_AddPlayer(newplayernum); - newplayer = &players[newplayernum]; - - newplayer->jointime = 0; - newplayer->quittime = 0; - - // I hereby name you Bot X - strcpy(player_names[newplayernum], va("Bot %d", botcount)); - - // Read the skin string! - if (!lua_isnoneornil(L, 1)) - { - skinnum = R_SkinAvailable(luaL_checkstring(L, 1)); - skinnum = skinnum < 0 ? 0 : skinnum; - - // Bots can be whatever they want - if (!R_SkinUsable(newplayernum, skinnum)) - newplayer->availabilities |= 1 << skinnum; - } - - // Read the color! - if (!lua_isnoneornil(L, 2)) - newplayer->skincolor = R_GetColorByName(luaL_checkstring(L, 2)); - else - newplayer->skincolor = skins[newplayer->skin].prefcolor; - - // Read the bot name, if given! - if (!lua_isnoneornil(L, 3)) - strcpy(player_names[newplayernum], luaL_checkstring(L, 3)); - - bot = luaL_optinteger(L, 4, 3); - newplayer->bot = (bot >= 0 && bot <= 3) ? bot : 3; - - // Set the skin - SetPlayerSkinByNum(newplayernum, skinnum); - - - if (netgame) - { - char joinmsg[256]; - - 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); - } - - LUA_PushUserdata(L, newplayer, META_PLAYER); - return 0; -} - static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) { if (ISINLEVEL) @@ -4059,7 +3987,6 @@ static luaL_Reg lib[] = { // g_game {"G_AddGametype", lib_gAddGametype}, - {"G_AddPlayer", lib_gAddPlayer}, {"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_FindMap",lib_gFindMap}, From 4e029dbc67a51529d88c2e16c696da97b5f73703 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:45:41 -0500 Subject: [PATCH 040/241] Update lua_baselib.c --- src/lua_baselib.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index c5f847be6..438c20b81 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3407,6 +3407,82 @@ static int lib_gAddGametype(lua_State *L) return 0; } +// Bot adding function! +// Partly lifted from Got_AddPlayer +static int lib_gAddPlayer(lua_State *L) +{ + INT16 i, newplayernum, botcount = 1; + player_t *newplayer; + INT8 skinnum = 0, bot; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + break; + + if (players[i].bot) + botcount++; // How many of us are there already? + } + if (i >= MAXPLAYERS) + { + lua_pushnil(L); + return 1; + } + + + newplayernum = i; + + //if (!splitscreen && !botingame) + CL_ClearPlayer(newplayernum); + + playeringame[newplayernum] = true; + G_AddPlayer(newplayernum); + newplayer = &players[newplayernum]; + + newplayer->jointime = 0; + newplayer->quittime = 0; + + // I hereby name you Bot X + strcpy(player_names[newplayernum], va("Bot %d", botcount)); + + // Read the skin string! + if (!lua_isnoneornil(L, 1)) + { + skinnum = R_SkinAvailable(luaL_checkstring(L, 1)); + skinnum = skinnum < 0 ? 0 : skinnum; + } + + // Read the color! + if (!lua_isnoneornil(L, 2)) + newplayer->skincolor = R_GetColorByName(luaL_checkstring(L, 2)); + else + newplayer->skincolor = skins[newplayer->skin].prefcolor; + + // Read the bot name, if given! + if (!lua_isnoneornil(L, 3)) + strcpy(player_names[newplayernum], luaL_checkstring(L, 3)); + + bot = luaL_optinteger(L, 4, 3); + newplayer->bot = (bot >= 0 && bot <= 3) ? bot : 3; + + // Set the skin (needed to set bot first!) + SetPlayerSkinByNum(newplayernum, skinnum); + + + if (netgame) + { + char joinmsg[256]; + + 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); + } + + LUA_PushUserdata(L, newplayer, META_PLAYER); + return 0; +} + + static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) { if (ISINLEVEL) @@ -3987,6 +4063,7 @@ static luaL_Reg lib[] = { // g_game {"G_AddGametype", lib_gAddGametype}, + {"G_AddPlayer", lib_gAddPlayer}, {"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_FindMap",lib_gFindMap}, From 8fa8ca622249af77e1aad9ffe6e2800f92448380 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:47:26 -0500 Subject: [PATCH 041/241] Update r_skins.c --- src/r_skins.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/r_skins.c b/src/r_skins.c index 155a64700..a29209873 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -512,6 +512,10 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) GETFLAG(MULTIABILITY) GETFLAG(NONIGHTSROTATION) GETFLAG(NONIGHTSSUPER) + GETFLAG(NOSUPERSPRITES) + GETFLAG(NOSUPERJUMPBOOST) + GETFLAG(CANBUSTWALLS) + GETFLAG(NOSHIELDABILITY) #undef GETFLAG else // let's check if it's a sound, otherwise error out From 93562b782e9e001d82fa6d8c94860ea3170a2bc9 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 22:50:20 +0000 Subject: [PATCH 042/241] =?UTF-8?q?Revert=20"Command=5FKick()=20-=20Allow?= =?UTF-8?q?=20removal=20of=20non-consoleplayer/secondaryviewplayer=20playe?= =?UTF-8?q?r=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 079fe9ba7e488e880561318e1200e8630289d117 --- src/d_clisrv.c | 66 ++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 88b4d9387..4fdc7e7ee 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1595,9 +1595,7 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i < MAXPLAYERS; i++) { -#ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[i]); -#endif sprintf(player_names[i], "Player %d", i + 1); } @@ -2260,11 +2258,15 @@ void D_SaveBan(void) size_t i; banreason_t *reasonlist = reasonhead; const char *address, *mask; + const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt"); if (!reasonhead) + { + remove(path); return; + } - f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "w"); + f = fopen(path, "w"); if (!f) { @@ -2308,16 +2310,14 @@ static void Ban_Add(const char *reason) reasontail = reasonlist; } -static void Command_ClearBans(void) +static void Ban_Clear(void) { banreason_t *temp; - if (!I_ClearBans) - return; - I_ClearBans(); - D_SaveBan(); + reasontail = NULL; + while (reasonhead) { temp = reasonhead->next; @@ -2327,6 +2327,15 @@ static void Command_ClearBans(void) } } +static void Command_ClearBans(void) +{ + if (!I_ClearBans) + return; + + Ban_Clear(); + D_SaveBan(); +} + static void Ban_Load_File(boolean warning) { FILE *f; @@ -2334,6 +2343,9 @@ static void Ban_Load_File(boolean warning) const char *address, *mask; char buffer[MAX_WADPATH]; + if (!I_ClearBans) + return; + f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); if (!f) @@ -2343,13 +2355,7 @@ static void Ban_Load_File(boolean warning) return; } - if (I_ClearBans) - Command_ClearBans(); - else - { - fclose(f); - return; - } + Ban_Clear(); for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++) { @@ -2809,11 +2815,11 @@ static void Command_Kick(void) return; } - //if (!netgame) // Don't kick Tails in splitscreen! - //{ - // CONS_Printf(M_GetText("This only works in a netgame.\n")); - // return; - //} + if (!netgame) // Don't kick Tails in splitscreen! + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } if (server || IsPlayerAdmin(consoleplayer)) { @@ -2821,14 +2827,9 @@ static void Command_Kick(void) UINT8 *p = buf; const SINT8 pn = nametonum(COM_Argv(1)); - if (splitscreen && (pn == 0 || pn == 1)) - { - CONS_Printf(M_GetText("Splitscreen players cannot be kicked.\n")); - return; - } if (pn == -1 || pn == 0) return; - + // Special case if we are trying to kick a player who is downloading the game state: // trigger a timeout instead of kicking them, because a kick would only // take effect after they have finished downloading @@ -3031,8 +3032,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) if (pnum == consoleplayer) { - if (Playing()) - LUAh_GameQuit(); + LUAh_GameQuit(false); #ifdef DUMPCONSISTENCY if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); #endif @@ -3732,8 +3732,7 @@ static void HandleConnect(SINT8 node) static void HandleShutdown(SINT8 node) { (void)node; - if (Playing()) - LUAh_GameQuit(); + LUAh_GameQuit(false); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -3748,8 +3747,7 @@ static void HandleShutdown(SINT8 node) static void HandleTimeout(SINT8 node) { (void)node; - if (Playing()) - LUAh_GameQuit(); + LUAh_GameQuit(false); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -4852,14 +4850,14 @@ void TryRunTics(tic_t realtics) { DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic)); - ps_tictime = I_GetTimeMicros(); + ps_tictime = I_GetPreciseTime(); G_Ticker((gametic % NEWTICRATERATIO) == 0); ExtraDataTicker(); gametic++; consistancy[gametic%BACKUPTICS] = Consistancy(); - ps_tictime = I_GetTimeMicros() - ps_tictime; + ps_tictime = I_GetPreciseTime() - ps_tictime; // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) From 9bbebcbe9e4d6ed144bed21c0cf0b37d6918f20c Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 17:55:14 -0500 Subject: [PATCH 043/241] Update d_clisrv.c --- src/d_clisrv.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4fdc7e7ee..4574e5a1c 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2815,18 +2815,22 @@ static void Command_Kick(void) return; } - if (!netgame) // Don't kick Tails in splitscreen! - { - CONS_Printf(M_GetText("This only works in a netgame.\n")); - return; - } - if (server || IsPlayerAdmin(consoleplayer)) { UINT8 buf[3 + MAX_REASONLENGTH]; UINT8 *p = buf; const SINT8 pn = nametonum(COM_Argv(1)); + // Unlike bans, kicks are used especially to remove bot players, so we'll + // need to run a more specific check which allows kicking offline, but + // not against splitscreen players. + if (splitscreen && (pn == 0 || pn == 1)) + { + CONS_Printf(M_GetText("Splitscreen players cannot be kicked.\n")); + return; + } + + if (pn == -1 || pn == 0) return; From 225e7c72ace052a5945454b46ba14ab623209396 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 18:00:00 -0500 Subject: [PATCH 044/241] Update p_mobj.c --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 58124fb9b..f27ab2914 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1840,7 +1840,7 @@ void P_XYMovement(mobj_t *mo) moved = false; if (player) { - if (player->bot) + if (player->bot and player->bot != 3) B_MoveBlocked(player); } @@ -4135,7 +4135,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) player = &players[actor->lastlook]; - if (player->pflags & PF_INVIS || player->bot || player->spectator) + if (player->pflags & PF_INVIS || (player->bot && player->bot != 3) || player->spectator) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) From 505ba1ff631c91d3f91a65bd728817fe19ea6d76 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 18:06:36 -0500 Subject: [PATCH 045/241] Update g_game.c --- src/g_game.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index f1cae8cf5..43906e558 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2974,7 +2974,8 @@ void G_DoReborn(INT32 playernum) // Make sure objectplace is OFF when you first start the level! OP_ResetObjectplace(); - if (player->bot && playernum != consoleplayer) + // Tailsbot + if (player->bot && player->bot != 3 && playernum != consoleplayer) { // Bots respawn next to their master. mobj_t *oldmo = NULL; @@ -2992,6 +2993,28 @@ void G_DoReborn(INT32 playernum) return; } + + // Additional players (e.g. independent bots) in Single Player + if (playernum != consoleplayer && !(netgame || multiplayer)) + { + mobj_t *oldmo = NULL; + // Do nothing if out of lives + if (player->lives <= 0) + return; + + // Otherwise do respawn, starting by removing the player object + if (player->mo) + { + oldmo = player->mo; + P_RemoveMobj(player->mo); + } + // Do spawning + G_SpawnPlayer(playernum); + if (oldmo) + G_ChangePlayerReferences(oldmo, players[playernum].mo); + + return; //Exit function to avoid proccing other SP related mechanics + } if (countdowntimeup || (!(netgame || multiplayer) && (gametyperules & GTR_CAMPAIGN))) resetlevel = true; From 1583bf126b3105f98d647634a4256d22bc1e7e4d Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 18:31:09 -0500 Subject: [PATCH 046/241] lua habits --- 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 f27ab2914..a660a8a92 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1840,7 +1840,7 @@ void P_XYMovement(mobj_t *mo) moved = false; if (player) { - if (player->bot and player->bot != 3) + if (player->bot && player->bot != 3) B_MoveBlocked(player); } From 0e9b4acb587491b6f5d0b9c9c898a1c37811de85 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 19:29:03 -0500 Subject: [PATCH 047/241] Update g_game.c (Account for bot type 3) --- src/g_game.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 43906e558..5e2b4e708 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2627,8 +2627,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->totalring = totalring; p->mare = mare; - if (bot) + if (bot == 2) p->bot = 1; // reset to AI-controlled + else + p->bot = bot; p->pity = pity; p->rings = rings; p->spheres = spheres; From b73a15a0bfe628e8c1001dc97aef7d2720940ff5 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 22:50:15 -0500 Subject: [PATCH 048/241] fixed G_AddPlayer not sending return value --- src/lua_baselib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 438c20b81..f54662278 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3479,7 +3479,7 @@ static int lib_gAddPlayer(lua_State *L) } LUA_PushUserdata(L, newplayer, META_PLAYER); - return 0; + return 1; } From e19b0856846bbdcc860c735b9da95082965f604b Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Fri, 15 Jan 2021 22:56:48 -0500 Subject: [PATCH 049/241] Netcode failsafe. At least until I can figure out the best way to produce bot cmds outside of player sends. --- src/b_bot.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/b_bot.c b/src/b_bot.c index d3635f32c..35b14bd78 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -362,6 +362,12 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) // Bot AI isn't programmed in analog. CV_SetValue(&cv_analog[1], false); + // Bot cmd functions and hooks are not currently netplay compatible + // Necessary failsafe, as a bot in the P2 position in a netgame can inherit + // the last input from a hook triggered in splitscreen or SP. + if (netgame) + return; + // Let Lua scripts build ticcmds if (LUAh_BotTiccmd(player, cmd)) return; From ce8e389a2d9cec8c36f43a9573f0d9a29bf50d18 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 09:49:57 -0500 Subject: [PATCH 050/241] Add lua player.botleader and player.buttons_last (read+write) --- src/lua_playerlib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0eb54808f..a8dc64a15 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -370,6 +370,10 @@ static int player_get(lua_State *L) lua_pushboolean(L, plr->outofcoop); else if (fastcmp(field,"bot")) lua_pushinteger(L, plr->bot); + else if (fastcmp(field,"botleader")) + LUA_PushUserdata(L, plr->botleader, META_PLAYER); + else if (fastcmp(field,"buttons_last")) + lua_pushinteger(L, plr->buttons_last); else if (fastcmp(field,"jointime")) lua_pushinteger(L, plr->jointime); else if (fastcmp(field,"quittime")) From c391d76c11331dec29f3eedddb9bcc9344eb82e7 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:06:47 -0500 Subject: [PATCH 051/241] buttons_last -> lastbuttons --- src/lua_playerlib.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index a8dc64a15..51eb4ac0c 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -372,8 +372,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->bot); else if (fastcmp(field,"botleader")) LUA_PushUserdata(L, plr->botleader, META_PLAYER); - else if (fastcmp(field,"buttons_last")) - lua_pushinteger(L, plr->buttons_last); + else if (fastcmp(field,"lastbuttons")) + lua_pushinteger(L, plr->lastbuttons); else if (fastcmp(field,"jointime")) lua_pushinteger(L, plr->jointime); else if (fastcmp(field,"quittime")) @@ -723,6 +723,15 @@ static int player_set(lua_State *L) plr->outofcoop = lua_toboolean(L, 3); else if (fastcmp(field,"bot")) return NOSET; + else if (fastcmp(field,"botleader")) + { + player_t *player = NULL; + if (!lua_isnil(L, 3)) + player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); + plr->botleader = player; + } + else if (fastcmp(field,"lastbuttons")) + plr->lastbuttons = (UINT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"jointime")) plr->jointime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"quittime")) From 2abf89e8000b6dbda26d5dd59b9306c5d32624b6 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:13:16 -0500 Subject: [PATCH 052/241] Update G_AddPlayer() --- src/lua_baselib.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f54662278..525ce89ec 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3432,8 +3432,7 @@ static int lib_gAddPlayer(lua_State *L) newplayernum = i; - //if (!splitscreen && !botingame) - CL_ClearPlayer(newplayernum); + CL_ClearPlayer(newplayernum); playeringame[newplayernum] = true; G_AddPlayer(newplayernum); @@ -3442,30 +3441,34 @@ static int lib_gAddPlayer(lua_State *L) newplayer->jointime = 0; newplayer->quittime = 0; - // I hereby name you Bot X + // Set the bot name (defaults to Bot #) strcpy(player_names[newplayernum], va("Bot %d", botcount)); - // Read the skin string! + // Read the skin argument (defaults to Sonic) if (!lua_isnoneornil(L, 1)) { skinnum = R_SkinAvailable(luaL_checkstring(L, 1)); skinnum = skinnum < 0 ? 0 : skinnum; } - // Read the color! + // Read the color (defaults to skin prefcolor) if (!lua_isnoneornil(L, 2)) newplayer->skincolor = R_GetColorByName(luaL_checkstring(L, 2)); else newplayer->skincolor = skins[newplayer->skin].prefcolor; - // Read the bot name, if given! + // Read the bot name, if given if (!lua_isnoneornil(L, 3)) strcpy(player_names[newplayernum], luaL_checkstring(L, 3)); bot = luaL_optinteger(L, 4, 3); newplayer->bot = (bot >= 0 && bot <= 3) ? bot : 3; - - // Set the skin (needed to set bot first!) + + // If our bot is a 2P type, we'll need to set its leader so it can spawn + if (newplayer->bot == BOT_2PAI || newplayer->bot == BOT_2PHUMAN) + B_UpdateBotleader(newplayer); + + // Set the skin (can't do this until AFTER bot type is set!) SetPlayerSkinByNum(newplayernum, skinnum); From 2e528216ac855fbfdf9f73df3a534a237936ccbd Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:15:33 -0500 Subject: [PATCH 053/241] Updated references to player->bot --- src/p_user.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 9e86e2d73..c631f49b2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -776,8 +776,8 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) { UINT8 oldmare, oldmarelap, oldmarebonuslap; - // Bots can't be NiGHTSerized, silly!1 :P - if (player->bot && player->bot != 3) + //! Bots can't be NiGHTSerized, silly!1 :P + if (player->bot == BOT_2PAI || player->bot || BOT_2PHUMAN) return; if (player->powers[pw_carry] != CR_NIGHTSMODE) @@ -1188,9 +1188,9 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) { if (!player) return; - - if (player->bot && player->bot != 3) - player = &players[consoleplayer]; + //! + if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) + player = player->botleader; if (!player->mo) return; @@ -1234,8 +1234,8 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres) if (!player) return; - if (player->bot && player->bot != 3) - player = &players[consoleplayer]; + if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) + player = player->botleader; if (!player->mo) return; @@ -1261,8 +1261,8 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) if (!player) return; - if (player->bot && player->bot != 3) - player = &players[consoleplayer]; + if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) + player = player->botleader; if (gamestate == GS_LEVEL) { @@ -1367,8 +1367,8 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) { UINT32 oldscore; - if (player->bot && player->bot != 3) - player = &players[consoleplayer]; + if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) + player = player->botleader; // NiGHTS does it different! if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->typeoflevel & TOL_NIGHTS) @@ -5370,7 +5370,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_STARTDASH); - if (player->bot == 1) + if (player->bot == BOT_2PAI) player->pflags |= PF_THOKKED; else player->pflags |= (PF_THOKKED|PF_CANCARRY); @@ -5957,7 +5957,8 @@ static void P_3dMovement(player_t *player) acceleration = 96 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * 40; topspeed = normalspd; } - else if (player->bot && player->bot != 3) + //! Kill this! + /* else if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) { // Bot steals player 1's stats normalspd = FixedMul(players[consoleplayer].normalspeed, player->mo->scale); thrustfactor = players[consoleplayer].thrustfactor; @@ -5972,7 +5973,7 @@ static void P_3dMovement(player_t *player) } else topspeed = normalspd; - } + } */ else { if (player->powers[pw_super] || player->powers[pw_sneakers]) @@ -9497,7 +9498,7 @@ static void P_DeathThink(player_t *player) if (player->deadtimer < INT32_MAX) player->deadtimer++; - if (player->bot && player->bot != 3) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already + if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) // don't allow followbots to do any of the below, B_CheckRespawn does all they need for respawning already goto notrealplayer; // continue logic @@ -11473,6 +11474,9 @@ void P_PlayerThink(player_t *player) I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri)); #endif + //! Reset terrain blocked status for this frame + player->blocked = false; + // todo: Figure out what is actually causing these problems in the first place... if (player->mo->health <= 0 && player->playerstate == PST_LIVE) //you should be DEAD! { @@ -11480,7 +11484,7 @@ void P_PlayerThink(player_t *player) player->playerstate = PST_DEAD; } - if (player->bot && player->bot != 3) + if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) { if (player->playerstate == PST_LIVE || player->playerstate == PST_DEAD) { @@ -11623,8 +11627,8 @@ void P_PlayerThink(player_t *player) INT32 i; for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator || players[i].bot) + { //! + if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (players[i].lives <= 0) continue; @@ -11655,8 +11659,8 @@ void P_PlayerThink(player_t *player) INT32 i, total = 0, exiting = 0; for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator || players[i].bot) + { //! + if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (players[i].quittime > 30 * TICRATE) continue; @@ -12596,8 +12600,8 @@ void P_PlayerAfterThink(player_t *player) player->mo->momy = tails->momy; player->mo->momz = tails->momz; } - - if (G_CoopGametype() && tails->player && tails->player->bot != 1) + //! + if (G_CoopGametype() && tails->player && tails->player->bot != BOT_2PAI) { player->mo->angle = tails->angle; From 2016caa70b584286af7aff80e83eb63c32f16534 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:16:27 -0500 Subject: [PATCH 054/241] Update references to player->bot --- src/p_mobj.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index a660a8a92..43d81077e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1839,10 +1839,9 @@ void P_XYMovement(mobj_t *mo) // blocked move moved = false; - if (player) { - if (player->bot && player->bot != 3) - B_MoveBlocked(player); - } + //!!! + if (player) + B_MoveBlocked(player); if (LUAh_MobjMoveBlocked(mo)) { @@ -4135,7 +4134,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) player = &players[actor->lastlook]; - if (player->pflags & PF_INVIS || (player->bot && player->bot != 3) || player->spectator) + if (player->pflags & PF_INVIS || player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN || player->spectator) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) @@ -4176,7 +4175,7 @@ boolean P_SupermanLook4Players(mobj_t *actor) if (players[c].pflags & PF_INVIS) continue; // ignore notarget - if (!players[c].mo || players[c].bot) + if (!players[c].mo || players[c].bot == BOT_2PAI || players[c].bot == BOT_2PHUMAN) continue; if (players[c].mo->health <= 0) @@ -7307,7 +7306,7 @@ static void P_RosySceneryThink(mobj_t *mobj) continue; if (!players[i].mo) continue; - if (players[i].bot) + if (players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (!players[i].mo->health) continue; From fd536e91a3bb73c44adcc13486631c18e83d9620 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:17:05 -0500 Subject: [PATCH 055/241] void B_UpdateBotleader(player_t *player); --- src/b_bot.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/b_bot.h b/src/b_bot.h index 2806bd68f..53114df48 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -10,6 +10,7 @@ /// \file b_bot.h /// \brief Basic bot handling +void B_UpdateBotleader(player_t *player); void B_BuildTiccmd(player_t *player, ticcmd_t *cmd); void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin); boolean B_CheckRespawn(player_t *player); From b8fea55f6777d3fa9891d845c6d1430f66acb363 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:25:35 -0500 Subject: [PATCH 056/241] Update b_bot.c --- src/b_bot.c | 251 +++++++++++++++++++++++++++++----------------------- 1 file changed, 139 insertions(+), 112 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index 35b14bd78..151aaa633 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -18,29 +18,41 @@ #include "b_bot.h" #include "lua_hook.h" -// If you want multiple bots, variables like this will -// have to be stuffed in something accessible through player_t. -static boolean lastForward = false; -static boolean lastBlocked = false; -static boolean blocked = false; - -static boolean jump_last = false; -static boolean spin_last = false; -static UINT8 anxiety = 0; -static boolean panic = false; -static UINT8 flymode = 0; -static boolean spinmode = false; -static boolean thinkfly = false; - -static inline void B_ResetAI(void) +void B_UpdateBotleader(player_t *player) { - jump_last = false; - spin_last = false; - anxiety = 0; - panic = false; - flymode = 0; - spinmode = false; - thinkfly = false; + UINT32 i; + fixed_t dist; + fixed_t neardist = INT32_MAX; + player_t *nearplayer = NULL; + //Find new botleader + //if (!player->botleader) + //{ + for (i = 0; i < MAXPLAYERS; i++) + { + if (players[i].bot || players[i].playerstate != PST_LIVE || players[i].spectator || !players[i].mo) + continue; + if (!player->mo) //Can't do distance calculations if there's no player object, so we'll just take the first we find + { + player->botleader = &players[i]; + return; + } + //Update best candidate based on nearest distance + dist = R_PointToDist2(player->mo->x, player->mo->y, players[i].mo->x, players[i].mo->y); + if (neardist > dist) + { + neardist = dist; + nearplayer = &players[i]; + } + } + //Set botleader to best candidate (or null if none available) + player->botleader = nearplayer; + //} +} + +static inline void B_ResetAI(botmem_t *mem) +{ + mem->thinkstate = AI_FOLLOW; + mem->catchup_tics = 0; } static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) @@ -49,39 +61,48 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) player_t *player = sonic->player, *bot = tails->player; ticcmd_t *pcmd = &player->cmd; - boolean water = tails->eflags & MFE_UNDERWATER; + botmem_t *mem = &bot->botmem; + boolean water = (tails->eflags & MFE_UNDERWATER); SINT8 flip = P_MobjFlip(tails); boolean _2d = (tails->flags2 & MF2_TWOD) || twodlevel; fixed_t scale = tails->scale; + boolean jump_last = (bot->lastbuttons & BT_JUMP); + boolean spin_last = (bot->lastbuttons & BT_SPIN); fixed_t dist = P_AproxDistance(sonic->x - tails->x, sonic->y - tails->y); fixed_t zdist = flip * (sonic->z - tails->z); angle_t ang = sonic->angle; fixed_t pmom = P_AproxDistance(sonic->momx, sonic->momy); fixed_t bmom = P_AproxDistance(tails->momx, tails->momy); - fixed_t followmax = 128 * 8 * scale; // Max follow distance before AI begins to enter "panic" state + fixed_t followmax = 128 * 8 * scale; // Max follow distance before AI begins to enter catchup state fixed_t followthres = 92 * scale; // Distance that AI will try to reach fixed_t followmin = 32 * scale; fixed_t comfortheight = 96 * scale; fixed_t touchdist = 24 * scale; boolean stalled = (bmom < scale >> 1) && dist > followthres; // Helps to see if the AI is having trouble catching up boolean samepos = (sonic->x == tails->x && sonic->y == tails->y); - + boolean blocked = bot->blocked; + if (!samepos) ang = R_PointToAngle2(tails->x, tails->y, sonic->x, sonic->y); - // We can't follow Sonic if he's not around! - if (!sonic || sonic->health <= 0) - return; - // Lua can handle it! if (LUAh_BotAI(sonic, tails, cmd)) return; + // We can't follow Sonic if he's not around! + if (!sonic || sonic->health <= 0) + { + mem->thinkstate = AI_STANDBY; + return; + } + else if (mem->thinkstate == AI_STANDBY) + mem->thinkstate = AI_FOLLOW; + if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC) { boolean isrelevant = (sonic->player->powers[pw_carry] == CR_MACESPIN || sonic->player->powers[pw_carry] == CR_GENERIC); - dist = P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y); + //dist = P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y); //! This is totally redundant. if (sonic->player->cmd.buttons & BT_JUMP && (sonic->player->pflags & PF_JUMPED) && isrelevant) cmd->buttons |= BT_JUMP; if (isrelevant) @@ -103,56 +124,57 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) followmin = 0; followthres = 16*scale; followmax >>= 1; - thinkfly = false; + if (mem->thinkstate == AI_THINKFLY) + mem->thinkstate = AI_FOLLOW; } - // Check anxiety - if (spinmode) + // Update catchup_tics + if (mem->thinkstate == AI_SPINFOLLOW) { - anxiety = 0; - panic = false; + mem-> catchup_tics = 0; } else if (dist > followmax || zdist > comfortheight || stalled) { - anxiety = min(anxiety + 2, 70); - if (anxiety >= 70) - panic = true; + mem-> catchup_tics = min(mem-> catchup_tics + 2, 70); + if (mem-> catchup_tics >= 70) + mem->thinkstate = AI_CATCHUP; } else { - anxiety = max(anxiety - 1, 0); - panic = false; + mem-> catchup_tics = max(mem-> catchup_tics - 1, 0); + if (mem->thinkstate == AI_CATCHUP) + mem->thinkstate = AI_FOLLOW; } // Orientation + // cmd->angleturn won't be relative to player angle, since we're not going through G_BuildTiccmd. if (bot->pflags & (PF_SPINNING|PF_STARTDASH)) { - cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT + cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT } - else if (flymode == 2) + else if (mem->thinkstate == AI_FLYCARRY) { - cmd->angleturn = sonic->player->cmd.angleturn - (tails->angle >> 16); + cmd->angleturn = sonic->player->cmd.angleturn; } else { - cmd->angleturn = (ang - tails->angle) >> 16; // NOT FRACBITS DAMNIT + cmd->angleturn = (ang) >> 16; // NOT FRACBITS DAMNIT } // ******** // FLY MODE - // spinmode check - if (spinmode || player->exiting) - thinkfly = false; + // exiting check + if (player->exiting && mem->thinkstate == AI_THINKFLY) + mem->thinkstate = AI_FOLLOW; else { // Activate co-op flight - if (thinkfly && player->pflags & PF_JUMPED) + if (mem->thinkstate == AI_THINKFLY && player->pflags & PF_JUMPED) { if (!jump_last) { jump = true; - flymode = 1; - thinkfly = false; + mem->thinkstate = AI_FLYSTANDBY; bot->pflags |= PF_CANCARRY; } } @@ -165,20 +187,19 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) && P_IsObjectOnGround(sonic) && P_IsObjectOnGround(tails) && !(player->pflags & PF_STASIS) && bot->charability == CA_FLY) - thinkfly = true; - else - thinkfly = false; + mem->thinkstate = AI_THINKFLY; + else if (mem->thinkstate == AI_THINKFLY) + mem->thinkstate = AI_FOLLOW; // Set carried state if (player->powers[pw_carry] == CR_PLAYER && sonic->tracer == tails) { - flymode = 2; + mem->thinkstate = AI_FLYCARRY; } // Ready for takeoff - if (flymode == 1) + if (mem->thinkstate == AI_FLYSTANDBY) { - thinkfly = false; if (zdist < -64*scale || (flip * tails->momz) > scale) // Make sure we're not too high up spin = true; else if (!jump_last) @@ -186,10 +207,10 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) // Abort if the player moves away or spins if (dist > followthres || player->dashspeed) - flymode = 0; + mem->thinkstate = AI_FOLLOW; } // Read player inputs while carrying - else if (flymode == 2) + else if (mem->thinkstate == AI_FLYCARRY) { cmd->forwardmove = pcmd->forwardmove; cmd->sidemove = pcmd->sidemove; @@ -203,19 +224,19 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) // End flymode if (player->powers[pw_carry] != CR_PLAYER) { - flymode = 0; + mem->thinkstate = AI_FOLLOW; } } } - if (flymode && P_IsObjectOnGround(tails) && !(pcmd->buttons & BT_JUMP)) - flymode = 0; + if (P_IsObjectOnGround(tails) && !(pcmd->buttons & BT_JUMP) && (mem->thinkstate == AI_FLYSTANDBY || mem->thinkstate == AI_FLYCARRY)) + mem->thinkstate = AI_FOLLOW; // ******** // SPINNING - if (panic || flymode || !(player->pflags & PF_SPINNING) || (player->pflags & PF_JUMPED)) - spinmode = false; - else + if (!(player->pflags & (PF_SPINNING|PF_STARTDASH)) && mem->thinkstate == AI_SPINFOLLOW) + mem->thinkstate = AI_FOLLOW; + else if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_SPINFOLLOW) { if (!_2d) { @@ -224,21 +245,21 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) { if (dist < followthres && dist > touchdist) // Do positioning { - cmd->angleturn = (ang - tails->angle) >> 16; // NOT FRACBITS DAMNIT + cmd->angleturn = (ang) >> 16; // NOT FRACBITS DAMNIT cmd->forwardmove = 50; - spinmode = true; + mem->thinkstate = AI_SPINFOLLOW; } else if (dist < touchdist) { if (!bmom && (!(bot->pflags & PF_SPINNING) || (bot->dashspeed && bot->pflags & PF_SPINNING))) { - cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT + cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT spin = true; } - spinmode = true; + mem->thinkstate = AI_SPINFOLLOW; } else - spinmode = false; + mem->thinkstate = AI_FOLLOW; } // Spin else if (player->dashspeed == bot->dashspeed && player->pflags & PF_SPINNING) @@ -246,12 +267,12 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) if (bot->pflags & PF_SPINNING || !spin_last) { spin = true; - cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT + cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT cmd->forwardmove = MAXPLMOVE; - spinmode = true; + mem->thinkstate = AI_SPINFOLLOW; } else - spinmode = false; + mem->thinkstate = AI_FOLLOW; } } // 2D mode @@ -261,17 +282,19 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) && ((bot->pflags & PF_SPINNING) || !spin_last)) { spin = true; - spinmode = true; + mem->thinkstate = AI_SPINFOLLOW; } + else + mem->thinkstate = AI_FOLLOW; } } // ******** // FOLLOW - if (!(flymode || spinmode)) + if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_CATCHUP) { // Too far - if (panic || dist > followthres) + if (mem->thinkstate == AI_CATCHUP || dist > followthres) { if (!_2d) cmd->forwardmove = MAXPLMOVE; @@ -281,7 +304,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) cmd->sidemove = -MAXPLMOVE; } // Within threshold - else if (!panic && dist > followmin && abs(zdist) < 192*scale) + else if (dist > followmin && abs(zdist) < 192*scale) { if (!_2d) cmd->forwardmove = FixedHypot(pcmd->forwardmove, pcmd->sidemove); @@ -292,7 +315,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) else if (dist < followmin) { // Copy inputs - cmd->angleturn = (sonic->angle - tails->angle) >> 16; // NOT FRACBITS DAMNIT + cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT bot->drawangle = ang; cmd->forwardmove = 8 * pcmd->forwardmove / 10; cmd->sidemove = 8 * pcmd->sidemove / 10; @@ -301,7 +324,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) // ******** // JUMP - if (!(flymode || spinmode)) + if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_CATCHUP || (mem->thinkstate == AI_SPINFOLLOW && player->pflags & PF_JUMPED)) { // Flying catch-up if (bot->pflags & PF_THOKKED) @@ -319,31 +342,30 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) // Start jump else if (!jump_last && !(bot->pflags & PF_JUMPED) //&& !(player->pflags & PF_SPINNING) && ((zdist > 32*scale && player->pflags & PF_JUMPED) // Following - || (zdist > 64*scale && panic) // Vertical catch-up - || (stalled && anxiety > 20 && bot->powers[pw_carry] == CR_NONE) + || (zdist > 64*scale && mem->thinkstate == AI_CATCHUP) // Vertical catch-up + || (stalled && mem-> catchup_tics > 20 && bot->powers[pw_carry] == CR_NONE) //|| (bmom < scale>>3 && dist > followthres && !(bot->powers[pw_carry])) // Stopped & not in carry state || (bot->pflags & PF_SPINNING && !(bot->pflags & PF_JUMPED)))) // Spinning jump = true; // Hold jump - else if (bot->pflags & PF_JUMPED && jump_last && tails->momz*flip > 0 && (zdist > 0 || panic)) + else if (bot->pflags & PF_JUMPED && jump_last && tails->momz*flip > 0 && (zdist > 0 || mem->thinkstate == AI_CATCHUP)) jump = true; // Start flying - else if (bot->pflags & PF_JUMPED && panic && !jump_last && bot->charability == CA_FLY) + else if (bot->pflags & PF_JUMPED && mem->thinkstate == AI_CATCHUP && !jump_last && bot->charability == CA_FLY) jump = true; } // ******** // HISTORY - jump_last = jump; - spin_last = spin; + //jump_last = jump; + //spin_last = spin; // Turn the virtual keypresses into ticcmd_t. B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin); // Update our status - lastForward = forward; - lastBlocked = blocked; - blocked = false; + mem->lastForward = forward; + mem->lastBlocked = blocked; } void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) @@ -362,32 +384,31 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) // Bot AI isn't programmed in analog. CV_SetValue(&cv_analog[1], false); - // Bot cmd functions and hooks are not currently netplay compatible - // Necessary failsafe, as a bot in the P2 position in a netgame can inherit - // the last input from a hook triggered in splitscreen or SP. - if (netgame) - return; - // Let Lua scripts build ticcmds if (LUAh_BotTiccmd(player, cmd)) return; - // We don't have any main character AI, sorry. D: - if (player-players == consoleplayer) + // Make sure we have a valid main character to follow + B_UpdateBotleader(player); + if (!player->botleader) return; - // Basic Tails AI - B_BuildTailsTiccmd(players[consoleplayer].mo, player->mo, cmd); + // Single Player Tails AI + //B_BuildTailsTiccmd(players[consoleplayer].mo, player->mo, cmd); + B_BuildTailsTiccmd(player->botleader->mo, player->mo, cmd); } void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin) { + player_t *player = mo->player; // don't try to do stuff if your sonic is in a minecart or something - if (players[consoleplayer].powers[pw_carry] && players[consoleplayer].powers[pw_carry] != CR_PLAYER) + //if (players[consoleplayer].powers[pw_carry] && players[consoleplayer].powers[pw_carry] != CR_PLAYER) + //!!! + if (&player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER) return; // Turn the virtual keypresses into ticcmd_t. if (twodlevel || mo->flags2 & MF2_TWOD) { - if (players[consoleplayer].climbing + if (player->botleader->climbing || mo->player->pflags & PF_GLIDING) { // Don't mess with bot inputs during these unhandled movement conditions. // The normal AI doesn't use abilities, so custom AI should be sending us exactly what it wants anyway. @@ -426,10 +447,10 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward cmd->forwardmove += MAXPLMOVE<>16; if (backward) cmd->forwardmove -= MAXPLMOVE<>16; - if (left) + if (left) cmd->angleturn += 1280; if (right) - cmd->angleturn -= 1280; + cmd->angleturn -= 1280; if (strafeleft) cmd->sidemove -= MAXPLMOVE<>16; if (straferight) @@ -453,14 +474,19 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward void B_MoveBlocked(player_t *player) { (void)player; - blocked = true; + player->blocked = true; } boolean B_CheckRespawn(player_t *player) { - mobj_t *sonic = players[consoleplayer].mo; + mobj_t *sonic; mobj_t *tails = player->mo; + //We don't have a main player to spawn to! + if (!player->botleader) + return false; + + sonic = player->botleader->mo; // We can't follow Sonic if he's not around! if (!sonic || sonic->health <= 0) return false; @@ -511,15 +537,19 @@ void B_RespawnBot(INT32 playernum) { player_t *player = &players[playernum]; fixed_t x,y,z; - mobj_t *sonic = players[consoleplayer].mo; + mobj_t *sonic; mobj_t *tails; + if (!player->botleader) + return; + + sonic = player->botleader->mo; if (!sonic || sonic->health <= 0) return; - B_ResetAI(); + B_ResetAI(&player->botmem); - player->bot = 1; + player->bot = BOT_2PAI; P_SpawnPlayer(playernum); tails = player->mo; @@ -546,10 +576,7 @@ void B_RespawnBot(INT32 playernum) player->powers[pw_spacetime] = sonic->player->powers[pw_spacetime]; player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots]; player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol]; - player->acceleration = sonic->player->acceleration; - player->accelstart = sonic->player->accelstart; - player->thrustfactor = sonic->player->thrustfactor; - player->normalspeed = sonic->player->normalspeed; + //!!! Nuke the speed equivalencies player->pflags |= PF_AUTOBRAKE|(sonic->player->pflags & PF_DIRECTIONCHAR); P_TeleportMove(tails, x, y, z); @@ -567,11 +594,11 @@ void B_RespawnBot(INT32 playernum) void B_HandleFlightIndicator(player_t *player) { mobj_t *tails = player->mo; - + botmem_t *mem = &player->botmem; if (!tails) return; - if (thinkfly && player->bot == 1 && tails->health) + if (mem->thinkstate == AI_THINKFLY && player->bot == BOT_2PAI && tails->health) { if (!tails->hnext) { From 4e47f240adc21eab710b6c17673d6053539579eb Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:30:07 -0500 Subject: [PATCH 057/241] Add new botstuffs --- src/d_player.h | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index 2e7afed88..bb206c889 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -313,9 +313,43 @@ typedef enum RW_RAIL = 32 } ringweapons_t; +//Bot types +typedef enum +{ + BOT_NONE = 0, + BOT_2PAI, + BOT_2PHUMAN, + BOT_MPAI +} bottype_t; + +//AI states +typedef enum +{ + AI_STANDBY = 0, + AI_FOLLOW, + AI_CATCHUP, + AI_THINKFLY, + AI_FLYSTANDBY, + AI_FLYCARRY, + AI_SPINFOLLOW +} aistatetype_t; + + // ======================================================================== // PLAYER STRUCTURE // ======================================================================== + +//Bot memory struct +typedef struct botmem_s +{ + boolean lastForward; + boolean lastBlocked; + boolean blocked; + UINT8 catchup_tics; + UINT8 thinkstate; +} botmem_t; + +//Main struct typedef struct player_s { mobj_t *mo; @@ -526,7 +560,11 @@ typedef struct player_s boolean spectator; boolean outofcoop; UINT8 bot; - + struct player_s *botleader; + UINT16 lastbuttons; + botmem_t botmem; + boolean blocked; + tic_t jointime; // Timer when player joins game to change skin/color tic_t quittime; // Time elapsed since user disconnected, zero if connected #ifdef HWRENDER From 25bf4b54e2cccb666acb143aecaaa6f26993fc88 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:36:44 -0500 Subject: [PATCH 058/241] Restructured botticcmds into G_Ticker --- src/g_game.c | 88 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 5e2b4e708..3d6fc52b7 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1087,7 +1087,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) boolean turnleft, turnright, strafelkey, straferkey, movefkey, movebkey, mouseaiming, analogjoystickmove, gamepadjoystickmove, thisjoyaiming; boolean strafeisturn; // Simple controls only player_t *player = &players[ssplayer == 2 ? secondarydisplayplayer : consoleplayer]; - camera_t *thiscam = ((ssplayer == 1 || player->bot == 2) ? &camera : &camera2); + camera_t *thiscam = ((ssplayer == 1 || player->bot == BOT_2PHUMAN) ? &camera : &camera2); angle_t *myangle = (ssplayer == 1 ? &localangle : &localangle2); INT32 *myaiming = (ssplayer == 1 ? &localaiming : &localaiming2); @@ -1560,23 +1560,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->forwardmove = (SINT8)(cmd->forwardmove + forward); cmd->sidemove = (SINT8)(cmd->sidemove + side); - if (player->bot == 1) { // Tailsbot for P2 - if (!player->powers[pw_tailsfly] && (cmd->forwardmove || cmd->sidemove || cmd->buttons)) - { - player->bot = 2; // A player-controlled bot. Returns to AI when it respawns. - CV_SetValue(&cv_analog[1], true); - } - else - { - G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver - B_BuildTiccmd(player, cmd); - } - B_HandleFlightIndicator(player); - } - else if (player->bot == 2) + //Note: Majority of botstuffs are handled in G_Ticker now. + if (player->bot == BOT_2PHUMAN) //Player-controlled bot + { + G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver // Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy cmd->angleturn = (INT16)((localangle - *myangle) >> 16); - + } + *myangle += (cmd->angleturn<<16); if (controlstyle == CS_LMAOGALOG) { @@ -2290,22 +2281,51 @@ void G_Ticker(boolean run) for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) - { + { //!!! INT16 received; + //Save last frame's button readings + players[i].lastbuttons = players[i].cmd.buttons; G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); + //Bot ticcmd handling + //Yes, ordinarily this would be handled in G_BuildTiccmd... + //...however, bot players won't have a corresponding consoleplayer or splitscreen player 2 to send that information. + //Therefore, this has to be done after ticcmd sends are received. + if (players[i].bot == BOT_2PAI) { // Tailsbot for P2 + if (!players[i].powers[pw_tailsfly] && (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons)) + { + players[i].bot = BOT_2PHUMAN; // A player-controlled bot. Returns to AI when it respawns. + CV_SetValue(&cv_analog[1], true); + } + else + { + B_BuildTiccmd(&players[i], &players[i].cmd); + } + B_HandleFlightIndicator(&players[i]); + } + else if (players[i].bot == BOT_MPAI) { + B_BuildTiccmd(&players[i], &players[i].cmd); + } + + // Do angle adjustments. + if (players[i].bot == BOT_NONE || players[i].bot == BOT_2PHUMAN) + { + received = (players[i].cmd.angleturn & TICCMD_RECEIVED); + players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn; + players[i].oldrelangleturn = players[i].cmd.angleturn; + if (P_ControlStyle(&players[i]) == CS_LMAOGALOG) + P_ForceLocalAngle(&players[i], players[i].angleturn << 16); + else + players[i].cmd.angleturn = players[i].angleturn; - received = (players[i].cmd.angleturn & TICCMD_RECEIVED); - - players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn; - players[i].oldrelangleturn = players[i].cmd.angleturn; - if (P_ControlStyle(&players[i]) == CS_LMAOGALOG) - P_ForceLocalAngle(&players[i], players[i].angleturn << 16); - else - players[i].cmd.angleturn = players[i].angleturn; - - players[i].cmd.angleturn &= ~TICCMD_RECEIVED; - players[i].cmd.angleturn |= received; + players[i].cmd.angleturn &= ~TICCMD_RECEIVED; + players[i].cmd.angleturn |= received; + } + else // Less work is required if we're building a bot ticcmd. + { + players[i].angleturn = players[i].cmd.angleturn; + players[i].oldrelangleturn = players[i].cmd.angleturn; + } } } @@ -2627,8 +2647,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->totalring = totalring; p->mare = mare; - if (bot == 2) - p->bot = 1; // reset to AI-controlled + if (bot == BOT_2PHUMAN) + p->bot = BOT_2PAI; // reset to AI-controlled else p->bot = bot; p->pity = pity; @@ -2976,8 +2996,8 @@ void G_DoReborn(INT32 playernum) // Make sure objectplace is OFF when you first start the level! OP_ResetObjectplace(); - // Tailsbot - if (player->bot && player->bot != 3 && playernum != consoleplayer) + //! Tailsbot + if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) { // Bots respawn next to their master. mobj_t *oldmo = NULL; @@ -3198,7 +3218,7 @@ void G_AddPlayer(INT32 playernum) if (!playeringame[i]) continue; - if (players[i].bot) // ignore dumb, stupid tails + if (players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) // ignore dumb, stupid tails continue; countplayers++; @@ -3239,7 +3259,7 @@ boolean G_EnoughPlayersFinished(void) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || players[i].spectator || players[i].bot) + if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (players[i].quittime > 30 * TICRATE) continue; From 1274b4651e6decce71a8b4627bb367377a483465 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:39:59 -0500 Subject: [PATCH 059/241] Added botstuffs to savestate --- src/p_saveg.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index c1364e08f..d80495e5b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -158,6 +158,18 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].dashmode); WRITEUINT32(save_p, players[i].skidtime); + ////////// + // Bots // + ////////// + WRITEUINT8(save_p, players[i].bot); + WRITEUINT8(save_p, players[i].botmem.lastForward); + WRITEUINT8(save_p, players[i].botmem.lastBlocked); + WRITEUINT8(save_p, players[i].botmem.catchup_tics); + WRITEUINT8(save_p, players[i].botmem.thinkstate); + + WRITEUINT8(save_p, players[i].blocked); + WRITEUINT16(save_p, players[i].lastbuttons); + //////////////////////////// // Conveyor Belt Movement // //////////////////////////// @@ -372,6 +384,19 @@ static void P_NetUnArchivePlayers(void) players[i].dashmode = READUINT32(save_p); // counter for dashmode ability players[i].skidtime = READUINT32(save_p); // Skid timer + ////////// + // Bots // + ////////// + players[i].bot = READUINT8(save_p); + + players[i].botmem.lastForward = READUINT8(save_p); + players[i].botmem.lastBlocked = READUINT8(save_p); + players[i].botmem.catchup_tics = READUINT8(save_p); + players[i].botmem.thinkstate = READUINT8(save_p); + + players[i].blocked = READUINT8(save_p); + players[i].lastbuttons = READUINT16(save_p); + //////////////////////////// // Conveyor Belt Movement // //////////////////////////// From 135032c2932afa6474b15b0859717fe1771a3dc7 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sat, 23 Jan 2021 10:58:34 -0500 Subject: [PATCH 060/241] Correction to implicit declaration of B_UpdateBotleader() --- src/lua_baselib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 525ce89ec..b6adc0ccd 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -28,6 +28,7 @@ #include "console.h" #include "d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff +#include "b_bot.h" // B_UpdateBotleader #include "lua_script.h" #include "lua_libs.h" From 0a60fe0b1db198d8ed9ead70bab43a4e7711810b Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Sat, 23 Jan 2021 14:05:36 -0800 Subject: [PATCH 061/241] Almost forgot: player.blocked --- src/lua_playerlib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 51eb4ac0c..8156c2ac1 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -374,6 +374,8 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->botleader, META_PLAYER); else if (fastcmp(field,"lastbuttons")) lua_pushinteger(L, plr->lastbuttons); + else if (fastcmp(field,"blocked")) + lua_pushboolean(L, plr->blocked); else if (fastcmp(field,"jointime")) lua_pushinteger(L, plr->jointime); else if (fastcmp(field,"quittime")) @@ -732,6 +734,8 @@ static int player_set(lua_State *L) } else if (fastcmp(field,"lastbuttons")) plr->lastbuttons = (UINT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"blocked")) + plr->blocked = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"jointime")) plr->jointime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"quittime")) From 93ec472c7849fecb0fe53e99e7802904a2b7c1ba Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Sat, 23 Jan 2021 14:49:20 -0800 Subject: [PATCH 062/241] Expose BOT_ to lua --- src/deh_tables.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index 3039bf7de..cd6ceb3c6 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5167,6 +5167,12 @@ struct int_const_s const INT_CONST[] = { {"GF_REDFLAG",GF_REDFLAG}, {"GF_BLUEFLAG",GF_BLUEFLAG}, + // Bot types + {"BOT_NONE",BOT_NONE}, + {"BOT_2PAI",BOT_2PAI}, + {"BOT_2PHUMAN",BOT_2PHUMAN}, + {"BOT_MPAI",BOT_MPAI}, + // Customisable sounds for Skins, from sounds.h {"SKSSPIN",SKSSPIN}, {"SKSPUTPUT",SKSPUTPUT}, From a2fce68f14fe8002394639ce1f8facf109f3ea3c Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Sat, 23 Jan 2021 17:01:48 -0800 Subject: [PATCH 063/241] Specialized Lua function for bot removal --- src/d_clisrv.c | 18 +++++++----------- src/d_clisrv.h | 1 + src/lua_baselib.c | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4574e5a1c..691408b54 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2472,7 +2472,7 @@ void CL_ClearPlayer(INT32 playernum) // // Removes a player from the current game // -static void CL_RemovePlayer(INT32 playernum, kickreason_t reason) +void CL_RemovePlayer(INT32 playernum, kickreason_t reason) { // Sanity check: exceptional cases (i.e. c-fails) can cause multiple // kick commands to be issued for the same player. @@ -2815,22 +2815,18 @@ static void Command_Kick(void) return; } + if (!netgame) // Don't kick Tails in splitscreen! + { + CONS_Printf(M_GetText("This only works in a netgame.\n")); + return; + } + if (server || IsPlayerAdmin(consoleplayer)) { UINT8 buf[3 + MAX_REASONLENGTH]; UINT8 *p = buf; const SINT8 pn = nametonum(COM_Argv(1)); - // Unlike bans, kicks are used especially to remove bot players, so we'll - // need to run a more specific check which allows kicking offline, but - // not against splitscreen players. - if (splitscreen && (pn == 0 || pn == 1)) - { - CONS_Printf(M_GetText("Splitscreen players cannot be kicked.\n")); - return; - } - - if (pn == -1 || pn == 0) return; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 3d67525da..adb611ecf 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -401,6 +401,7 @@ void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); void CL_QueryServerList(msg_server_t *list); void CL_UpdateServerList(boolean internetsearch, INT32 room); +void CL_RemovePlayer(INT32 playernum, kickreason_t reason); // Is there a game running boolean Playing(void); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b6adc0ccd..9aeabe1fc 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -29,6 +29,7 @@ #include "d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff #include "b_bot.h" // B_UpdateBotleader +#include "d_clisrv.h" // CL_RemovePlayer #include "lua_script.h" #include "lua_libs.h" @@ -3463,7 +3464,7 @@ static int lib_gAddPlayer(lua_State *L) strcpy(player_names[newplayernum], luaL_checkstring(L, 3)); bot = luaL_optinteger(L, 4, 3); - newplayer->bot = (bot >= 0 && bot <= 3) ? bot : 3; + newplayer->bot = (bot >= BOT_NONE && bot <= BOT_MPAI) ? bot : BOT_MPAI; // If our bot is a 2P type, we'll need to set its leader so it can spawn if (newplayer->bot == BOT_2PAI || newplayer->bot == BOT_2PHUMAN) @@ -3487,6 +3488,37 @@ static int lib_gAddPlayer(lua_State *L) } +// Bot removing function +static int lib_gRemovePlayer(lua_State *L) +{ + UINT8 pnum = -1; + //const char *kickreason = luaL_checkstring(L, 2); + + if (!lua_isnoneornil(L, 1)) + pnum = luaL_checkinteger(L, 1); + if (&players[pnum]) + { + if (players[pnum].bot != BOT_NONE) + { +// CL_RemovePlayer(pnum, *kickreason); + CL_RemovePlayer(pnum, pnum); + if (netgame) + { + char kickmsg[256]; + + strcpy(kickmsg, M_GetText("\x82*Bot %s has been removed")); + strcpy(kickmsg, va(kickmsg, player_names[pnum], pnum)); + HU_AddChatText(kickmsg, false); + } + lua_pushboolean(L, true); + return 1; + } + } + lua_pushboolean(L, false); + return 1; +} + + static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) { if (ISINLEVEL) @@ -4068,6 +4100,7 @@ static luaL_Reg lib[] = { // g_game {"G_AddGametype", lib_gAddGametype}, {"G_AddPlayer", lib_gAddPlayer}, + {"G_RemovePlayer", lib_gRemovePlayer}, {"G_BuildMapName",lib_gBuildMapName}, {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_FindMap",lib_gFindMap}, From ea6879b5c290811395a74c442924f2a200c491ce Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sun, 24 Jan 2021 12:43:13 -0500 Subject: [PATCH 064/241] missed a couple spots --- 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 637eba83f..d0e0cc9ee 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -743,8 +743,8 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if (player->mo->health <= 0) continue; // dead - if (player->bot && player->bot != 3) - continue; // ignore bots + if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) + continue; // ignore followbots if (player->quittime) continue; // Ignore uncontrolled bodies @@ -3590,7 +3590,7 @@ void A_1upThinker(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || players[i].bot || players[i].spectator) + if (!playeringame[i] || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN || players[i].spectator) continue; if (!players[i].mo) From ca00e2d5086af7f6a5ba63a3caf82b74742680a1 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Sun, 24 Jan 2021 12:46:03 -0500 Subject: [PATCH 065/241] correction to nights bot clause --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index c631f49b2..f0cbb6f37 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -777,7 +777,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) UINT8 oldmare, oldmarelap, oldmarebonuslap; //! Bots can't be NiGHTSerized, silly!1 :P - if (player->bot == BOT_2PAI || player->bot || BOT_2PHUMAN) + if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) return; if (player->powers[pw_carry] != CR_NIGHTSMODE) From 4891611ab73a7ec60119bfee84d5a164b3127611 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Wed, 27 Jan 2021 19:23:04 -0300 Subject: [PATCH 066/241] tRNS chunk fix Fixes a faulty check not properly detecting the presence of a tRNS chunk. --- src/r_picformats.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_picformats.c b/src/r_picformats.c index f87362c76..ac9747426 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -979,8 +979,8 @@ static png_bytep *PNG_Read( for (i = 0; i < 256; i++) { - UINT32 rgb = R_PutRgbaRGBA(pal->red, pal->green, pal->blue, 0xFF); - if (rgb != pMasterPalette[i].rgba) + byteColor_t *curpal = &(pMasterPalette[i].s); + if (pal->red != curpal->red || pal->green != curpal->green || pal->blue != curpal->blue) { usepal = false; break; @@ -996,12 +996,12 @@ static png_bytep *PNG_Read( { png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values); - if (trans && trans_num == 256) + if (trans && trans_num > 0) { INT32 i; for (i = 0; i < trans_num; i++) { - // libpng will transform this image into RGB even if + // libpng will transform this image into RGBA even if // the transparent index does not exist in the image, // and there is no way around that. if (trans[i] < 0xFF) From 326be012760a1f9e1dff38d3162d8120b620a489 Mon Sep 17 00:00:00 2001 From: namishere <50415197+namishere@users.noreply.github.com> Date: Thu, 11 Feb 2021 04:06:40 -0800 Subject: [PATCH 067/241] Expose P_ButteredSlope to lua --- src/lua_baselib.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index c5f847be6..240591506 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2494,6 +2494,17 @@ static int lib_pGetZAt(lua_State *L) return 1; } +static int lib_pButteredSlope(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + P_ButteredSlope(mobj); + return 0; +} + // R_DEFS //////////// @@ -3932,6 +3943,7 @@ static luaL_Reg lib[] = { // p_slopes {"P_GetZAt",lib_pGetZAt}, + {"P_ButteredSlope",lib_pButteredSlope}, // r_defs {"R_PointToAngle",lib_rPointToAngle}, From eda6b0ad8edb2cfda121f8e5058065975a853a1f Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 11 Feb 2021 13:24:20 +0100 Subject: [PATCH 068/241] Remove TAG_ITER_DECLARECOUNTER and the level field on the iterator macros. Declare the position counters inside the for loops instead; RIP C90. --- src/p_ceilng.c | 6 +-- src/p_floor.c | 39 ++++++---------- src/p_lights.c | 3 +- src/p_mobj.c | 6 +-- src/p_setup.c | 8 +--- src/p_slopes.c | 3 +- src/p_spec.c | 122 +++++++++++++++++++++++-------------------------- src/taglist.h | 11 ++--- 8 files changed, 82 insertions(+), 116 deletions(-) diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 2168d1d78..264a6e2c8 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -395,9 +395,8 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) sector_t *sec; ceiling_t *ceiling; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -617,9 +616,8 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type) sector_t *sec; ceiling_t *ceiling; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; diff --git a/src/p_floor.c b/src/p_floor.c index de8f5d4e8..86a2a9319 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -635,7 +635,6 @@ void T_BounceCheese(bouncecheese_t *bouncer) boolean remove; INT32 i; mtag_t tag = Tag_FGet(&bouncer->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT || bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself! @@ -650,7 +649,7 @@ void T_BounceCheese(bouncecheese_t *bouncer) } // You can use multiple target sectors, but at your own risk!!! - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { actionsector = §ors[i]; actionsector->moved = true; @@ -775,7 +774,6 @@ void T_StartCrumble(crumble_t *crumble) sector_t *sector; INT32 i; mtag_t tag = Tag_FGet(&crumble->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); // Once done, the no-return thinker just sits there, // constantly 'returning'... kind of an oxymoron, isn't it? @@ -804,7 +802,7 @@ void T_StartCrumble(crumble_t *crumble) } else if (++crumble->timer == 0) // Reposition back to original spot { - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; @@ -840,7 +838,7 @@ void T_StartCrumble(crumble_t *crumble) // Flash to indicate that the platform is about to return. if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0)) { - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; @@ -932,7 +930,7 @@ void T_StartCrumble(crumble_t *crumble) P_RemoveThinker(&crumble->thinker); } - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; sector->moved = true; @@ -948,7 +946,6 @@ void T_StartCrumble(crumble_t *crumble) void T_MarioBlock(mariothink_t *block) { INT32 i; - TAG_ITER_DECLARECOUNTER(0); T_MovePlane ( @@ -983,7 +980,7 @@ void T_MarioBlock(mariothink_t *block) block->sector->ceilspeed = 0; block->direction = 0; } - TAG_ITER_SECTORS(0, (INT16)block->tag, i) + TAG_ITER_SECTORS((INT16)block->tag, i) P_RecalcPrecipInSector(§ors[i]); } @@ -1293,9 +1290,8 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) INT32 secnum = -1; boolean FOFsector = false; mtag_t tag = Tag_FGet(&nobaddies->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -1306,14 +1302,13 @@ void T_NoEnemiesSector(noenemies_t *nobaddies) { INT32 targetsecnum = -1; mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags); - TAG_ITER_DECLARECOUNTER(1); if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) continue; FOFsector = true; - TAG_ITER_SECTORS(1, tag2, targetsecnum) + TAG_ITER_SECTORS(tag2, targetsecnum) { if (T_SectorHasEnemies(§ors[targetsecnum])) return; @@ -1400,7 +1395,6 @@ void T_EachTimeThinker(eachtime_t *eachtime) fixed_t bottomheight, topheight; ffloor_t *rover; mtag_t tag = Tag_FGet(&eachtime->sourceline->tags); - TAG_ITER_DECLARECOUNTER(0); for (i = 0; i < MAXPLAYERS; i++) { @@ -1410,7 +1404,7 @@ void T_EachTimeThinker(eachtime_t *eachtime) eachtime->playersOnArea[i] = false; } - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -1428,14 +1422,13 @@ void T_EachTimeThinker(eachtime_t *eachtime) { INT32 targetsecnum = -1; mtag_t tag2 = Tag_FGet(&sec->lines[i]->tags); - TAG_ITER_DECLARECOUNTER(1); if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) continue; FOFsector = true; - TAG_ITER_SECTORS(1, tag2, targetsecnum) + TAG_ITER_SECTORS(tag2, targetsecnum) { targetsec = §ors[targetsecnum]; @@ -1570,12 +1563,11 @@ void T_RaiseSector(raise_t *raise) INT32 direction; result_e res = 0; mtag_t tag = raise->tag; - TAG_ITER_DECLARECOUNTER(0); if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata) return; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { sector = §ors[i]; @@ -1702,7 +1694,7 @@ void T_RaiseSector(raise_t *raise) raise->sector->ceilspeed = 42; raise->sector->floorspeed = speed*direction; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) P_RecalcPrecipInSector(§ors[i]); } @@ -1820,9 +1812,8 @@ void EV_DoFloor(line_t *line, floor_e floortype) sector_t *sec; floormove_t *dofloor; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -2037,10 +2028,9 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) sector_t *sec; elevator_t *elevator; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); // act on all sectors with the same tag as the triggering linedef - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; @@ -2337,7 +2327,6 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, sector_t *foundsec; INT32 i; mtag_t tag = Tag_FGet(&rover->master->tags); - TAG_ITER_DECLARECOUNTER(0); // If floor is already activated, skip it if (sec->floordata) @@ -2380,7 +2369,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, crumble->sector->crumblestate = CRUMBLE_ACTIVATED; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { foundsec = §ors[i]; diff --git a/src/p_lights.c b/src/p_lights.c index d396e92d3..3fc8e6c10 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -374,10 +374,9 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force) { INT32 i; - TAG_ITER_DECLARECOUNTER(0); // search all sectors for ones with tag - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { if (!force && ticbased // always let speed fader execute && sectors[i].lightingdata diff --git a/src/p_mobj.c b/src/p_mobj.c index 69eecd26d..2b408b2fd 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4607,9 +4607,8 @@ static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta) INT32 snum; sector_t *sector; boolean gotcage = false; - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, snum) + TAG_ITER_SECTORS(tag, snum) { sector = §ors[snum]; sector->floorheight += delta; @@ -4693,9 +4692,8 @@ static void P_Boss4DestroyCage(mobj_t *mobj) size_t a; sector_t *sector, *rsec; ffloor_t *rover; - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, snum) + TAG_ITER_SECTORS(tag, snum) { sector = §ors[snum]; diff --git a/src/p_setup.c b/src/p_setup.c index 2c0b84ba6..e93d930da 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2966,9 +2966,7 @@ static void P_ConvertBinaryMap(void) INT32 check = -1; INT32 paramline = -1; - TAG_ITER_DECLARECOUNTER(0); - - TAG_ITER_LINES(0, tag, check) + TAG_ITER_LINES(tag, check) { if (lines[check].special == 22) { @@ -3183,11 +3181,9 @@ static void P_ConvertBinaryMap(void) INT32 firstline = -1; mtag_t tag = mapthings[i].angle; - TAG_ITER_DECLARECOUNTER(0); - Tag_FSet(&mapthings[i].tags, tag); - TAG_ITER_LINES(0, tag, check) + TAG_ITER_LINES(tag, check) { if (lines[check].special == 20) { diff --git a/src/p_slopes.c b/src/p_slopes.c index d77d0805f..29fbb308f 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -546,11 +546,10 @@ static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling) { INT32 i; pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope; - TAG_ITER_DECLARECOUNTER(0); if (!tag || *secslope) return false; - TAG_ITER_SECTORS(0, tag, i) + TAG_ITER_SECTORS(tag, i) { pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope; if (srcslope) diff --git a/src/p_spec.c b/src/p_spec.c index eb14f8dd6..998f8d9e3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2223,7 +2223,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT32 secnum = -1; mobj_t *bot = NULL; mtag_t tag = Tag_FGet(&line->tags); - TAG_ITER_DECLARECOUNTER(0); I_Assert(!mo || !P_MobjWasRemoved(mo)); // If mo is there, mo must be valid! @@ -2251,7 +2250,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) newceilinglightsec = line->frontsector->ceilinglightsec; // act on all sectors with the same tag as the triggering linedef - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (sectors[secnum].lightingdata) { @@ -2306,7 +2305,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 409: // Change tagged sectors' tag // (formerly "Change calling sectors' tag", but behavior was changed) { - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) Tag_SectorFSet(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); break; } @@ -2316,7 +2315,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 411: // Stop floor/ceiling movement in tagged sector(s) - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (sectors[secnum].floordata) { @@ -2501,7 +2500,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Additionally play the sound from tagged sectors' soundorgs sector_t *sec; - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { sec = §ors[secnum]; S_StartSound(&sec->soundorg, sfxnum); @@ -2616,7 +2615,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 416: // Spawn adjustable fire flicker - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2650,7 +2649,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 417: // Spawn adjustable glowing light - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2684,7 +2683,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 418: // Spawn adjustable strobe flash (unsynchronized) - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2718,7 +2717,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 419: // Spawn adjustable strobe flash (synchronized) - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2766,7 +2765,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 421: // Stop lighting effect in tagged sectors - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) if (sectors[secnum].lightingdata) { P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); @@ -2980,7 +2979,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ffloor_t *rover; // FOF that we are going to crumble boolean foundrover = false; // for debug, "Can't find a FOF" message - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3105,7 +3104,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->sidenum[1] != 0xffff) state = (statenum_t)sides[line->sidenum[1]].toptexture; - TAG_ITER_SECTORS(0, tag, secnum) + TAG_ITER_SECTORS(tag, secnum) { boolean tryagain; sec = sectors + secnum; @@ -3165,7 +3164,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) boolean foundrover = false; // for debug, "Can't find a FOF" message ffloortype_e oldflags; // store FOF's old flags - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3223,7 +3222,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->flags & ML_NOCLIMB) // don't respawn! respawn = false; - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3279,7 +3278,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) source = sectors[sourcesec].extra_colormap; } } - TAG_ITER_SECTORS(0, line->args[0], secnum) + TAG_ITER_SECTORS(line->args[0], secnum) { if (sectors[secnum].colormap_protected) continue; @@ -3414,7 +3413,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3478,7 +3477,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) boolean foundrover = false; // for debug, "Can't find a FOF" message size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3563,7 +3562,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) ffloor_t *rover; // FOF that we are going to operate boolean foundrover = false; // for debug, "Can't find a FOF" message - TAG_ITER_SECTORS(0, sectag, secnum) + TAG_ITER_SECTORS(sectag, secnum) { sec = sectors + secnum; @@ -3614,7 +3613,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } } - TAG_ITER_SECTORS(0, line->args[0], secnum) + TAG_ITER_SECTORS(line->args[0], secnum) { extracolormap_t *source_exc, *dest_exc, *exc; @@ -3694,7 +3693,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } case 456: // Stop fade colormap - TAG_ITER_SECTORS(0, line->args[0], secnum) + TAG_ITER_SECTORS(line->args[0], secnum) P_ResetColormapFader(§ors[secnum]); break; @@ -3887,12 +3886,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 465: // Set linedef executor delay { INT32 linenum; - TAG_ITER_DECLARECOUNTER(1); if (!udmf) break; - TAG_ITER_LINES(1, line->args[0], linenum) + TAG_ITER_LINES(line->args[0], linenum) { if (line->args[2]) lines[linenum].executordelay += line->args[1]; @@ -5928,9 +5926,8 @@ void T_LaserFlash(laserthink_t *flash) sector_t *sector; sector_t *sourcesec = flash->sourceline->frontsector; fixed_t top, bottom; - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, flash->tag, s) + TAG_ITER_SECTORS(flash->tag, s) { sector = §ors[s]; for (fflr = sector->ffloors; fflr; fflr = fflr->next) @@ -6210,11 +6207,10 @@ void P_SpawnSpecials(boolean fromnetsave) INT32 s; size_t sec; ffloortype_e ffloorflags; - TAG_ITER_DECLARECOUNTER(0); case 1: // Definable gravity per sector sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) { sectors[s].gravity = §ors[sec].floorheight; // This allows it to change in realtime! @@ -6238,7 +6234,7 @@ void P_SpawnSpecials(boolean fromnetsave) case 5: // Change camera info sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); break; @@ -6265,7 +6261,7 @@ void P_SpawnSpecials(boolean fromnetsave) P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs); else { - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs); } } @@ -6276,7 +6272,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 8: // Sector Parameters - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) { if (lines[i].flags & ML_NOCLIMB) { @@ -6303,7 +6299,7 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 10: // Vertical culling plane for sprites and FOFs - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].cullheight = &lines[i]; // This allows it to change in realtime! break; @@ -6364,19 +6360,19 @@ void P_SpawnSpecials(boolean fromnetsave) case 63: // support for drawn heights coming from different sector sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].heightsec = (INT32)sec; break; case 64: // Appearing/Disappearing FOF option if (lines[i].flags & ML_BLOCKMONSTERS) { // Find FOFs by control sector tag - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) for (j = 0; (unsigned)j < sectors[s].linecount; j++) if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i); } else // Find FOFs by effect sector tag { - TAG_ITER_LINES(0, tag, s) + TAG_ITER_LINES(tag, s) { if ((size_t)s == i) continue; @@ -6387,15 +6383,15 @@ void P_SpawnSpecials(boolean fromnetsave) break; case 66: // Displace floor by front sector - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddPlaneDisplaceThinker(pd_floor, FixedHypot(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; case 67: // Displace ceiling by front sector - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddPlaneDisplaceThinker(pd_ceiling, FixedHypot(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; case 68: // Displace both floor AND ceiling by front sector - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddPlaneDisplaceThinker(pd_both, FixedHypot(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; @@ -6991,46 +6987,46 @@ void P_SpawnSpecials(boolean fromnetsave) case 600: // floor lighting independently (e.g. lava) sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].floorlightsec = (INT32)sec; break; case 601: // ceiling lighting independently sec = sides[*lines[i].sidenum].sector-sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) sectors[s].ceilinglightsec = (INT32)sec; break; case 602: // Adjustable pulsating light sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableGlowingLight(§ors[sec], §ors[s], FixedHypot(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 603: // Adjustable flickering light sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableFireFlicker(§ors[sec], §ors[s], FixedHypot(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 604: // Adjustable Blinking Light (unsynchronized) sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false); break; case 605: // Adjustable Blinking Light (synchronized) sec = sides[*lines[i].sidenum].sector - sectors; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true); break; case 606: // HACK! Copy colormaps. Just plain colormaps. - TAG_ITER_SECTORS(0, lines[i].args[0], s) + TAG_ITER_SECTORS(lines[i].args[0], s) { extracolormap_t *exc; @@ -7104,13 +7100,12 @@ void P_SpawnSpecials(boolean fromnetsave) */ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinkerlist_t *secthinkers) { - TAG_ITER_DECLARECOUNTER(0); INT32 s; mtag_t tag = Tag_FGet(&lines[line].tags); size_t sec = sides[*lines[line].sidenum].sector-sectors; line_t* li = lines + line; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) P_AddFakeFloor(§ors[s], §ors[sec], li, ffloorflags, secthinkers); } @@ -7220,7 +7215,6 @@ void T_Scroll(scroll_t *s) size_t i; INT32 sect; ffloor_t *rover; - TAG_ITER_DECLARECOUNTER(0); case sc_side: // scroll wall texture side = sides + s->affectee; @@ -7257,7 +7251,7 @@ void T_Scroll(scroll_t *s) if (!is3dblock) continue; - TAG_ITER_SECTORS(0, Tag_FGet(&line->tags), sect) + TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) { sector_t *psec; psec = sectors + sect; @@ -7332,7 +7326,7 @@ void T_Scroll(scroll_t *s) if (!is3dblock) continue; - TAG_ITER_SECTORS(0, Tag_FGet(&line->tags), sect) + TAG_ITER_SECTORS(Tag_FGet(&line->tags), sect) { sector_t *psec; psec = sectors + sect; @@ -7472,11 +7466,10 @@ static void P_SpawnScrollers(void) switch (special) { register INT32 s; - TAG_ITER_DECLARECOUNTER(0); case 513: // scroll effect ceiling case 533: // scroll and carry objects on ceiling - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_ceiling, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); if (special != 533) break; @@ -7485,13 +7478,13 @@ static void P_SpawnScrollers(void) case 523: // carry objects on ceiling dx = FixedMul(dx, CARRYFACTOR); dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_carry_ceiling, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); break; case 510: // scroll effect floor case 530: // scroll and carry objects on floor - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_floor, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); if (special != 530) break; @@ -7500,7 +7493,7 @@ static void P_SpawnScrollers(void) case 520: // carry objects on floor dx = FixedMul(dx, CARRYFACTOR); dy = FixedMul(dy, CARRYFACTOR); - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Scroller(sc_carry, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); break; @@ -7508,7 +7501,7 @@ static void P_SpawnScrollers(void) // (same direction and speed as scrolling floors) case 502: { - TAG_ITER_LINES(0, tag, s) + TAG_ITER_LINES(tag, s) if (s != (INT32)i) { if (l->flags & ML_EFFECT2) // use texture offsets instead @@ -7610,9 +7603,8 @@ void T_Disappear(disappear_t *d) ffloor_t *rover; register INT32 s; mtag_t afftag = Tag_FGet(&lines[d->affectee].tags); - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, afftag, s) + TAG_ITER_SECTORS(afftag, s) { for (rover = sectors[s].ffloors; rover; rover = rover->next) { @@ -8343,7 +8335,6 @@ static void P_SpawnFriction(void) fixed_t strength; // frontside texture offset controls magnitude fixed_t friction; // friction value to be applied during movement INT32 movefactor; // applied to each player move to simulate inertia - TAG_ITER_DECLARECOUNTER(0); for (i = 0; i < numlines; i++, l++) if (l->special == 540) @@ -8369,7 +8360,7 @@ static void P_SpawnFriction(void) else movefactor = FRACUNIT; - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Friction(friction, movefactor, s, -1); } } @@ -8888,7 +8879,6 @@ static void P_SpawnPushers(void) mtag_t tag; register INT32 s; mobj_t *thing; - TAG_ITER_DECLARECOUNTER(0); for (i = 0; i < numlines; i++, l++) { @@ -8896,15 +8886,15 @@ static void P_SpawnPushers(void) switch (l->special) { case 541: // wind - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_wind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 544: // current - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_current, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 547: // push/pull - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) { thing = P_GetPushThing(s); if (thing) // No MT_P* means no effect @@ -8912,19 +8902,19 @@ static void P_SpawnPushers(void) } break; case 545: // current up - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_upcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 546: // current down - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_downcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 542: // wind up - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_upwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 543: // wind down - TAG_ITER_SECTORS(0, tag, s) + TAG_ITER_SECTORS(tag, s) Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; } diff --git a/src/taglist.h b/src/taglist.h index a0529ab6b..df0606a68 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -71,15 +71,12 @@ INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p); INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag); INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start); -// Use this macro to declare an iterator position variable. -#define TAG_ITER_DECLARECOUNTER(level) size_t ICNT_##level - -#define TAG_ITER(level, fn, tag, return_varname) for(ICNT_##level = 0; (return_varname = fn(tag, ICNT_##level)) >= 0; ICNT_##level++) +#define TAG_ITER(fn, tag, return_varname) for(size_t ICNT_ ## __LINE__ = 0; (return_varname = fn(tag, ICNT_ ## __LINE__)) >= 0; ICNT_ ## __LINE__++) // Use these macros as wrappers for a taglist iteration. -#define TAG_ITER_SECTORS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Sectors, tag, return_varname) -#define TAG_ITER_LINES(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Lines, tag, return_varname) -#define TAG_ITER_THINGS(level, tag, return_varname) TAG_ITER(level, Tag_Iterate_Things, tag, return_varname) +#define TAG_ITER_SECTORS(tag, return_varname) TAG_ITER(Tag_Iterate_Sectors, tag, return_varname) +#define TAG_ITER_LINES(tag, return_varname) TAG_ITER(Tag_Iterate_Lines, tag, return_varname) +#define TAG_ITER_THINGS(tag, return_varname) TAG_ITER(Tag_Iterate_Things, tag, return_varname) /* ITERATION MACROS TAG_ITER_DECLARECOUNTER must be used before using the iterators. From fbe2a19c6037bc141dbe56304164a6a80de23316 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 11 Feb 2021 14:12:50 +0100 Subject: [PATCH 069/241] Fix __LINE__ macro expansion via recursive macro expansion; C macros sure are something sometimes... --- src/taglist.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/taglist.h b/src/taglist.h index df0606a68..b02fc34dd 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -71,7 +71,9 @@ INT32 Tag_Iterate_Things (const mtag_t tag, const size_t p); INT32 Tag_FindLineSpecial(const INT16 special, const mtag_t tag); INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start); -#define TAG_ITER(fn, tag, return_varname) for(size_t ICNT_ ## __LINE__ = 0; (return_varname = fn(tag, ICNT_ ## __LINE__)) >= 0; ICNT_ ## __LINE__++) +#define ICNAME2(id) ICNT_##id +#define ICNAME(id) ICNAME2(id) +#define TAG_ITER(fn, tag, return_varname) for(size_t ICNAME(__LINE__) = 0; (return_varname = fn(tag, ICNAME(__LINE__))) >= 0; ICNAME(__LINE__)++) // Use these macros as wrappers for a taglist iteration. #define TAG_ITER_SECTORS(tag, return_varname) TAG_ITER(Tag_Iterate_Sectors, tag, return_varname) From a57c695f79de5e863e1c708c340fa30c9735e665 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 11 Feb 2021 14:22:49 +0100 Subject: [PATCH 070/241] Update example comment. --- src/taglist.h | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/taglist.h b/src/taglist.h index b02fc34dd..2dd160c9a 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -81,14 +81,6 @@ INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start); #define TAG_ITER_THINGS(tag, return_varname) TAG_ITER(Tag_Iterate_Things, tag, return_varname) /* ITERATION MACROS -TAG_ITER_DECLARECOUNTER must be used before using the iterators. - -'level': -For each nested iteration, an additional TAG_ITER_DECLARECOUNTER -must be used with a different level number to avoid conflict with -the outer iterations. -Most cases don't have nested iterations and thus the level is just 0. - 'tag': Pretty much the elements' tag to iterate through. @@ -98,17 +90,12 @@ Target variable's name to return the iteration results to. EXAMPLE: { - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_DECLARECOUNTER(1); // For the nested iteration. - size_t li; - size_t sec; - INT32 tag1 = 4; ... - TAG_ITER_LINES(0, tag1, li) + TAG_ITER_LINES(tag1, li) { line_t *line = lines + li; @@ -116,11 +103,11 @@ EXAMPLE: if (something) { + size_t sec; mtag_t tag2 = 8; - // Nested iteration; just make sure the level is higher - // and that it has its own counter declared in scope. - TAG_ITER_SECTORS(1, tag2, sec) + // Nested iteration. + TAG_ITER_SECTORS(tag2, sec) { sector_t *sector = sectors + sec; From cf389179e85536d05fa4545004477f784181adc1 Mon Sep 17 00:00:00 2001 From: lachwright Date: Mon, 15 Feb 2021 01:11:03 +1100 Subject: [PATCH 071/241] Rollout rock improvements: - No longer struggles to start to accelerating at certain angles - Carrying a player onto a rollout rock no longer leaves them in their ride state - Changed dispoffset might alleviate some sorting issues - Changes the player's camera angle when sprung horizontally - Works better in reverse gravity --- src/info.c | 2 +- src/p_enemy.c | 14 ++++++++++---- src/p_map.c | 7 +++++++ src/p_user.c | 9 ++++++--- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/info.c b/src/info.c index ee836a372..6fbf71432 100644 --- a/src/info.c +++ b/src/info.c @@ -13481,7 +13481,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 32*FRACUNIT, // speed 30*FRACUNIT, // radius 60*FRACUNIT, // height - 0, // display offset + -1, // display offset 100, // mass 0, // damage sfx_None, // activesound diff --git a/src/p_enemy.c b/src/p_enemy.c index 3e7f52a3f..294615b88 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -14319,6 +14319,14 @@ void A_RolloutRock(mobj_t *actor) if (LUA_CallAction(A_ROLLOUTROCK, actor)) return; + if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) + actor->flags |= MF_PUSHABLE; + else + { + actor->flags2 = (actor->flags2 & ~MF2_OBJECTFLIP) | (actor->tracer->flags2 & MF2_OBJECTFLIP); + actor->eflags = (actor->eflags & ~MFE_VERTICALFLIP) | (actor->tracer->eflags & MFE_VERTICALFLIP); + } + actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves if (actor->eflags & MFE_JUSTHITFLOOR) @@ -14357,7 +14365,8 @@ void A_RolloutRock(mobj_t *actor) speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling - if (speed < actor->scale >> 1) // stop moving if speed is insignificant + if (((actor->flags & MF_PUSHABLE) || !(actor->flags2 & MF2_STRONGBOX)) + && speed < actor->scale) // stop moving if speed is insignificant { actor->momx = 0; actor->momy = 0; @@ -14377,9 +14386,6 @@ void A_RolloutRock(mobj_t *actor) actor->frame = actor->reactiontime % maxframes; // set frame - if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) - actor->flags |= MF_PUSHABLE; - if (!(actor->flags & MF_PUSHABLE) || (actor->movecount != 1)) // if being ridden or haven't moved, don't disappear actor->fuse = actor->info->painchance; else if (actor->fuse < 2*TICRATE) diff --git a/src/p_map.c b/src/p_map.c index a1cad524e..630d28200 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -429,6 +429,13 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) else P_SetPlayerMobjState(object, S_PLAY_FALL); } + else if (horizspeed + && object->tracer + && object->tracer->player + && object->tracer->player->powers[pw_carry] != CR_NONE + && object->tracer->tracer == object + && (!demoplayback || P_ControlStyle(object->tracer->player) == CS_LMAOGALOG)) + P_SetPlayerAngle(object->tracer->player, spring->angle); object->standingslope = NULL; // And again. diff --git a/src/p_user.c b/src/p_user.c index a9e1fe9a2..ca1dfd478 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -12608,14 +12608,14 @@ void P_PlayerAfterThink(player_t *player) if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > player->mo->radius) player->powers[pw_carry] = CR_NONE; - if (player->powers[pw_carry] != CR_NONE) + if (player->powers[pw_carry] == CR_PLAYER) { if (player->mo->state-states != S_PLAY_RIDE) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER)) tails->player->powers[pw_tailsfly] = 0; } - else + else if (player->powers[pw_carry] == CR_NONE) P_SetTarget(&player->mo->tracer, NULL); if (player-players == consoleplayer && botingame) @@ -12718,9 +12718,12 @@ void P_PlayerAfterThink(player_t *player) if (player->cmd.forwardmove || player->cmd.sidemove) { + rock->flags2 |= MF2_STRONGBOX; // signifies the rock should not slow to a halt rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); P_Thrust(rock, rock->movedir, rock->scale >> 1); } + else + rock->flags2 &= ~MF2_STRONGBOX; mo->momx = rock->momx; mo->momy = rock->momy; @@ -12736,7 +12739,7 @@ void P_PlayerAfterThink(player_t *player) mo->tics = walktics; } - P_TeleportMove(player->mo, rock->x, rock->y, rock->z + rock->height); + P_TeleportMove(player->mo, rock->x, rock->y, rock->z + ((mo->eflags & MFE_VERTICALFLIP) ? -mo->height : rock->height)); break; } case CR_PTERABYTE: // being carried by a Pterabyte From 998d06569880aa79e310484d7baa7fdd638d9083 Mon Sep 17 00:00:00 2001 From: sphere Date: Wed, 17 Feb 2021 16:06:02 +0100 Subject: [PATCH 072/241] Add more actions for slope copying & update the ZB config. --- extras/conf/SRB2-22.cfg | 78 +++++++++++++++++++++++++++++++++++++++++ src/p_setup.c | 28 +++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index a0d40cdf0..b7ba56ba7 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3059,6 +3059,84 @@ linedeftypes slopeargs = 3; } + 723 + { + title = "Copy Backside Floor Slope from Line Tag"; + prefix = "(720)"; + slope = "copy"; + slopeargs = 4; + } + + 724 + { + title = "Copy Backside Ceiling Slope from Line Tag"; + prefix = "(721)"; + slope = "copy"; + slopeargs = 8; + } + + 725 + { + title = "Copy Backside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + slope = "copy"; + slopeargs = 12; + } + + 730 + { + title = "Copy Frontside Floor Slope to Backside"; + prefix = "(730)"; + slope = "copy"; + slopeargs = 1; + //copyslopeargs = 1; uncomment when ZB updates + } + + 731 + { + title = "Copy Frontside Ceiling Slope to Backside"; + prefix = "(731)"; + slope = "copy"; + slopeargs = 2; + //copyslopeargs = 4; uncomment when ZB updates + } + + 732 + { + title = "Copy Frontside Floor and Ceiling Slope to Backside"; + prefix = "(732)"; + slope = "copy"; + slopeargs = 3; + //copyslopeargs = 5; uncomment when ZB updates + } + + 733 + { + title = "Copy Backside Floor Slope to Frontside"; + prefix = "(730)"; + slope = "copy"; + slopeargs = 1; + //copyslopeargs = 2; uncomment when ZB updates + } + + 734 + { + title = "Copy Backside Ceiling Slope to Frontside"; + prefix = "(731)"; + slope = "copy"; + slopeargs = 2; + //copyslopeargs = 8; uncomment when ZB updates + } + + 735 + { + title = "Copy Backside Floor and Ceiling Slope to Frontside"; + prefix = "(732)"; + slope = "copy"; + slopeargs = 3; + //copyslopeargs = 10; uncomment when ZB updates + } + 799 { title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; diff --git a/src/p_setup.c b/src/p_setup.c index 66243fb0e..1c70c01e6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3141,6 +3141,34 @@ static void P_ConvertBinaryMap(void) lines[i].args[1] = tag; lines[i].special = 720; break; + case 723: //Copy back side floor slope + case 724: //Copy back side ceiling slope + case 725: //Copy back side floor and ceiling slope + if (lines[i].special != 724) + lines[i].args[2] = tag; + if (lines[i].special != 723) + lines[i].args[3] = tag; + lines[i].special = 720; + break; + case 730: //Copy front side floor slope to back side + case 731: //Copy front side ceiling slope to back side + case 732: //Copy front side floor and ceiling slope to back side + if (lines[i].special != 731) + lines[i].args[4] |= TMSC_FRONTTOBACKFLOOR; + if (lines[i].special != 730) + lines[i].args[4] |= TMSC_FRONTTOBACKCEILING; + lines[i].special = 720; + break; + case 733: //Copy back side floor slope to front side + case 734: //Copy back side ceiling slope to front side + case 735: //Copy back side floor and ceiling slope to front side + if (lines[i].special != 734) + lines[i].args[4] |= TMSC_BACKTOFRONTFLOOR; + if (lines[i].special != 733) + lines[i].args[4] |= TMSC_BACKTOFRONTCEILING; + lines[i].special = 720; + break; + case 900: //Translucent wall (10%) case 901: //Translucent wall (20%) case 902: //Translucent wall (30%) From 12205314bcc8e973e22e1bbbfcccb8f34c304629 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 21 Feb 2021 19:32:00 -0600 Subject: [PATCH 073/241] Check against null tmpusher source before attempting to push a thing. --- src/p_spec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 226e58d15..9886495db 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -8458,6 +8458,9 @@ static inline boolean PIT_PushThing(mobj_t *thing) if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG) return false; + if (!tmpusher->source) + return false; + // Allow this to affect pushable objects at some point? if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->powers[pw_carry] == CR_NIGHTSMODE)) { From d305952119aff3f84eee15697c4e2af6b32a1140 Mon Sep 17 00:00:00 2001 From: sphere Date: Wed, 24 Feb 2021 10:30:48 +0100 Subject: [PATCH 074/241] Update ZB config: at this rate, ZB will update before this gets merged. --- extras/conf/SRB2-22.cfg | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index b7ba56ba7..246ef9b64 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3088,8 +3088,7 @@ linedeftypes title = "Copy Frontside Floor Slope to Backside"; prefix = "(730)"; slope = "copy"; - slopeargs = 1; - //copyslopeargs = 1; uncomment when ZB updates + copyslopeargs = 1; } 731 @@ -3097,8 +3096,7 @@ linedeftypes title = "Copy Frontside Ceiling Slope to Backside"; prefix = "(731)"; slope = "copy"; - slopeargs = 2; - //copyslopeargs = 4; uncomment when ZB updates + copyslopeargs = 4; } 732 @@ -3106,8 +3104,7 @@ linedeftypes title = "Copy Frontside Floor and Ceiling Slope to Backside"; prefix = "(732)"; slope = "copy"; - slopeargs = 3; - //copyslopeargs = 5; uncomment when ZB updates + copyslopeargs = 5; } 733 @@ -3115,8 +3112,7 @@ linedeftypes title = "Copy Backside Floor Slope to Frontside"; prefix = "(730)"; slope = "copy"; - slopeargs = 1; - //copyslopeargs = 2; uncomment when ZB updates + copyslopeargs = 2; } 734 @@ -3124,8 +3120,7 @@ linedeftypes title = "Copy Backside Ceiling Slope to Frontside"; prefix = "(731)"; slope = "copy"; - slopeargs = 2; - //copyslopeargs = 8; uncomment when ZB updates + copyslopeargs = 8; } 735 @@ -3133,8 +3128,7 @@ linedeftypes title = "Copy Backside Floor and Ceiling Slope to Frontside"; prefix = "(732)"; slope = "copy"; - slopeargs = 3; - //copyslopeargs = 10; uncomment when ZB updates + copyslopeargs = 10; } 799 From 0c22fecafa04ad263cfa411833835ca6415b2c4b Mon Sep 17 00:00:00 2001 From: sphere Date: Wed, 17 Mar 2021 12:42:18 +0100 Subject: [PATCH 075/241] Make horizontal springs above floors put the player in spring state. --- src/p_map.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index a1cad524e..214d2096e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -419,10 +419,10 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } else if (object->player->dashmode >= DASHMODE_THRESHOLD) P_SetPlayerMobjState(object, S_PLAY_DASH); - else if (P_IsObjectOnGround(object) && horizspeed >= FixedMul(object->player->runspeed, object->scale)) - P_SetPlayerMobjState(object, S_PLAY_RUN); + else if (P_IsObjectOnGround(object)) + P_SetPlayerMobjState(object, (horizspeed >= FixedMul(object->player->runspeed, object->scale)) ? S_PLAY_RUN : S_PLAY_WALK); else - P_SetPlayerMobjState(object, S_PLAY_WALK); + P_SetPlayerMobjState(object, (object->momz > 0) ? S_PLAY_SPRING : S_PLAY_FALL); } else if (P_MobjFlip(object)*vertispeed > 0) P_SetPlayerMobjState(object, S_PLAY_SPRING); From 08937f892a4eec9c6cdf7c0c3c1ce255941c8ba6 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 23 Mar 2021 01:18:28 -0300 Subject: [PATCH 076/241] Allocate a buffer for non-RGBA to RGBA texture conversions. UpdateTexture will I_Error (from AllocTextureBuffer) if the allocation fails. --- src/hardware/r_opengl/r_opengl.c | 124 ++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 42 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 6967bab74..7c77c27ea 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -131,7 +131,6 @@ static const GLfloat byte2float[256] = { // -----------------+ // GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, // : else do nothing -// Returns : // -----------------+ #ifdef DEBUG_TO_FILE @@ -159,8 +158,6 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) // -----------------+ // GL_MSG_Warning : Raises a warning. -// : -// Returns : // -----------------+ static void GL_MSG_Warning(const char *format, ...) @@ -184,8 +181,6 @@ static void GL_MSG_Warning(const char *format, ...) // -----------------+ // GL_MSG_Error : Raises an error. -// : -// Returns : // -----------------+ static void GL_MSG_Error(const char *format, ...) @@ -207,6 +202,32 @@ static void GL_MSG_Error(const char *format, ...) #endif } +// ----------------------+ +// GetTextureFormatName : Returns the corresponding texture format string from the texture format enumeration. +// ----------------------+ +static const char *GetTextureFormatName(INT32 format) +{ + static char num[12]; + + switch (format) + { + case GL_TEXFMT_P_8: return "GL_TEXFMT_P_8"; + case GL_TEXFMT_AP_88: return "GL_TEXFMT_AP_88"; + case GL_TEXFMT_RGBA: return "GL_TEXFMT_RGBA"; + case GL_TEXFMT_ALPHA_8: return "GL_TEXFMT_ALPHA_8"; + case GL_TEXFMT_INTENSITY_8: return "GL_TEXFMT_INTENSITY_8"; + case GL_TEXFMT_ALPHA_INTENSITY_88: return "GL_TEXFMT_ALPHA_INTENSITY_88"; + default: break; + } + + // If the texture format is not known (due to it being invalid), + // return a string containing the format index instead. + format = INT32_MIN; + snprintf(num, sizeof(num), "%d", format); + + return num; +} + #ifdef STATIC_OPENGL /* 1.0 functions */ /* Miscellaneous */ @@ -1375,7 +1396,6 @@ INT32 isExtAvailable(const char *extension, const GLubyte *start) // -----------------+ // Init : Initialise the OpenGL interface API -// Returns : // -----------------+ EXPORT boolean HWRAPI(Init) (void) { @@ -1737,37 +1757,59 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) CurrentPolyFlags = PolyFlags; } +// -------------------+ +// AllocTextureBuffer : Allocates memory for converting a non-RGBA texture into an RGBA texture. +// -------------------+ +static RGBA_t *AllocTextureBuffer(GLMipmap_t *pTexInfo) +{ + size_t len = (pTexInfo->width * pTexInfo->height); + RGBA_t *tex = calloc(len, sizeof(RGBA_t)); + + if (tex == NULL) + I_Error("AllocTextureBuffer: out of memory allocating %s bytes for texture %d, format %s", + sizeu1(len * sizeof(RGBA_t)), pTexInfo->downloaded, GetTextureFormatName(pTexInfo->format)); + + return tex; +} + +// ------------------+ +// FreeTextureBuffer : Frees memory allocated by AllocTextureBuffer. +// ------------------+ +static void FreeTextureBuffer(RGBA_t *tex) +{ + if (tex) + free(tex); +} + // -----------------+ -// UpdateTexture : Updates the texture data. +// UpdateTexture : Updates texture data. // -----------------+ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) { - // Download a mipmap - boolean updatemipmap = true; - static RGBA_t tex[2048*2048]; - const GLvoid *ptex = tex; - INT32 w, h; - GLuint texnum = 0; + // Upload a texture + GLuint num = pTexInfo->downloaded; + boolean update = true; - if (!pTexInfo->downloaded) + INT32 w = pTexInfo->width, h = pTexInfo->height; + INT32 i, j; + + const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; + const GLvoid *ptex = NULL; + RGBA_t *tex = NULL; + + // Generate a new texture name. + if (!num) { - pglGenTextures(1, &texnum); - pTexInfo->downloaded = texnum; - updatemipmap = false; + pglGenTextures(1, &num); + pTexInfo->downloaded = num; + update = false; } - else - texnum = pTexInfo->downloaded; - //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->data); + //GL_DBG_Printf("UpdateTexture %d %x\n", (INT32)num, pImgData); - w = pTexInfo->width; - h = pTexInfo->height; - - if ((pTexInfo->format == GL_TEXFMT_P_8) || - (pTexInfo->format == GL_TEXFMT_AP_88)) + if ((pTexInfo->format == GL_TEXFMT_P_8) || (pTexInfo->format == GL_TEXFMT_AP_88)) { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; - INT32 i, j; + ptex = tex = AllocTextureBuffer(pTexInfo); for (j = 0; j < h; j++) { @@ -1798,20 +1840,17 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) tex[w*j+i].s.alpha = *pImgData; pImgData++; } - } } } else if (pTexInfo->format == GL_TEXFMT_RGBA) { - // corona test : passed as ARGB 8888, which is not in glide formats - // Hurdler: not used for coronas anymore, just for dynamic lighting - ptex = pTexInfo->data; + // Directly upload the texture data without any kind of conversion. + ptex = pImgData; } else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88) { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; - INT32 i, j; + ptex = tex = AllocTextureBuffer(pTexInfo); for (j = 0; j < h; j++) { @@ -1828,8 +1867,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; - INT32 i, j; + ptex = tex = AllocTextureBuffer(pTexInfo); for (j = 0; j < h; j++) { @@ -1844,11 +1882,10 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } } else - GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->format); + GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format); - // the texture number was already generated by pglGenTextures - pglBindTexture(GL_TEXTURE_2D, texnum); - tex_downloaded = texnum; + pglBindTexture(GL_TEXTURE_2D, num); + tex_downloaded = num; // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues if (pTexInfo->flags & TF_TRANSPARENT) @@ -1877,7 +1914,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else { - if (updatemipmap) + if (update) pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); @@ -1898,7 +1935,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else { - if (updatemipmap) + if (update) pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); @@ -1918,13 +1955,16 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else { - if (updatemipmap) + if (update) pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); } } + // Free the texture buffer + FreeTextureBuffer(tex); + if (pTexInfo->flags & TF_WRAPX) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); else From 6267abac8add71a70409fd9987630c44fc56befd Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Thu, 25 Mar 2021 12:43:30 -0500 Subject: [PATCH 077/241] Fix console text bleeding --- src/console.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/console.c b/src/console.c index f3b0aa603..2d95e10b8 100644 --- a/src/console.c +++ b/src/console.c @@ -1652,6 +1652,7 @@ static void CON_DrawHudlines(void) { charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; p++; + c++; } if (*p < HU_FONTSTART) ;//charwidth = 4 * con_scalefactor; @@ -1774,6 +1775,7 @@ static void CON_DrawConsole(void) { charflags = (*p & 0x7f) << V_CHARCOLORSHIFT; p++; + c++; } V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } From 428ae3127e76753aa47c79b07867560bf9145c60 Mon Sep 17 00:00:00 2001 From: Mari0shi06 Date: Sun, 28 Mar 2021 17:12:58 -0400 Subject: [PATCH 078/241] Change Raspberry's chat colormap to V_ROSYMAP --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index ee836a372..19a477e5b 100644 --- a/src/info.c +++ b/src/info.c @@ -21761,7 +21761,7 @@ 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 {"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 {"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_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY + {"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 {"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 From 424f67a74b5aff5083c174a81a21664a1a63e6dc Mon Sep 17 00:00:00 2001 From: Mari0shi06 Date: Sun, 28 Mar 2021 21:19:26 +0000 Subject: [PATCH 079/241] Revert "Change Raspberry's chat colormap to V_ROSYMAP" This reverts commit 428ae3127e76753aa47c79b07867560bf9145c60 --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 19a477e5b..ee836a372 100644 --- a/src/info.c +++ b/src/info.c @@ -21761,7 +21761,7 @@ 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 {"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 {"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 + {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY {"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 From 192fa5cb4b2d13ac6e1a026c3a190cece32201fc Mon Sep 17 00:00:00 2001 From: Mari0shi06 Date: Sun, 28 Mar 2021 17:26:41 -0400 Subject: [PATCH 080/241] Change Raspberry's chat color to V_ROSYMAP --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index ee836a372..2b577c07e 100644 --- a/src/info.c +++ b/src/info.c @@ -21761,7 +21761,7 @@ 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 {"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 {"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_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY + {"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 {"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 From 715a3661b5e2cdc8ae3ef8dd5374427031d9da4b Mon Sep 17 00:00:00 2001 From: Mari0shi06 Date: Sun, 28 Mar 2021 21:27:46 +0000 Subject: [PATCH 081/241] Revert "Change Raspberry's chat color to V_ROSYMAP" This reverts commit 192fa5cb4b2d13ac6e1a026c3a190cece32201fc --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 2b577c07e..ee836a372 100644 --- a/src/info.c +++ b/src/info.c @@ -21761,7 +21761,7 @@ 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 {"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 {"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 + {"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY {"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 From 29704e141b9bc2b265a58f41a2ff1c7a293b3ad7 Mon Sep 17 00:00:00 2001 From: Mari0shi06 Date: Sun, 28 Mar 2021 17:29:24 -0400 Subject: [PATCH 082/241] Change Raspberry's chat colormap to V_ROSYMAP --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index ee836a372..2b577c07e 100644 --- a/src/info.c +++ b/src/info.c @@ -21761,7 +21761,7 @@ 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 {"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 {"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_MAGENTAMAP, true}, // SKINCOLOR_RASPBERRY + {"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 {"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 From 6bf76602ed442a6a9d3f141896c0f2dd0a0bf2a8 Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Tue, 23 Mar 2021 00:02:49 -0500 Subject: [PATCH 083/241] Refactor mouse --- src/d_main.c | 9 +++++++++ src/g_game.c | 31 ++++++++++++------------------- src/g_input.c | 34 ++++++++++++++++++++++++---------- src/g_input.h | 17 ++++++++++++++--- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 23a2c0133..2a4e9ab81 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -175,6 +175,10 @@ void D_ProcessEvents(void) boolean eaten; + // Reset possibly stale mouse info + G_SetMouseData(0, 0, 1); + G_SetMouseData(0, 0, 2); + for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { ev = &events[eventtail]; @@ -219,6 +223,11 @@ void D_ProcessEvents(void) G_Responder(ev); } + + if (mouse.rdx || mouse.rdy) + G_SetMouseData(mouse.rdx, mouse.rdy, 1); + if (mouse2.rdx || mouse2.rdy) + G_SetMouseData(mouse2.rdx, mouse2.rdy, 2); } // diff --git a/src/g_game.c b/src/g_game.c index 2b304b4fd..e46a7f816 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1094,7 +1094,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0; INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, turnmultiplier, mousemove; controlstyle_e controlstyle = G_ControlStyle(ssplayer); - INT32 *mx; INT32 *my; INT32 *mly; + mouse_t *m = &mouse; static INT32 turnheld[2]; // for accelerative turning static boolean keyboard_look[2]; // true if lookup/down using keyboard @@ -1117,9 +1117,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) invertmouse = cv_invertmouse.value; turnmultiplier = cv_cam_turnmultiplier.value; mousemove = cv_mousemove.value; - mx = &mousex; - my = &mousey; - mly = &mlooky; G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver } else @@ -1131,9 +1128,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) invertmouse = cv_invertmouse2.value; turnmultiplier = cv_cam2_turnmultiplier.value; mousemove = cv_mousemove2.value; - mx = &mouse2x; - my = &mouse2y; - mly = &mlook2y; + m = &mouse2; G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver } @@ -1476,7 +1471,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) keyboard_look[forplayer] = false; // looking up/down - *myaiming += (*mly<<19)*player_invert*screen_invert; + *myaiming += (m->mlookdy<<19)*player_invert*screen_invert; } if (analogjoystickmove && joyaiming[forplayer] && lookjoystickvector.yaxis != 0 && configlookaxis != 0) @@ -1510,24 +1505,22 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } if (!mouseaiming && mousemove) - forward += *my; + forward += m->dy; if ((!demoplayback && (player->pflags & PF_SLIDING))) // Analog for mouse - side += *mx*2; + side += m->dx*2; else if (controlstyle == CS_LMAOGALOG) { - if (*mx) + if (m->dx) { - if (*mx > 0) + if (m->dx > 0) cmd->buttons |= BT_CAMRIGHT; else cmd->buttons |= BT_CAMLEFT; } } else - cmd->angleturn = (INT16)(cmd->angleturn - (*mx*8)); - - *mx = *my = *mly = 0; + cmd->angleturn = (INT16)(cmd->angleturn - (m->dx*8)); if (forward > MAXPLMOVE) forward = MAXPLMOVE; @@ -1873,8 +1866,8 @@ void G_DoLoadLevel(boolean resetplayer) joyxmove[i] = joyymove[i] = 0; joy2xmove[i] = joy2ymove[i] = 0; } - mousex = mousey = 0; - mouse2x = mouse2y = 0; + G_SetMouseData(0, 0, 1); + G_SetMouseData(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); @@ -3095,8 +3088,8 @@ void G_DoReborn(INT32 playernum) joyxmove[i] = joyymove[i] = 0; joy2xmove[i] = joy2ymove[i] = 0; } - mousex = mousey = 0; - mouse2x = mouse2y = 0; + G_SetMouseData(0, 0, 1); + G_SetMouseData(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); diff --git a/src/g_input.c b/src/g_input.c index d3c21e774..049a4d82c 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -31,10 +31,8 @@ consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL); consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL); -INT32 mousex, mousey; -INT32 mlooky; // like mousey but with a custom sensitivity for mlook - -INT32 mouse2x, mouse2y, mlook2y; +mouse_t mouse; +mouse_t mouse2; // joystick values are repeated INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET]; @@ -142,9 +140,8 @@ void G_MapEventsToControls(event_t *ev) case ev_mouse: // buttons are virtual keys if (menuactive || CON_Ready() || chat_on) break; - mousex = (INT32)(ev->data2*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f)); - mousey = (INT32)(ev->data3*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f)); - mlooky = (INT32)(ev->data3*((cv_mouseysens.value*cv_mousesens.value)/110.0f + 0.1f)); + mouse.rdx = ev->data2; + mouse.rdy = ev->data3; break; case ev_joystick: // buttons are virtual keys @@ -166,9 +163,8 @@ void G_MapEventsToControls(event_t *ev) case ev_mouse2: // buttons are virtual keys if (menuactive || CON_Ready() || chat_on) break; - mouse2x = (INT32)(ev->data2*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); - mouse2y = (INT32)(ev->data3*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); - mlook2y = (INT32)(ev->data3*((cv_mouseysens2.value*cv_mousesens2.value)/110.0f + 0.1f)); + mouse2.rdx = ev->data2; + mouse2.rdy = ev->data3; break; default: @@ -1073,3 +1069,21 @@ void Command_Setcontrol2_f(void) setcontrol(gamecontrolbis); } + +void G_SetMouseData(INT32 realdx, INT32 realdy, UINT8 ssplayer) +{ + mouse_t *m = ssplayer == 1 ? &mouse : &mouse2; + consvar_t *cvsens, *cvysens; + + if (!realdx && !realdy) { + memset(m, 0, sizeof(*m)); + return; + } + cvsens = ssplayer == 1 ? &cv_mousesens : &cv_mousesens2; + cvysens = ssplayer == 1 ? &cv_mouseysens : &cv_mouseysens2; + m->rdx = realdx; + m->rdy = realdy; + m->dx = (INT32)(m->rdx*((cvsens->value*cvsens->value)/110.0f + 0.1f)); + m->dy = (INT32)(m->rdy*((cvsens->value*cvsens->value)/110.0f + 0.1f)); + m->mlookdy = (INT32)(m->rdy*((cvysens->value*cvsens->value)/110.0f + 0.1f)); +} diff --git a/src/g_input.h b/src/g_input.h index ce38f6ba9..5912bfdc7 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -116,9 +116,17 @@ extern consvar_t cv_mousesens, cv_mouseysens; extern consvar_t cv_mousesens2, cv_mouseysens2; extern consvar_t cv_controlperkey; -extern INT32 mousex, mousey; -extern INT32 mlooky; //mousey with mlookSensitivity -extern INT32 mouse2x, mouse2y, mlook2y; +typedef struct +{ + INT32 dx; // deltas with mousemove sensitivity + INT32 dy; + INT32 mlookdy; // dy with mouselook sensitivity + INT32 rdx; // deltas without sensitivity + INT32 rdy; +} mouse_t; + +extern mouse_t mouse; +extern mouse_t mouse2; extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET]; @@ -175,4 +183,7 @@ void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const I void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]); INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify); +// sets the members of a mouse_t given position deltas +void G_SetMouseData(INT32 realdx, INT32 realdy, UINT8 ssplayer); + #endif From 3faa98cf4a824ac21a7fa8eae2292f2c6e6d917c Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Wed, 24 Mar 2021 03:54:11 -0500 Subject: [PATCH 084/241] Expose inputs to Lua --- src/CMakeLists.txt | 1 + src/blua/Makefile.cfg | 3 +- src/console.c | 4 +- src/d_main.c | 17 +++ src/deh_tables.c | 59 ++++++++ src/g_game.c | 84 +++++------ src/g_game.h | 20 +++ src/g_input.c | 16 +- src/g_input.h | 4 +- src/lua_baselib.c | 2 + src/lua_hook.h | 4 + src/lua_hooklib.c | 72 +++++++++ src/lua_inputlib.c | 214 +++++++++++++++++++++++++++ src/lua_libs.h | 3 + src/lua_script.c | 21 ++- src/m_menu.c | 4 +- src/sdl/Srb2SDL-vc10.vcxproj | 1 + src/sdl/Srb2SDL-vc10.vcxproj.filters | 3 + 18 files changed, 471 insertions(+), 61 deletions(-) create mode 100644 src/lua_inputlib.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 87a0499b6..77b5a0e4f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -281,6 +281,7 @@ set(SRB2_LUA_SOURCES lua_mobjlib.c lua_playerlib.c lua_polyobjlib.c + lua_inputlib.c lua_script.c lua_skinlib.c lua_thinkerlib.c diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index 3a2962e65..4536628ba 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -50,4 +50,5 @@ OBJS:=$(OBJS) \ $(OBJDIR)/lua_taglib.o \ $(OBJDIR)/lua_polyobjlib.o \ $(OBJDIR)/lua_blockmaplib.o \ - $(OBJDIR)/lua_hudlib.o + $(OBJDIR)/lua_hudlib.o \ + $(OBJDIR)/lua_inputlib.o diff --git a/src/console.c b/src/console.c index 121605b10..3b29e9c4f 100644 --- a/src/console.c +++ b/src/console.c @@ -221,7 +221,7 @@ static void CONS_Bind_f(void) for (key = 0; key < NUMINPUTS; key++) if (bindtable[key]) { - CONS_Printf("%s : \"%s\"\n", G_KeynumToString(key), bindtable[key]); + CONS_Printf("%s : \"%s\"\n", G_KeyNumToString(key), bindtable[key]); na = 1; } if (!na) @@ -229,7 +229,7 @@ static void CONS_Bind_f(void) return; } - key = G_KeyStringtoNum(COM_Argv(1)); + key = G_KeyStringToNum(COM_Argv(1)); if (key <= 0 || key >= NUMINPUTS) { CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n")); diff --git a/src/d_main.c b/src/d_main.c index 2a4e9ab81..d60a6cf47 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -181,6 +181,8 @@ void D_ProcessEvents(void) for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { + boolean hooked = false; + ev = &events[eventtail]; // Screenshots over everything so that they can be taken anywhere. @@ -193,6 +195,12 @@ void D_ProcessEvents(void) continue; } + if (!CON_Ready() && !menuactive) { + if (G_LuaResponder(ev)) + continue; + hooked = true; + } + // Menu input #ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); @@ -207,6 +215,12 @@ void D_ProcessEvents(void) if (eaten) continue; // menu ate the event + if (!hooked && !CON_Ready()) { + if (G_LuaResponder(ev)) + continue; + hooked = true; + } + // console input #ifdef HAVE_THREADS I_lock_mutex(&con_mutex); @@ -221,6 +235,9 @@ void D_ProcessEvents(void) if (eaten) continue; // ate the event + if (!hooked && G_LuaResponder(ev)) + continue; + G_Responder(ev); } diff --git a/src/deh_tables.c b/src/deh_tables.c index dd6d7d69f..7bfe723da 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -22,6 +22,8 @@ #include "v_video.h" // video flags (for lua) #include "i_sound.h" // musictype_t (for lua) #include "g_state.h" // gamestate_t (for lua) +#include "g_game.h" // Joystick axes (for lua) +#include "g_input.h" // Game controls (for lua) #include "deh_tables.h" @@ -5455,6 +5457,63 @@ struct int_const_s const INT_CONST[] = { {"GS_DEDICATEDSERVER",GS_DEDICATEDSERVER}, {"GS_WAITINGPLAYERS",GS_WAITINGPLAYERS}, + // Joystick axes + {"JA_NONE",JA_NONE}, + {"JA_TURN",JA_TURN}, + {"JA_MOVE",JA_MOVE}, + {"JA_LOOK",JA_LOOK}, + {"JA_STRAFE",JA_STRAFE}, + {"JA_DIGITAL",JA_DIGITAL}, + {"JA_JUMP",JA_JUMP}, + {"JA_SPIN",JA_SPIN}, + {"JA_FIRE",JA_FIRE}, + {"JA_FIRENORMAL",JA_FIRENORMAL}, + + // Game controls + {"gc_null",gc_null}, + {"gc_forward",gc_forward}, + {"gc_backward",gc_backward}, + {"gc_strafeleft",gc_strafeleft}, + {"gc_straferight",gc_straferight}, + {"gc_turnleft",gc_turnleft}, + {"gc_turnright",gc_turnright}, + {"gc_weaponnext",gc_weaponnext}, + {"gc_weaponprev",gc_weaponprev}, + {"gc_wepslot1",gc_wepslot1}, + {"gc_wepslot2",gc_wepslot2}, + {"gc_wepslot3",gc_wepslot3}, + {"gc_wepslot4",gc_wepslot4}, + {"gc_wepslot5",gc_wepslot5}, + {"gc_wepslot6",gc_wepslot6}, + {"gc_wepslot7",gc_wepslot7}, + {"gc_wepslot8",gc_wepslot8}, + {"gc_wepslot9",gc_wepslot9}, + {"gc_wepslot10",gc_wepslot10}, + {"gc_fire",gc_fire}, + {"gc_firenormal",gc_firenormal}, + {"gc_tossflag",gc_tossflag}, + {"gc_spin",gc_spin}, + {"gc_camtoggle",gc_camtoggle}, + {"gc_camreset",gc_camreset}, + {"gc_lookup",gc_lookup}, + {"gc_lookdown",gc_lookdown}, + {"gc_centerview",gc_centerview}, + {"gc_mouseaiming",gc_mouseaiming}, + {"gc_talkkey",gc_talkkey}, + {"gc_teamkey",gc_teamkey}, + {"gc_scores",gc_scores}, + {"gc_jump",gc_jump}, + {"gc_console",gc_console}, + {"gc_pause",gc_pause}, + {"gc_systemmenu",gc_systemmenu}, + {"gc_screenshot",gc_screenshot}, + {"gc_recordgif",gc_recordgif}, + {"gc_viewpoint",gc_viewpoint}, + {"gc_custom1",gc_custom1}, + {"gc_custom2",gc_custom2}, + {"gc_custom3",gc_custom3}, + {"num_gamecontrols",num_gamecontrols}, + {NULL,0} }; diff --git a/src/g_game.c b/src/g_game.c index e46a7f816..823ea7c56 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -406,22 +406,6 @@ consvar_t cv_cam_lockonboss[2] = { CVAR_INIT ("cam2_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL), }; -typedef enum -{ - AXISNONE = 0, - AXISTURN, - AXISMOVE, - AXISLOOK, - AXISSTRAFE, - - AXISDIGITAL, // axes below this use digital deadzone - - AXISJUMP, - AXISSPIN, - AXISFIRE, - AXISFIRENORMAL, -} axis_input_e; - consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "X-Rudder", CV_SAVE, joyaxis_cons_t, NULL); 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); @@ -841,7 +825,7 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming) return (INT16)((*aiming)>>16); } -static INT32 JoyAxis(axis_input_e axissel) +INT32 JoyAxis(joyaxis_e axissel) { INT32 retaxis; INT32 axisval; @@ -850,28 +834,28 @@ static INT32 JoyAxis(axis_input_e axissel) //find what axis to get switch (axissel) { - case AXISTURN: + case JA_TURN: axisval = cv_turnaxis.value; break; - case AXISMOVE: + case JA_MOVE: axisval = cv_moveaxis.value; break; - case AXISLOOK: + case JA_LOOK: axisval = cv_lookaxis.value; break; - case AXISSTRAFE: + case JA_STRAFE: axisval = cv_sideaxis.value; break; - case AXISJUMP: + case JA_JUMP: axisval = cv_jumpaxis.value; break; - case AXISSPIN: + case JA_SPIN: axisval = cv_spinaxis.value; break; - case AXISFIRE: + case JA_FIRE: axisval = cv_fireaxis.value; break; - case AXISFIRENORMAL: + case JA_FIRENORMAL: axisval = cv_firenaxis.value; break; default: @@ -903,7 +887,7 @@ static INT32 JoyAxis(axis_input_e axissel) if (retaxis > (+JOYAXISRANGE)) retaxis = +JOYAXISRANGE; - if (!Joystick.bGamepadStyle && axissel > AXISDIGITAL) + if (!Joystick.bGamepadStyle && axissel > JA_DIGITAL) { const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) @@ -914,7 +898,7 @@ static INT32 JoyAxis(axis_input_e axissel) return retaxis; } -static INT32 Joy2Axis(axis_input_e axissel) +INT32 Joy2Axis(joyaxis_e axissel) { INT32 retaxis; INT32 axisval; @@ -923,28 +907,28 @@ static INT32 Joy2Axis(axis_input_e axissel) //find what axis to get switch (axissel) { - case AXISTURN: + case JA_TURN: axisval = cv_turnaxis2.value; break; - case AXISMOVE: + case JA_MOVE: axisval = cv_moveaxis2.value; break; - case AXISLOOK: + case JA_LOOK: axisval = cv_lookaxis2.value; break; - case AXISSTRAFE: + case JA_STRAFE: axisval = cv_sideaxis2.value; break; - case AXISJUMP: + case JA_JUMP: axisval = cv_jumpaxis2.value; break; - case AXISSPIN: + case JA_SPIN: axisval = cv_spinaxis2.value; break; - case AXISFIRE: + case JA_FIRE: axisval = cv_fireaxis2.value; break; - case AXISFIRENORMAL: + case JA_FIRENORMAL: axisval = cv_firenaxis2.value; break; default: @@ -978,7 +962,7 @@ static INT32 Joy2Axis(axis_input_e axissel) if (retaxis > (+JOYAXISRANGE)) retaxis = +JOYAXISRANGE; - if (!Joystick2.bGamepadStyle && axissel > AXISDIGITAL) + if (!Joystick2.bGamepadStyle && axissel > JA_DIGITAL) { const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone2.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) @@ -1174,10 +1158,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) *myaiming = 0; joyaiming[forplayer] = thisjoyaiming; - turnaxis = PlayerJoyAxis(ssplayer, AXISTURN); + turnaxis = PlayerJoyAxis(ssplayer, JA_TURN); if (strafeisturn) - turnaxis += PlayerJoyAxis(ssplayer, AXISSTRAFE); - lookaxis = PlayerJoyAxis(ssplayer, AXISLOOK); + turnaxis += PlayerJoyAxis(ssplayer, JA_STRAFE); + lookaxis = PlayerJoyAxis(ssplayer, JA_LOOK); lookjoystickvector.xaxis = turnaxis; lookjoystickvector.yaxis = lookaxis; G_HandleAxisDeadZone(forplayer, &lookjoystickvector); @@ -1256,8 +1240,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) tta_factor[forplayer] = 0; // suspend turn to angle } - strafeaxis = strafeisturn ? 0 : PlayerJoyAxis(ssplayer, AXISSTRAFE); - moveaxis = PlayerJoyAxis(ssplayer, AXISMOVE); + strafeaxis = strafeisturn ? 0 : PlayerJoyAxis(ssplayer, JA_STRAFE); + moveaxis = PlayerJoyAxis(ssplayer, JA_MOVE); movejoystickvector.xaxis = strafeaxis; movejoystickvector.yaxis = moveaxis; G_HandleAxisDeadZone(forplayer, &movejoystickvector); @@ -1313,12 +1297,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } // fire with any button/key - axis = PlayerJoyAxis(ssplayer, AXISFIRE); + axis = PlayerJoyAxis(ssplayer, JA_FIRE); if (PLAYERINPUTDOWN(ssplayer, gc_fire) || (usejoystick && axis > 0)) cmd->buttons |= BT_ATTACK; // fire normal with any button/key - axis = PlayerJoyAxis(ssplayer, AXISFIRENORMAL); + axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL); if (PLAYERINPUTDOWN(ssplayer, gc_firenormal) || (usejoystick && axis > 0)) cmd->buttons |= BT_FIRENORMAL; @@ -1334,7 +1318,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->buttons |= BT_CUSTOM3; // use with any button/key - axis = PlayerJoyAxis(ssplayer, AXISSPIN); + axis = PlayerJoyAxis(ssplayer, JA_SPIN); if (PLAYERINPUTDOWN(ssplayer, gc_spin) || (usejoystick && axis > 0)) cmd->buttons |= BT_SPIN; @@ -1452,7 +1436,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // jump button - axis = PlayerJoyAxis(ssplayer, AXISJUMP); + axis = PlayerJoyAxis(ssplayer, JA_JUMP); if (PLAYERINPUTDOWN(ssplayer, gc_jump) || (usejoystick && axis > 0)) cmd->buttons |= BT_JUMP; @@ -2191,6 +2175,16 @@ boolean G_Responder(event_t *ev) return false; } +// +// G_LuaResponder +// Let Lua handle key events. +// +boolean G_LuaResponder(event_t *ev) +{ + return (ev->type == ev_keydown && LUAh_KeyDown(ev->data1)) || + (ev->type == ev_keyup && LUAh_KeyUp(ev->data1)); +} + // // G_Ticker // Make ticcmd_ts for the players. diff --git a/src/g_game.h b/src/g_game.h index 744d6755a..0cc380294 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -85,6 +85,25 @@ typedef enum } lockassist_e; +typedef enum +{ + JA_NONE = 0, + JA_TURN, + JA_MOVE, + JA_LOOK, + JA_STRAFE, + + JA_DIGITAL, // axes below this use digital deadzone + + JA_JUMP, + JA_SPIN, + JA_FIRE, + JA_FIRENORMAL, +} joyaxis_e; + +INT32 JoyAxis(joyaxis_e axissel); +INT32 Joy2Axis(joyaxis_e axissel); + // mouseaiming (looking up/down with the mouse or keyboard) #define KB_LOOKSPEED (1<<25) #define MAXPLMOVE (50) @@ -204,6 +223,7 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); +boolean G_LuaResponder(event_t *ev); void G_AddPlayer(INT32 playernum); diff --git a/src/g_input.c b/src/g_input.c index 049a4d82c..629b389e5 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -626,7 +626,7 @@ void G_ClearAllControlKeys(void) // Returns the name of a key (or virtual key for mouse and joy) // the input value being an keynum // -const char *G_KeynumToString(INT32 keynum) +const char *G_KeyNumToString(INT32 keynum) { static char keynamestr[8]; @@ -650,7 +650,7 @@ const char *G_KeynumToString(INT32 keynum) return keynamestr; } -INT32 G_KeyStringtoNum(const char *keystr) +INT32 G_KeyStringToNum(const char *keystr) { UINT32 j; @@ -813,10 +813,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(fromcontrols[i][0])); + G_KeyNumToString(fromcontrols[i][0])); if (fromcontrols[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrols[i][1])); + fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrols[i][1])); else fprintf(f, "\n"); } @@ -824,10 +824,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(fromcontrolsbis[i][0])); + G_KeyNumToString(fromcontrolsbis[i][0])); if (fromcontrolsbis[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsbis[i][1])); + fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrolsbis[i][1])); else fprintf(f, "\n"); } @@ -1003,8 +1003,8 @@ static void setcontrol(INT32 (*gc)[2]) CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl); return; } - keynum1 = G_KeyStringtoNum(COM_Argv(2)); - keynum2 = G_KeyStringtoNum(COM_Argv(3)); + keynum1 = G_KeyStringToNum(COM_Argv(2)); + keynum2 = G_KeyStringToNum(COM_Argv(3)); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) diff --git a/src/g_input.h b/src/g_input.h index 5912bfdc7..96139e751 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -169,8 +169,8 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin]; void G_MapEventsToControls(event_t *ev); // returns the name of a key -const char *G_KeynumToString(INT32 keynum); -INT32 G_KeyStringtoNum(const char *keystr); +const char *G_KeyNumToString(INT32 keynum); +INT32 G_KeyStringToNum(const char *keystr); // detach any keys associated to the given game control void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index a59ba546e..71282d09c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -212,6 +212,8 @@ static const struct { {META_ACTION, "action"}, {META_LUABANKS, "luabanks[]"}, + + {META_MOUSE, "mouse_t"}, {NULL, NULL} }; diff --git a/src/lua_hook.h b/src/lua_hook.h index 0d631aa4e..ae1c17a4d 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -63,6 +63,8 @@ enum hook { hook_MusicChange, hook_PlayerHeight, hook_PlayerCanEnterSpinGaps, + hook_KeyDown, + hook_KeyUp, hook_MAX // last hook }; @@ -122,3 +124,5 @@ boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building pl boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes fixed_t LUAh_PlayerHeight(player_t *player); UINT8 LUAh_PlayerCanEnterSpinGaps(player_t *player); +boolean LUAh_KeyDown(INT32 keycode); // Hooks for key events +boolean LUAh_KeyUp(INT32 keycode); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 637809fd8..8a7ce2cb9 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -79,6 +79,8 @@ const char *const hookNames[hook_MAX+1] = { "MusicChange", "PlayerHeight", "PlayerCanEnterSpinGaps", + "KeyDown", + "KeyUp", NULL }; @@ -2061,3 +2063,73 @@ UINT8 LUAh_PlayerCanEnterSpinGaps(player_t *player) lua_settop(gL, 0); return canEnter; } + +// Hook for key press +boolean LUAh_KeyDown(INT32 keycode) +{ + hook_p hookp; + boolean override = false; + if (!gL || !(hooksAvailable[hook_KeyDown/8] & (1<<(hook_KeyDown%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_KeyDown) + continue; + + PushHook(gL, hookp); + lua_pushinteger(gL, keycode); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + override = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + + return override; +} + +// Hook for key release +boolean LUAh_KeyUp(INT32 keycode) +{ + hook_p hookp; + boolean override = false; + if (!gL || !(hooksAvailable[hook_KeyUp/8] & (1<<(hook_KeyUp%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_KeyUp) + continue; + + PushHook(gL, hookp); + lua_pushinteger(gL, keycode); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + override = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + + return override; +} diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c new file mode 100644 index 000000000..1b5991e57 --- /dev/null +++ b/src/lua_inputlib.c @@ -0,0 +1,214 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2021 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_inputlib.c +/// \brief input library for Lua scripting + +#include "doomdef.h" +#include "fastcmp.h" +#include "g_input.h" +#include "g_game.h" +#include "hu_stuff.h" + +#include "lua_script.h" +#include "lua_libs.h" + +/////////////// +// FUNCTIONS // +/////////////// + +static int lib_gameControlDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, PLAYER1INPUTDOWN(i)); + return 1; +} + +static int lib_gameControl2Down(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, PLAYER2INPUTDOWN(i)); + return 1; +} + +static int lib_gameControlToKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, gamecontrol[i][0]); + lua_pushinteger(L, gamecontrol[i][1]); + return 2; +} + +static int lib_gameControl2ToKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, gamecontrolbis[i][0]); + lua_pushinteger(L, gamecontrolbis[i][1]); + return 2; +} + +static int lib_joyAxis(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushinteger(L, JoyAxis(i)); + return 1; +} + +static int lib_joy2Axis(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushinteger(L, Joy2Axis(i)); + return 1; +} + +static int lib_keyNumToString(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushstring(L, G_KeyNumToString(i)); + return 1; +} + +static int lib_keyStringToNum(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); + lua_pushinteger(L, G_KeyStringToNum(str)); + return 1; +} + +static int lib_keyNumPrintable(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushboolean(L, i >= 32 && i <= 127); + return 1; +} + +static int lib_shiftKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i >= 32 && i <= 127) + lua_pushinteger(L, shiftxform[i]); + return 1; +} + +static luaL_Reg lib[] = { + {"G_GameControlDown", lib_gameControlDown}, + {"G_GameControl2Down", lib_gameControl2Down}, + {"G_GameControlToKeyNum", lib_gameControlToKeyNum}, + {"G_GameControl2ToKeyNum", lib_gameControl2ToKeyNum}, + {"G_JoyAxis", lib_joyAxis}, + {"G_Joy2Axis", lib_joy2Axis}, + {"G_KeyNumToString", lib_keyNumToString}, + {"G_KeyStringToNum", lib_keyStringToNum}, + {"HU_KeyNumPrintable", lib_keyNumPrintable}, + {"HU_ShiftKeyNum", lib_shiftKeyNum}, + {NULL, NULL} +}; + +/////////////////// +// gamekeydown[] // +/////////////////// + +static int lib_getGameKeyDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMINPUTS) + return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); + lua_pushboolean(L, gamekeydown[i]); + return 1; +} + +static int lib_setGameKeyDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 2); + boolean j = luaL_checkboolean(L, 3); + if (i < 0 || i >= NUMINPUTS) + return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); + gamekeydown[i] = j; + return 0; +} + +static int lib_lenGameKeyDown(lua_State *L) +{ + lua_pushinteger(L, NUMINPUTS); + return 1; +} + +/////////// +// MOUSE // +/////////// + +static int mouse_get(lua_State *L) +{ + mouse_t *m = *((mouse_t **)luaL_checkudata(L, 1, META_MOUSE)); + const char *field = luaL_checkstring(L, 2); + + I_Assert(m != NULL); + + if (fastcmp(field,"dx")) + lua_pushinteger(L, m->dx); + else if (fastcmp(field,"dy")) + lua_pushinteger(L, m->dy); + else if (fastcmp(field,"mlookdy")) + lua_pushinteger(L, m->mlookdy); + else if (fastcmp(field,"rdx")) + lua_pushinteger(L, m->rdx); + else if (fastcmp(field,"rdy")) + lua_pushinteger(L, m->rdy); + else + return luaL_error(L, "mouse_t has no field named %s", field); + + return 1; +} + +// #mouse -> 1 or 2 +static int mouse_num(lua_State *L) +{ + mouse_t *m = *((mouse_t **)luaL_checkudata(L, 1, META_MOUSE)); + + I_Assert(m != NULL); + + lua_pushinteger(L, m == &mouse ? 1 : 2); + return 1; +} + +int LUA_InputLib(lua_State *L) +{ + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getGameKeyDown); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setGameKeyDown); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_lenGameKeyDown); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "gamekeydown"); + + luaL_newmetatable(L, META_MOUSE); + lua_pushcfunction(L, mouse_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, mouse_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + // Set global functions + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_register(L, NULL, lib); + return 0; +} diff --git a/src/lua_libs.h b/src/lua_libs.h index fbe8d4878..d56c45ab4 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -88,6 +88,8 @@ extern lua_State *gL; #define META_LUABANKS "LUABANKS[]*" +#define META_MOUSE "MOUSE_T*" + boolean luaL_checkboolean(lua_State *L, int narg); int LUA_EnumLib(lua_State *L); @@ -106,3 +108,4 @@ int LUA_TagLib(lua_State *L); int LUA_PolyObjLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); +int LUA_InputLib(lua_State *L); diff --git a/src/lua_script.c b/src/lua_script.c index 7fd5a98e6..45c18178a 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -20,6 +20,7 @@ #include "r_state.h" #include "r_sky.h" #include "g_game.h" +#include "g_input.h" #include "f_finale.h" #include "byteptr.h" #include "p_saveg.h" @@ -57,6 +58,7 @@ static lua_CFunction liblist[] = { LUA_PolyObjLib, // polyobj_t LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff + LUA_InputLib, // inputs NULL }; @@ -380,6 +382,12 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word, "gamestate")) { lua_pushinteger(L, gamestate); return 1; + } else if (fastcmp(word, "mouse")) { + LUA_PushUserdata(L, &mouse, META_MOUSE); + return 1; + } else if (fastcmp(word, "mouse2")) { + LUA_PushUserdata(L, &mouse2, META_MOUSE); + return 1; } return 0; } @@ -934,6 +942,7 @@ enum ARCH_SLOPE, ARCH_MAPHEADER, ARCH_SKINCOLOR, + ARCH_MOUSE, ARCH_TEND=0xFF, }; @@ -961,6 +970,7 @@ static const struct { {META_SLOPE, ARCH_SLOPE}, {META_MAPHEADER, ARCH_MAPHEADER}, {META_SKINCOLOR, ARCH_SKINCOLOR}, + {META_MOUSE, ARCH_MOUSE}, {NULL, ARCH_NULL} }; @@ -1268,7 +1278,6 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } - case ARCH_SKINCOLOR: { skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex)); @@ -1276,6 +1285,13 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) WRITEUINT16(save_p, info - skincolors); break; } + case ARCH_MOUSE: + { + mouse_t *m = *((mouse_t **)lua_touserdata(gL, myindex)); + WRITEUINT8(save_p, ARCH_MOUSE); + WRITEUINT8(save_p, m == &mouse ? 1 : 2); + break; + } default: WRITEUINT8(save_p, ARCH_NULL); return 2; @@ -1527,6 +1543,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX) case ARCH_SKINCOLOR: LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR); break; + case ARCH_MOUSE: + LUA_PushUserdata(gL, READUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE); + break; case ARCH_TEND: return 1; } diff --git a/src/m_menu.c b/src/m_menu.c index 0fca39801..fffe08cd2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12683,13 +12683,13 @@ static void M_DrawControl(void) else { if (keys[0] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[0])); + strcat (tmp, G_KeyNumToString (keys[0])); if (keys[0] != KEY_NULL && keys[1] != KEY_NULL) strcat(tmp," or "); if (keys[1] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[1])); + strcat (tmp, G_KeyNumToString (keys[1])); } diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index d46a4af2b..707b5c2d8 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -406,6 +406,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index adae2f446..dbc32c502 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -720,6 +720,9 @@ LUA + + LUA + LUA From eb2dc9e99bba9b321a0a1cc6c19071fa756a3d62 Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Thu, 25 Mar 2021 21:14:59 -0500 Subject: [PATCH 085/241] Mouse improvements --- src/d_main.c | 45 +++++++++++++++++++++++++++++++++++++++++---- src/deh_tables.c | 14 ++++++++++++++ src/g_game.c | 32 ++++++++++++++++++++------------ src/g_input.c | 12 +++--------- src/g_input.h | 14 +++++++++++++- src/i_system.h | 12 ++++++++++++ src/lua_inputlib.c | 28 ++++++++++++++++++++++++++++ src/m_menu.c | 2 +- src/sdl/i_system.c | 2 +- src/sdl/i_video.c | 22 ++++++++++++++++++++-- 10 files changed, 153 insertions(+), 30 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index d60a6cf47..0d21d2531 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -176,8 +176,10 @@ void D_ProcessEvents(void) boolean eaten; // Reset possibly stale mouse info - G_SetMouseData(0, 0, 1); - G_SetMouseData(0, 0, 2); + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); + mouse.buttons &= ~(MB_SCROLLUP|MB_SCROLLDOWN); + mouse2.buttons &= ~(MB_SCROLLUP|MB_SCROLLDOWN); for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { @@ -185,6 +187,41 @@ void D_ProcessEvents(void) ev = &events[eventtail]; + // Set mouse buttons early in case event is eaten later + if (ev->type == ev_keydown || ev->type == ev_keyup) + { + // Mouse buttons + if ((UINT32)(ev->data1 - KEY_MOUSE1) < MOUSEBUTTONS) + { + if (ev->type == ev_keydown) + mouse.buttons |= 1 << (ev->data1 - KEY_MOUSE1); + else + mouse.buttons &= ~(1 << (ev->data1 - KEY_MOUSE1)); + } + else if ((UINT32)(ev->data1 - KEY_2MOUSE1) < MOUSEBUTTONS) + { + if (ev->type == ev_keydown) + mouse2.buttons |= 1 << (ev->data1 - KEY_2MOUSE1); + else + mouse2.buttons &= ~(1 << (ev->data1 - KEY_2MOUSE1)); + } + // Scroll (has no keyup event) + else switch (ev->data1) { + case KEY_MOUSEWHEELUP: + mouse.buttons |= MB_SCROLLUP; + break; + case KEY_MOUSEWHEELDOWN: + mouse.buttons |= MB_SCROLLDOWN; + break; + case KEY_2MOUSEWHEELUP: + mouse2.buttons |= MB_SCROLLUP; + break; + case KEY_2MOUSEWHEELDOWN: + mouse2.buttons |= MB_SCROLLDOWN; + break; + } + } + // Screenshots over everything so that they can be taken anywhere. if (M_ScreenshotResponder(ev)) continue; // ate the event @@ -242,9 +279,9 @@ void D_ProcessEvents(void) } if (mouse.rdx || mouse.rdy) - G_SetMouseData(mouse.rdx, mouse.rdy, 1); + G_SetMouseDeltas(mouse.rdx, mouse.rdy, 1); if (mouse2.rdx || mouse2.rdy) - G_SetMouseData(mouse2.rdx, mouse2.rdy, 2); + G_SetMouseDeltas(mouse2.rdx, mouse2.rdy, 2); } // diff --git a/src/deh_tables.c b/src/deh_tables.c index 7bfe723da..79f0d1f11 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -23,6 +23,7 @@ #include "i_sound.h" // musictype_t (for lua) #include "g_state.h" // gamestate_t (for lua) #include "g_game.h" // Joystick axes (for lua) +#include "i_joy.h" #include "g_input.h" // Game controls (for lua) #include "deh_tables.h" @@ -5468,6 +5469,7 @@ struct int_const_s const INT_CONST[] = { {"JA_SPIN",JA_SPIN}, {"JA_FIRE",JA_FIRE}, {"JA_FIRENORMAL",JA_FIRENORMAL}, + {"JOYAXISRANGE",JOYAXISRANGE}, // Game controls {"gc_null",gc_null}, @@ -5514,6 +5516,18 @@ struct int_const_s const INT_CONST[] = { {"gc_custom3",gc_custom3}, {"num_gamecontrols",num_gamecontrols}, + // Mouse buttons + {"MB_BUTTON1",MB_BUTTON1}, + {"MB_BUTTON2",MB_BUTTON2}, + {"MB_BUTTON3",MB_BUTTON3}, + {"MB_BUTTON4",MB_BUTTON4}, + {"MB_BUTTON5",MB_BUTTON5}, + {"MB_BUTTON6",MB_BUTTON6}, + {"MB_BUTTON7",MB_BUTTON7}, + {"MB_BUTTON8",MB_BUTTON8}, + {"MB_SCROLLUP",MB_SCROLLUP}, + {"MB_SCROLLDOWN",MB_SCROLLDOWN}, + {NULL,0} }; diff --git a/src/g_game.c b/src/g_game.c index 823ea7c56..a7fbbd92f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1078,7 +1078,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) angle_t drawangleoffset = (player->powers[pw_carry] == CR_ROLLOUT) ? ANGLE_180 : 0; INT32 chasecam, chasefreelook, alwaysfreelook, usejoystick, invertmouse, turnmultiplier, mousemove; controlstyle_e controlstyle = G_ControlStyle(ssplayer); - mouse_t *m = &mouse; + INT32 mdx, mdy, mldy; static INT32 turnheld[2]; // for accelerative turning static boolean keyboard_look[2]; // true if lookup/down using keyboard @@ -1101,6 +1101,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) invertmouse = cv_invertmouse.value; turnmultiplier = cv_cam_turnmultiplier.value; mousemove = cv_mousemove.value; + mdx = mouse.dx; + mdy = -mouse.dy; + mldy = -mouse.mlookdy; G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver } else @@ -1112,10 +1115,15 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) invertmouse = cv_invertmouse2.value; turnmultiplier = cv_cam2_turnmultiplier.value; mousemove = cv_mousemove2.value; - m = &mouse2; + mdx = mouse2.dx; + mdy = -mouse2.dy; + mldy = -mouse2.mlookdy; G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver } + if (menuactive || CON_Ready() || chat_on) + mdx = mdy = mldy = 0; + strafeisturn = controlstyle == CS_SIMPLE && ticcmd_centerviewdown[forplayer] && ((cv_cam_lockedinput[forplayer].value && !ticcmd_ztargetfocus[forplayer]) || (player->pflags & PF_STARTDASH)) && !player->climbing && player->powers[pw_carry] != CR_MINECART; @@ -1455,7 +1463,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) keyboard_look[forplayer] = false; // looking up/down - *myaiming += (m->mlookdy<<19)*player_invert*screen_invert; + *myaiming += (mldy<<19)*player_invert*screen_invert; } if (analogjoystickmove && joyaiming[forplayer] && lookjoystickvector.yaxis != 0 && configlookaxis != 0) @@ -1489,22 +1497,22 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } if (!mouseaiming && mousemove) - forward += m->dy; + forward += mdy; if ((!demoplayback && (player->pflags & PF_SLIDING))) // Analog for mouse - side += m->dx*2; + side += mdx*2; else if (controlstyle == CS_LMAOGALOG) { - if (m->dx) + if (mdx) { - if (m->dx > 0) + if (mdx > 0) cmd->buttons |= BT_CAMRIGHT; else cmd->buttons |= BT_CAMLEFT; } } else - cmd->angleturn = (INT16)(cmd->angleturn - (m->dx*8)); + cmd->angleturn = (INT16)(cmd->angleturn - (mdx*8)); if (forward > MAXPLMOVE) forward = MAXPLMOVE; @@ -1850,8 +1858,8 @@ void G_DoLoadLevel(boolean resetplayer) joyxmove[i] = joyymove[i] = 0; joy2xmove[i] = joy2ymove[i] = 0; } - G_SetMouseData(0, 0, 1); - G_SetMouseData(0, 0, 2); + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); @@ -3082,8 +3090,8 @@ void G_DoReborn(INT32 playernum) joyxmove[i] = joyymove[i] = 0; joy2xmove[i] = joy2ymove[i] = 0; } - G_SetMouseData(0, 0, 1); - G_SetMouseData(0, 0, 2); + G_SetMouseDeltas(0, 0, 1); + G_SetMouseDeltas(0, 0, 2); // clear hud messages remains (usually from game startup) CON_ClearHUD(); diff --git a/src/g_input.c b/src/g_input.c index 629b389e5..3e8df9eb0 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -138,8 +138,6 @@ void G_MapEventsToControls(event_t *ev) break; case ev_mouse: // buttons are virtual keys - if (menuactive || CON_Ready() || chat_on) - break; mouse.rdx = ev->data2; mouse.rdy = ev->data3; break; @@ -1070,19 +1068,15 @@ void Command_Setcontrol2_f(void) setcontrol(gamecontrolbis); } -void G_SetMouseData(INT32 realdx, INT32 realdy, UINT8 ssplayer) +void G_SetMouseDeltas(INT32 dx, INT32 dy, UINT8 ssplayer) { mouse_t *m = ssplayer == 1 ? &mouse : &mouse2; consvar_t *cvsens, *cvysens; - if (!realdx && !realdy) { - memset(m, 0, sizeof(*m)); - return; - } cvsens = ssplayer == 1 ? &cv_mousesens : &cv_mousesens2; cvysens = ssplayer == 1 ? &cv_mouseysens : &cv_mouseysens2; - m->rdx = realdx; - m->rdy = realdy; + m->rdx = dx; + m->rdy = dy; m->dx = (INT32)(m->rdx*((cvsens->value*cvsens->value)/110.0f + 0.1f)); m->dy = (INT32)(m->rdy*((cvsens->value*cvsens->value)/110.0f + 0.1f)); m->mlookdy = (INT32)(m->rdy*((cvysens->value*cvsens->value)/110.0f + 0.1f)); diff --git a/src/g_input.h b/src/g_input.h index 96139e751..6127050ed 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -123,8 +123,20 @@ typedef struct INT32 mlookdy; // dy with mouselook sensitivity INT32 rdx; // deltas without sensitivity INT32 rdy; + UINT16 buttons; } mouse_t; +#define MB_BUTTON1 0x0001 +#define MB_BUTTON2 0x0002 +#define MB_BUTTON3 0x0004 +#define MB_BUTTON4 0x0008 +#define MB_BUTTON5 0x0010 +#define MB_BUTTON6 0x0020 +#define MB_BUTTON7 0x0040 +#define MB_BUTTON8 0x0080 +#define MB_SCROLLUP 0x0100 +#define MB_SCROLLDOWN 0x0200 + extern mouse_t mouse; extern mouse_t mouse2; @@ -184,6 +196,6 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify); // sets the members of a mouse_t given position deltas -void G_SetMouseData(INT32 realdx, INT32 realdy, UINT8 ssplayer); +void G_SetMouseDeltas(INT32 dx, INT32 dy, UINT8 ssplayer); #endif diff --git a/src/i_system.h b/src/i_system.h index 12f0d751d..787be88ee 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -314,4 +314,16 @@ const char *I_ClipboardPaste(void); void I_RegisterSysCommands(void); +/** \brief Return the position of the cursor relative to the top-left window corner. +*/ +void I_GetCursorPosition(INT32 *x, INT32 *y); + +/** \brief Retursn whether the mouse is grabbed +*/ +boolean I_GetMouseGrab(void); + +/** \brief Sets whether the mouse is grabbed +*/ +void I_SetMouseGrab(boolean grab); + #endif diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c index 1b5991e57..217202222 100644 --- a/src/lua_inputlib.c +++ b/src/lua_inputlib.c @@ -14,6 +14,7 @@ #include "g_input.h" #include "g_game.h" #include "hu_stuff.h" +#include "i_system.h" #include "lua_script.h" #include "lua_libs.h" @@ -103,6 +104,28 @@ static int lib_shiftKeyNum(lua_State *L) return 1; } +static int lib_getMouseGrab(lua_State *L) +{ + lua_pushboolean(L, I_GetMouseGrab()); + return 1; +} + +static int lib_setMouseGrab(lua_State *L) +{ + boolean grab = luaL_checkboolean(L, 1); + I_SetMouseGrab(grab); + return 0; +} + +static boolean lib_getCursorPosition(lua_State *L) +{ + int x, y; + I_GetCursorPosition(&x, &y); + lua_pushinteger(L, x); + lua_pushinteger(L, y); + return 2; +} + static luaL_Reg lib[] = { {"G_GameControlDown", lib_gameControlDown}, {"G_GameControl2Down", lib_gameControl2Down}, @@ -114,6 +137,9 @@ static luaL_Reg lib[] = { {"G_KeyStringToNum", lib_keyStringToNum}, {"HU_KeyNumPrintable", lib_keyNumPrintable}, {"HU_ShiftKeyNum", lib_shiftKeyNum}, + {"I_GetMouseGrab", lib_getMouseGrab}, + {"I_SetMouseGrab", lib_setMouseGrab}, + {"I_GetCursorPosition", lib_getCursorPosition}, {NULL, NULL} }; @@ -167,6 +193,8 @@ static int mouse_get(lua_State *L) lua_pushinteger(L, m->rdx); else if (fastcmp(field,"rdy")) lua_pushinteger(L, m->rdy); + else if (fastcmp(field,"buttons")) + lua_pushinteger(L, m->buttons); else return luaL_error(L, "mouse_t has no field named %s", field); diff --git a/src/m_menu.c b/src/m_menu.c index fffe08cd2..cc495c122 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3305,7 +3305,7 @@ boolean M_Responder(event_t *ev) } else if (ev->type == ev_mouse && mousewait < I_GetTime()) { - pmousey += ev->data3; + pmousey -= ev->data3; if (pmousey < lasty-30) { ch = KEY_DOWNARROW; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index a0dd6e1da..bd9d3d9a3 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1969,7 +1969,7 @@ void I_GetMouseEvents(void) event.data1 = 0; // event.data1 = buttons; // not needed event.data2 = handlermouse2x << 1; - event.data3 = -handlermouse2y << 1; + event.data3 = handlermouse2y << 1; handlermouse2x = 0; handlermouse2y = 0; diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 0ed10463f..20f2c8869 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -405,6 +405,19 @@ void I_UpdateMouseGrab(void) SDLdoGrabMouse(); } +boolean I_GetMouseGrab(void) +{ + return SDL_GetWindowGrab(window); +} + +void I_SetMouseGrab(boolean grab) +{ + if (grab) + SDLdoGrabMouse(); + else + SDLdoUngrabMouse(); +} + static void VID_Command_NumModes_f (void) { CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes()); @@ -673,8 +686,8 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) { if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window) { - mousemovex += evt.xrel; - mousemovey += -evt.yrel; + mousemovex += evt.xrel; + mousemovey += evt.yrel; SDL_SetWindowGrab(window, SDL_TRUE); } firstmove = false; @@ -1938,3 +1951,8 @@ void I_ShutdownGraphics(void) framebuffer = SDL_FALSE; } #endif + +void I_GetCursorPosition(INT32 *x, INT32 *y) +{ + SDL_GetMouseState(x, y); +} From cb3a8f7a58d535f17a9b60166fcd2c9ced3a84cf Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Thu, 25 Mar 2021 22:21:53 -0500 Subject: [PATCH 086/241] Remove key stuff --- src/console.c | 4 +- src/d_main.c | 17 ------- src/deh_tables.c | 46 ------------------ src/g_game.c | 10 ---- src/g_game.h | 1 - src/g_input.c | 16 +++--- src/g_input.h | 4 +- src/lua_baselib.c | 2 +- src/lua_inputlib.c | 118 --------------------------------------------- src/m_menu.c | 4 +- 10 files changed, 15 insertions(+), 207 deletions(-) diff --git a/src/console.c b/src/console.c index 3b29e9c4f..121605b10 100644 --- a/src/console.c +++ b/src/console.c @@ -221,7 +221,7 @@ static void CONS_Bind_f(void) for (key = 0; key < NUMINPUTS; key++) if (bindtable[key]) { - CONS_Printf("%s : \"%s\"\n", G_KeyNumToString(key), bindtable[key]); + CONS_Printf("%s : \"%s\"\n", G_KeynumToString(key), bindtable[key]); na = 1; } if (!na) @@ -229,7 +229,7 @@ static void CONS_Bind_f(void) return; } - key = G_KeyStringToNum(COM_Argv(1)); + key = G_KeyStringtoNum(COM_Argv(1)); if (key <= 0 || key >= NUMINPUTS) { CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n")); diff --git a/src/d_main.c b/src/d_main.c index 0d21d2531..9c95a2ac3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -183,8 +183,6 @@ void D_ProcessEvents(void) for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { - boolean hooked = false; - ev = &events[eventtail]; // Set mouse buttons early in case event is eaten later @@ -232,12 +230,6 @@ void D_ProcessEvents(void) continue; } - if (!CON_Ready() && !menuactive) { - if (G_LuaResponder(ev)) - continue; - hooked = true; - } - // Menu input #ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); @@ -252,12 +244,6 @@ void D_ProcessEvents(void) if (eaten) continue; // menu ate the event - if (!hooked && !CON_Ready()) { - if (G_LuaResponder(ev)) - continue; - hooked = true; - } - // console input #ifdef HAVE_THREADS I_lock_mutex(&con_mutex); @@ -272,9 +258,6 @@ void D_ProcessEvents(void) if (eaten) continue; // ate the event - if (!hooked && G_LuaResponder(ev)) - continue; - G_Responder(ev); } diff --git a/src/deh_tables.c b/src/deh_tables.c index 79f0d1f11..4ff193dcd 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -24,7 +24,6 @@ #include "g_state.h" // gamestate_t (for lua) #include "g_game.h" // Joystick axes (for lua) #include "i_joy.h" -#include "g_input.h" // Game controls (for lua) #include "deh_tables.h" @@ -5471,51 +5470,6 @@ struct int_const_s const INT_CONST[] = { {"JA_FIRENORMAL",JA_FIRENORMAL}, {"JOYAXISRANGE",JOYAXISRANGE}, - // Game controls - {"gc_null",gc_null}, - {"gc_forward",gc_forward}, - {"gc_backward",gc_backward}, - {"gc_strafeleft",gc_strafeleft}, - {"gc_straferight",gc_straferight}, - {"gc_turnleft",gc_turnleft}, - {"gc_turnright",gc_turnright}, - {"gc_weaponnext",gc_weaponnext}, - {"gc_weaponprev",gc_weaponprev}, - {"gc_wepslot1",gc_wepslot1}, - {"gc_wepslot2",gc_wepslot2}, - {"gc_wepslot3",gc_wepslot3}, - {"gc_wepslot4",gc_wepslot4}, - {"gc_wepslot5",gc_wepslot5}, - {"gc_wepslot6",gc_wepslot6}, - {"gc_wepslot7",gc_wepslot7}, - {"gc_wepslot8",gc_wepslot8}, - {"gc_wepslot9",gc_wepslot9}, - {"gc_wepslot10",gc_wepslot10}, - {"gc_fire",gc_fire}, - {"gc_firenormal",gc_firenormal}, - {"gc_tossflag",gc_tossflag}, - {"gc_spin",gc_spin}, - {"gc_camtoggle",gc_camtoggle}, - {"gc_camreset",gc_camreset}, - {"gc_lookup",gc_lookup}, - {"gc_lookdown",gc_lookdown}, - {"gc_centerview",gc_centerview}, - {"gc_mouseaiming",gc_mouseaiming}, - {"gc_talkkey",gc_talkkey}, - {"gc_teamkey",gc_teamkey}, - {"gc_scores",gc_scores}, - {"gc_jump",gc_jump}, - {"gc_console",gc_console}, - {"gc_pause",gc_pause}, - {"gc_systemmenu",gc_systemmenu}, - {"gc_screenshot",gc_screenshot}, - {"gc_recordgif",gc_recordgif}, - {"gc_viewpoint",gc_viewpoint}, - {"gc_custom1",gc_custom1}, - {"gc_custom2",gc_custom2}, - {"gc_custom3",gc_custom3}, - {"num_gamecontrols",num_gamecontrols}, - // Mouse buttons {"MB_BUTTON1",MB_BUTTON1}, {"MB_BUTTON2",MB_BUTTON2}, diff --git a/src/g_game.c b/src/g_game.c index a7fbbd92f..1d8eed964 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2183,16 +2183,6 @@ boolean G_Responder(event_t *ev) return false; } -// -// G_LuaResponder -// Let Lua handle key events. -// -boolean G_LuaResponder(event_t *ev) -{ - return (ev->type == ev_keydown && LUAh_KeyDown(ev->data1)) || - (ev->type == ev_keyup && LUAh_KeyUp(ev->data1)); -} - // // G_Ticker // Make ticcmd_ts for the players. diff --git a/src/g_game.h b/src/g_game.h index 0cc380294..ae93adf46 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -223,7 +223,6 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); -boolean G_LuaResponder(event_t *ev); void G_AddPlayer(INT32 playernum); diff --git a/src/g_input.c b/src/g_input.c index 3e8df9eb0..cc301e8e5 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -624,7 +624,7 @@ void G_ClearAllControlKeys(void) // Returns the name of a key (or virtual key for mouse and joy) // the input value being an keynum // -const char *G_KeyNumToString(INT32 keynum) +const char *G_KeynumToString(INT32 keynum) { static char keynamestr[8]; @@ -648,7 +648,7 @@ const char *G_KeyNumToString(INT32 keynum) return keynamestr; } -INT32 G_KeyStringToNum(const char *keystr) +INT32 G_KeyStringtoNum(const char *keystr) { UINT32 j; @@ -811,10 +811,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i], - G_KeyNumToString(fromcontrols[i][0])); + G_KeynumToString(fromcontrols[i][0])); if (fromcontrols[i][1]) - fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrols[i][1])); + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrols[i][1])); else fprintf(f, "\n"); } @@ -822,10 +822,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i], - G_KeyNumToString(fromcontrolsbis[i][0])); + G_KeynumToString(fromcontrolsbis[i][0])); if (fromcontrolsbis[i][1]) - fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrolsbis[i][1])); + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsbis[i][1])); else fprintf(f, "\n"); } @@ -1001,8 +1001,8 @@ static void setcontrol(INT32 (*gc)[2]) CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl); return; } - keynum1 = G_KeyStringToNum(COM_Argv(2)); - keynum2 = G_KeyStringToNum(COM_Argv(3)); + keynum1 = G_KeyStringtoNum(COM_Argv(2)); + keynum2 = G_KeyStringtoNum(COM_Argv(3)); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) diff --git a/src/g_input.h b/src/g_input.h index 6127050ed..798d888cd 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -181,8 +181,8 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin]; void G_MapEventsToControls(event_t *ev); // returns the name of a key -const char *G_KeyNumToString(INT32 keynum); -INT32 G_KeyStringToNum(const char *keystr); +const char *G_KeynumToString(INT32 keynum); +INT32 G_KeyStringtoNum(const char *keystr); // detach any keys associated to the given game control void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 71282d09c..6d4bde18d 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -212,7 +212,7 @@ static const struct { {META_ACTION, "action"}, {META_LUABANKS, "luabanks[]"}, - + {META_MOUSE, "mouse_t"}, {NULL, NULL} }; diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c index 217202222..875c29e70 100644 --- a/src/lua_inputlib.c +++ b/src/lua_inputlib.c @@ -13,7 +13,6 @@ #include "fastcmp.h" #include "g_input.h" #include "g_game.h" -#include "hu_stuff.h" #include "i_system.h" #include "lua_script.h" @@ -23,44 +22,6 @@ // FUNCTIONS // /////////////// -static int lib_gameControlDown(lua_State *L) -{ - int i = luaL_checkinteger(L, 1); - if (i < 0 || i >= num_gamecontrols) - return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); - lua_pushinteger(L, PLAYER1INPUTDOWN(i)); - return 1; -} - -static int lib_gameControl2Down(lua_State *L) -{ - int i = luaL_checkinteger(L, 1); - if (i < 0 || i >= num_gamecontrols) - return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); - lua_pushinteger(L, PLAYER2INPUTDOWN(i)); - return 1; -} - -static int lib_gameControlToKeyNum(lua_State *L) -{ - int i = luaL_checkinteger(L, 1); - if (i < 0 || i >= num_gamecontrols) - return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); - lua_pushinteger(L, gamecontrol[i][0]); - lua_pushinteger(L, gamecontrol[i][1]); - return 2; -} - -static int lib_gameControl2ToKeyNum(lua_State *L) -{ - int i = luaL_checkinteger(L, 1); - if (i < 0 || i >= num_gamecontrols) - return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); - lua_pushinteger(L, gamecontrolbis[i][0]); - lua_pushinteger(L, gamecontrolbis[i][1]); - return 2; -} - static int lib_joyAxis(lua_State *L) { int i = luaL_checkinteger(L, 1); @@ -75,35 +36,6 @@ static int lib_joy2Axis(lua_State *L) return 1; } -static int lib_keyNumToString(lua_State *L) -{ - int i = luaL_checkinteger(L, 1); - lua_pushstring(L, G_KeyNumToString(i)); - return 1; -} - -static int lib_keyStringToNum(lua_State *L) -{ - const char *str = luaL_checkstring(L, 1); - lua_pushinteger(L, G_KeyStringToNum(str)); - return 1; -} - -static int lib_keyNumPrintable(lua_State *L) -{ - int i = luaL_checkinteger(L, 1); - lua_pushboolean(L, i >= 32 && i <= 127); - return 1; -} - -static int lib_shiftKeyNum(lua_State *L) -{ - int i = luaL_checkinteger(L, 1); - if (i >= 32 && i <= 127) - lua_pushinteger(L, shiftxform[i]); - return 1; -} - static int lib_getMouseGrab(lua_State *L) { lua_pushboolean(L, I_GetMouseGrab()); @@ -127,51 +59,14 @@ static boolean lib_getCursorPosition(lua_State *L) } static luaL_Reg lib[] = { - {"G_GameControlDown", lib_gameControlDown}, - {"G_GameControl2Down", lib_gameControl2Down}, - {"G_GameControlToKeyNum", lib_gameControlToKeyNum}, - {"G_GameControl2ToKeyNum", lib_gameControl2ToKeyNum}, {"G_JoyAxis", lib_joyAxis}, {"G_Joy2Axis", lib_joy2Axis}, - {"G_KeyNumToString", lib_keyNumToString}, - {"G_KeyStringToNum", lib_keyStringToNum}, - {"HU_KeyNumPrintable", lib_keyNumPrintable}, - {"HU_ShiftKeyNum", lib_shiftKeyNum}, {"I_GetMouseGrab", lib_getMouseGrab}, {"I_SetMouseGrab", lib_setMouseGrab}, {"I_GetCursorPosition", lib_getCursorPosition}, {NULL, NULL} }; -/////////////////// -// gamekeydown[] // -/////////////////// - -static int lib_getGameKeyDown(lua_State *L) -{ - int i = luaL_checkinteger(L, 2); - if (i < 0 || i >= NUMINPUTS) - return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); - lua_pushboolean(L, gamekeydown[i]); - return 1; -} - -static int lib_setGameKeyDown(lua_State *L) -{ - int i = luaL_checkinteger(L, 2); - boolean j = luaL_checkboolean(L, 3); - if (i < 0 || i >= NUMINPUTS) - return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); - gamekeydown[i] = j; - return 0; -} - -static int lib_lenGameKeyDown(lua_State *L) -{ - lua_pushinteger(L, NUMINPUTS); - return 1; -} - /////////// // MOUSE // /////////// @@ -214,19 +109,6 @@ static int mouse_num(lua_State *L) int LUA_InputLib(lua_State *L) { - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getGameKeyDown); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setGameKeyDown); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_lenGameKeyDown); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "gamekeydown"); - luaL_newmetatable(L, META_MOUSE); lua_pushcfunction(L, mouse_get); lua_setfield(L, -2, "__index"); diff --git a/src/m_menu.c b/src/m_menu.c index cc495c122..be7fa8a7d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12683,13 +12683,13 @@ static void M_DrawControl(void) else { if (keys[0] != KEY_NULL) - strcat (tmp, G_KeyNumToString (keys[0])); + strcat (tmp, G_KeynumToString (keys[0])); if (keys[0] != KEY_NULL && keys[1] != KEY_NULL) strcat(tmp," or "); if (keys[1] != KEY_NULL) - strcat (tmp, G_KeyNumToString (keys[1])); + strcat (tmp, G_KeynumToString (keys[1])); } From 5a247bf375b7b1c973a52d702c37cf48de628fea Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Thu, 25 Mar 2021 23:29:42 -0500 Subject: [PATCH 087/241] Fix typo in comment of I_GetMouseGrab --- src/i_system.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_system.h b/src/i_system.h index 787be88ee..3f46eb592 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -318,7 +318,7 @@ void I_RegisterSysCommands(void); */ void I_GetCursorPosition(INT32 *x, INT32 *y); -/** \brief Retursn whether the mouse is grabbed +/** \brief Returns whether the mouse is grabbed */ boolean I_GetMouseGrab(void); From 0db07cef0ebac2f4d006094fe1b99b061bedfd57 Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Fri, 26 Mar 2021 02:03:52 -0500 Subject: [PATCH 088/241] Adjust joystick axis enum --- src/g_game.c | 4 ++-- src/g_game.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 1d8eed964..d8b615cbc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -887,7 +887,7 @@ INT32 JoyAxis(joyaxis_e axissel) if (retaxis > (+JOYAXISRANGE)) retaxis = +JOYAXISRANGE; - if (!Joystick.bGamepadStyle && axissel > JA_DIGITAL) + if (!Joystick.bGamepadStyle && axissel >= JA_DIGITAL) { const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) @@ -962,7 +962,7 @@ INT32 Joy2Axis(joyaxis_e axissel) if (retaxis > (+JOYAXISRANGE)) retaxis = +JOYAXISRANGE; - if (!Joystick2.bGamepadStyle && axissel > JA_DIGITAL) + if (!Joystick2.bGamepadStyle && axissel >= JA_DIGITAL) { const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone2.value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) diff --git a/src/g_game.h b/src/g_game.h index ae93adf46..c7fdad3ac 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -93,9 +93,9 @@ typedef enum JA_LOOK, JA_STRAFE, - JA_DIGITAL, // axes below this use digital deadzone + JA_DIGITAL, // axes henceforth use digital deadzone - JA_JUMP, + JA_JUMP = JA_DIGITAL, JA_SPIN, JA_FIRE, JA_FIRENORMAL, From 3895c023308c0ff71194531ce071860ad40764ae Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Thu, 1 Apr 2021 13:19:50 -0500 Subject: [PATCH 089/241] Revert "Remove key stuff" This reverts commit a439e569 --- src/console.c | 4 +- src/d_main.c | 17 +++++++ src/deh_tables.c | 46 ++++++++++++++++++ src/g_game.c | 10 ++++ src/g_game.h | 1 + src/g_input.c | 16 +++--- src/g_input.h | 4 +- src/lua_hooklib.c | 2 +- src/lua_inputlib.c | 118 +++++++++++++++++++++++++++++++++++++++++++++ src/m_menu.c | 4 +- 10 files changed, 207 insertions(+), 15 deletions(-) diff --git a/src/console.c b/src/console.c index 121605b10..3b29e9c4f 100644 --- a/src/console.c +++ b/src/console.c @@ -221,7 +221,7 @@ static void CONS_Bind_f(void) for (key = 0; key < NUMINPUTS; key++) if (bindtable[key]) { - CONS_Printf("%s : \"%s\"\n", G_KeynumToString(key), bindtable[key]); + CONS_Printf("%s : \"%s\"\n", G_KeyNumToString(key), bindtable[key]); na = 1; } if (!na) @@ -229,7 +229,7 @@ static void CONS_Bind_f(void) return; } - key = G_KeyStringtoNum(COM_Argv(1)); + key = G_KeyStringToNum(COM_Argv(1)); if (key <= 0 || key >= NUMINPUTS) { CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n")); diff --git a/src/d_main.c b/src/d_main.c index 9c95a2ac3..0d21d2531 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -183,6 +183,8 @@ void D_ProcessEvents(void) for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { + boolean hooked = false; + ev = &events[eventtail]; // Set mouse buttons early in case event is eaten later @@ -230,6 +232,12 @@ void D_ProcessEvents(void) continue; } + if (!CON_Ready() && !menuactive) { + if (G_LuaResponder(ev)) + continue; + hooked = true; + } + // Menu input #ifdef HAVE_THREADS I_lock_mutex(&m_menu_mutex); @@ -244,6 +252,12 @@ void D_ProcessEvents(void) if (eaten) continue; // menu ate the event + if (!hooked && !CON_Ready()) { + if (G_LuaResponder(ev)) + continue; + hooked = true; + } + // console input #ifdef HAVE_THREADS I_lock_mutex(&con_mutex); @@ -258,6 +272,9 @@ void D_ProcessEvents(void) if (eaten) continue; // ate the event + if (!hooked && G_LuaResponder(ev)) + continue; + G_Responder(ev); } diff --git a/src/deh_tables.c b/src/deh_tables.c index 4ff193dcd..79f0d1f11 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -24,6 +24,7 @@ #include "g_state.h" // gamestate_t (for lua) #include "g_game.h" // Joystick axes (for lua) #include "i_joy.h" +#include "g_input.h" // Game controls (for lua) #include "deh_tables.h" @@ -5470,6 +5471,51 @@ struct int_const_s const INT_CONST[] = { {"JA_FIRENORMAL",JA_FIRENORMAL}, {"JOYAXISRANGE",JOYAXISRANGE}, + // Game controls + {"gc_null",gc_null}, + {"gc_forward",gc_forward}, + {"gc_backward",gc_backward}, + {"gc_strafeleft",gc_strafeleft}, + {"gc_straferight",gc_straferight}, + {"gc_turnleft",gc_turnleft}, + {"gc_turnright",gc_turnright}, + {"gc_weaponnext",gc_weaponnext}, + {"gc_weaponprev",gc_weaponprev}, + {"gc_wepslot1",gc_wepslot1}, + {"gc_wepslot2",gc_wepslot2}, + {"gc_wepslot3",gc_wepslot3}, + {"gc_wepslot4",gc_wepslot4}, + {"gc_wepslot5",gc_wepslot5}, + {"gc_wepslot6",gc_wepslot6}, + {"gc_wepslot7",gc_wepslot7}, + {"gc_wepslot8",gc_wepslot8}, + {"gc_wepslot9",gc_wepslot9}, + {"gc_wepslot10",gc_wepslot10}, + {"gc_fire",gc_fire}, + {"gc_firenormal",gc_firenormal}, + {"gc_tossflag",gc_tossflag}, + {"gc_spin",gc_spin}, + {"gc_camtoggle",gc_camtoggle}, + {"gc_camreset",gc_camreset}, + {"gc_lookup",gc_lookup}, + {"gc_lookdown",gc_lookdown}, + {"gc_centerview",gc_centerview}, + {"gc_mouseaiming",gc_mouseaiming}, + {"gc_talkkey",gc_talkkey}, + {"gc_teamkey",gc_teamkey}, + {"gc_scores",gc_scores}, + {"gc_jump",gc_jump}, + {"gc_console",gc_console}, + {"gc_pause",gc_pause}, + {"gc_systemmenu",gc_systemmenu}, + {"gc_screenshot",gc_screenshot}, + {"gc_recordgif",gc_recordgif}, + {"gc_viewpoint",gc_viewpoint}, + {"gc_custom1",gc_custom1}, + {"gc_custom2",gc_custom2}, + {"gc_custom3",gc_custom3}, + {"num_gamecontrols",num_gamecontrols}, + // Mouse buttons {"MB_BUTTON1",MB_BUTTON1}, {"MB_BUTTON2",MB_BUTTON2}, diff --git a/src/g_game.c b/src/g_game.c index d8b615cbc..5939cfe3b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2183,6 +2183,16 @@ boolean G_Responder(event_t *ev) return false; } +// +// G_LuaResponder +// Let Lua handle key events. +// +boolean G_LuaResponder(event_t *ev) +{ + return (ev->type == ev_keydown && LUAh_KeyDown(ev->data1)) || + (ev->type == ev_keyup && LUAh_KeyUp(ev->data1)); +} + // // G_Ticker // Make ticcmd_ts for the players. diff --git a/src/g_game.h b/src/g_game.h index c7fdad3ac..00958abd0 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -223,6 +223,7 @@ void G_EndGame(void); // moved from y_inter.c/h and renamed void G_Ticker(boolean run); boolean G_Responder(event_t *ev); +boolean G_LuaResponder(event_t *ev); void G_AddPlayer(INT32 playernum); diff --git a/src/g_input.c b/src/g_input.c index cc301e8e5..3e8df9eb0 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -624,7 +624,7 @@ void G_ClearAllControlKeys(void) // Returns the name of a key (or virtual key for mouse and joy) // the input value being an keynum // -const char *G_KeynumToString(INT32 keynum) +const char *G_KeyNumToString(INT32 keynum) { static char keynamestr[8]; @@ -648,7 +648,7 @@ const char *G_KeynumToString(INT32 keynum) return keynamestr; } -INT32 G_KeyStringtoNum(const char *keystr) +INT32 G_KeyStringToNum(const char *keystr) { UINT32 j; @@ -811,10 +811,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(fromcontrols[i][0])); + G_KeyNumToString(fromcontrols[i][0])); if (fromcontrols[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrols[i][1])); + fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrols[i][1])); else fprintf(f, "\n"); } @@ -822,10 +822,10 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(fromcontrolsbis[i][0])); + G_KeyNumToString(fromcontrolsbis[i][0])); if (fromcontrolsbis[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsbis[i][1])); + fprintf(f, " \"%s\"\n", G_KeyNumToString(fromcontrolsbis[i][1])); else fprintf(f, "\n"); } @@ -1001,8 +1001,8 @@ static void setcontrol(INT32 (*gc)[2]) CONS_Printf(M_GetText("Control '%s' unknown\n"), namectrl); return; } - keynum1 = G_KeyStringtoNum(COM_Argv(2)); - keynum2 = G_KeyStringtoNum(COM_Argv(3)); + keynum1 = G_KeyStringToNum(COM_Argv(2)); + keynum2 = G_KeyStringToNum(COM_Argv(3)); keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) diff --git a/src/g_input.h b/src/g_input.h index 798d888cd..6127050ed 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -181,8 +181,8 @@ extern const INT32 gcl_jump_spin[num_gcl_jump_spin]; void G_MapEventsToControls(event_t *ev); // returns the name of a key -const char *G_KeynumToString(INT32 keynum); -INT32 G_KeyStringtoNum(const char *keystr); +const char *G_KeyNumToString(INT32 keynum); +INT32 G_KeyStringToNum(const char *keystr); // detach any keys associated to the given game control void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 8a7ce2cb9..28ae487b9 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1944,7 +1944,7 @@ boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boo lua_pushinteger(gL, *prefadems); lua_pushinteger(gL, *fadeinms); if (lua_pcall(gL, 7, 6, 1)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); continue; } diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c index 875c29e70..217202222 100644 --- a/src/lua_inputlib.c +++ b/src/lua_inputlib.c @@ -13,6 +13,7 @@ #include "fastcmp.h" #include "g_input.h" #include "g_game.h" +#include "hu_stuff.h" #include "i_system.h" #include "lua_script.h" @@ -22,6 +23,44 @@ // FUNCTIONS // /////////////// +static int lib_gameControlDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, PLAYER1INPUTDOWN(i)); + return 1; +} + +static int lib_gameControl2Down(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, PLAYER2INPUTDOWN(i)); + return 1; +} + +static int lib_gameControlToKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, gamecontrol[i][0]); + lua_pushinteger(L, gamecontrol[i][1]); + return 2; +} + +static int lib_gameControl2ToKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i < 0 || i >= num_gamecontrols) + return luaL_error(L, "gc_* constant %d out of range (0 - %d)", i, num_gamecontrols-1); + lua_pushinteger(L, gamecontrolbis[i][0]); + lua_pushinteger(L, gamecontrolbis[i][1]); + return 2; +} + static int lib_joyAxis(lua_State *L) { int i = luaL_checkinteger(L, 1); @@ -36,6 +75,35 @@ static int lib_joy2Axis(lua_State *L) return 1; } +static int lib_keyNumToString(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushstring(L, G_KeyNumToString(i)); + return 1; +} + +static int lib_keyStringToNum(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); + lua_pushinteger(L, G_KeyStringToNum(str)); + return 1; +} + +static int lib_keyNumPrintable(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + lua_pushboolean(L, i >= 32 && i <= 127); + return 1; +} + +static int lib_shiftKeyNum(lua_State *L) +{ + int i = luaL_checkinteger(L, 1); + if (i >= 32 && i <= 127) + lua_pushinteger(L, shiftxform[i]); + return 1; +} + static int lib_getMouseGrab(lua_State *L) { lua_pushboolean(L, I_GetMouseGrab()); @@ -59,14 +127,51 @@ static boolean lib_getCursorPosition(lua_State *L) } static luaL_Reg lib[] = { + {"G_GameControlDown", lib_gameControlDown}, + {"G_GameControl2Down", lib_gameControl2Down}, + {"G_GameControlToKeyNum", lib_gameControlToKeyNum}, + {"G_GameControl2ToKeyNum", lib_gameControl2ToKeyNum}, {"G_JoyAxis", lib_joyAxis}, {"G_Joy2Axis", lib_joy2Axis}, + {"G_KeyNumToString", lib_keyNumToString}, + {"G_KeyStringToNum", lib_keyStringToNum}, + {"HU_KeyNumPrintable", lib_keyNumPrintable}, + {"HU_ShiftKeyNum", lib_shiftKeyNum}, {"I_GetMouseGrab", lib_getMouseGrab}, {"I_SetMouseGrab", lib_setMouseGrab}, {"I_GetCursorPosition", lib_getCursorPosition}, {NULL, NULL} }; +/////////////////// +// gamekeydown[] // +/////////////////// + +static int lib_getGameKeyDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMINPUTS) + return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); + lua_pushboolean(L, gamekeydown[i]); + return 1; +} + +static int lib_setGameKeyDown(lua_State *L) +{ + int i = luaL_checkinteger(L, 2); + boolean j = luaL_checkboolean(L, 3); + if (i < 0 || i >= NUMINPUTS) + return luaL_error(L, "gamekeydown[] index %d out of range (0 - %d)", i, NUMINPUTS-1); + gamekeydown[i] = j; + return 0; +} + +static int lib_lenGameKeyDown(lua_State *L) +{ + lua_pushinteger(L, NUMINPUTS); + return 1; +} + /////////// // MOUSE // /////////// @@ -109,6 +214,19 @@ static int mouse_num(lua_State *L) int LUA_InputLib(lua_State *L) { + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getGameKeyDown); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setGameKeyDown); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_lenGameKeyDown); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "gamekeydown"); + luaL_newmetatable(L, META_MOUSE); lua_pushcfunction(L, mouse_get); lua_setfield(L, -2, "__index"); diff --git a/src/m_menu.c b/src/m_menu.c index be7fa8a7d..cc495c122 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -12683,13 +12683,13 @@ static void M_DrawControl(void) else { if (keys[0] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[0])); + strcat (tmp, G_KeyNumToString (keys[0])); if (keys[0] != KEY_NULL && keys[1] != KEY_NULL) strcat(tmp," or "); if (keys[1] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[1])); + strcat (tmp, G_KeyNumToString (keys[1])); } From 57c7a18a20b3049a47bc4bf6a3cc8fc678085e6f Mon Sep 17 00:00:00 2001 From: katsy Date: Fri, 2 Apr 2021 20:50:56 -0400 Subject: [PATCH 090/241] don't say we launched if we didn't actually launch --- src/p_slopes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index e93b0f6c9..bd0f15d2e 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -777,13 +777,13 @@ void P_SlopeLaunch(mobj_t *mo) mo->momx = slopemom.x; mo->momy = slopemom.y; mo->momz = slopemom.z/2; + + if (mo->player) + mo->player->powers[pw_justlaunched] = 1; } //CONS_Printf("Launched off of slope.\n"); mo->standingslope = NULL; - - if (mo->player) - mo->player->powers[pw_justlaunched] = 1; } // From 5b2abfa18d672a37320fb3a2cbcb2bba01e5c670 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 28 Mar 2021 20:16:17 -0500 Subject: [PATCH 091/241] Replace some decimal constants with more descriptive hex constants. --- src/r_draw8.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 1f451115e..4a72dcda4 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1227,8 +1227,9 @@ void R_DrawSplat_8 (void) // need! // // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) + // Why decimal? 0x3FFFF == 4194303... ~Golden val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[0] = colormap[val]; @@ -1236,7 +1237,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[1] = colormap[val]; @@ -1244,7 +1245,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[2] = colormap[val]; @@ -1252,7 +1253,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[3] = colormap[val]; @@ -1260,7 +1261,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[4] = colormap[val]; @@ -1268,7 +1269,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[5] = colormap[val]; @@ -1276,7 +1277,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[6] = colormap[val]; @@ -1284,7 +1285,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 4194303; + val &= 0x3FFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[7] = colormap[val]; From 776ce2a7506037b528fb7ce4acd81f22f3718582 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 28 Mar 2021 20:22:57 -0500 Subject: [PATCH 092/241] bruh i messed up --- src/r_draw8.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 4a72dcda4..b4c1491a0 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1227,9 +1227,9 @@ void R_DrawSplat_8 (void) // need! // // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - // Why decimal? 0x3FFFF == 4194303... ~Golden + // Why decimal? 0x3FFFFF == 4194303... ~Golden val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[0] = colormap[val]; @@ -1237,7 +1237,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[1] = colormap[val]; @@ -1245,7 +1245,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[2] = colormap[val]; @@ -1253,7 +1253,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[3] = colormap[val]; @@ -1261,7 +1261,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[4] = colormap[val]; @@ -1269,7 +1269,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[5] = colormap[val]; @@ -1277,7 +1277,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[6] = colormap[val]; @@ -1285,7 +1285,7 @@ void R_DrawSplat_8 (void) yposition += ystep; val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); - val &= 0x3FFFF; + val &= 0x3FFFFF; val = source[val]; if (val != TRANSPARENTPIXEL) dest[7] = colormap[val]; From c3d5740e983891b18bd45fccf45ac89cd9345403 Mon Sep 17 00:00:00 2001 From: SwitchKaze Date: Tue, 6 Apr 2021 15:06:44 -0500 Subject: [PATCH 093/241] Fix console text bleeding edge case A single character could prematurely read if there were enough special characters to push 'c' past 'con_width'. --- src/console.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/console.c b/src/console.c index 2d95e10b8..208b55212 100644 --- a/src/console.c +++ b/src/console.c @@ -1654,6 +1654,8 @@ static void CON_DrawHudlines(void) p++; c++; } + if (c >= con_width) + break; if (*p < HU_FONTSTART) ;//charwidth = 4 * con_scalefactor; else @@ -1777,6 +1779,8 @@ static void CON_DrawConsole(void) p++; c++; } + if (c >= con_width) + break; V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } } From dbc7f93f15479d7d123b5507b5aaf94e7f952249 Mon Sep 17 00:00:00 2001 From: sphere Date: Sat, 10 Apr 2021 11:52:15 -0400 Subject: [PATCH 094/241] Fix incorrect prefixes in the config --- extras/conf/SRB2-22.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 246ef9b64..a8217754d 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3110,7 +3110,7 @@ linedeftypes 733 { title = "Copy Backside Floor Slope to Frontside"; - prefix = "(730)"; + prefix = "(733)"; slope = "copy"; copyslopeargs = 2; } @@ -3118,7 +3118,7 @@ linedeftypes 734 { title = "Copy Backside Ceiling Slope to Frontside"; - prefix = "(731)"; + prefix = "(734)"; slope = "copy"; copyslopeargs = 8; } @@ -3126,7 +3126,7 @@ linedeftypes 735 { title = "Copy Backside Floor and Ceiling Slope to Frontside"; - prefix = "(732)"; + prefix = "(735)"; slope = "copy"; copyslopeargs = 10; } From b3d7df74c085464cc7f3dd3d78da6f54b8804305 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Wed, 14 Apr 2021 10:55:52 -0300 Subject: [PATCH 095/241] This is my attempted fix for texture rotation on slopes, in Software. --- src/r_draw8.c | 64 +++++++-------- src/r_draw8_npo2.c | 152 +++++++++++++++++----------------- src/r_plane.c | 197 +++++++++++++++++++++++---------------------- src/r_plane.h | 4 +- src/r_splats.c | 3 +- 5 files changed, 212 insertions(+), 208 deletions(-) diff --git a/src/r_draw8.c b/src/r_draw8.c index 1f451115e..5c62b5595 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -693,8 +693,8 @@ void R_DrawTiltedSpan_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); @@ -726,8 +726,8 @@ void R_DrawTiltedSpan_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -763,8 +763,8 @@ void R_DrawTiltedSpan_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -826,8 +826,8 @@ void R_DrawTiltedTranslucentSpan_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); @@ -858,8 +858,8 @@ void R_DrawTiltedTranslucentSpan_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -895,8 +895,8 @@ void R_DrawTiltedTranslucentSpan_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -960,8 +960,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); @@ -992,8 +992,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1029,8 +1029,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -1091,8 +1091,8 @@ void R_DrawTiltedSplat_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); @@ -1127,8 +1127,8 @@ void R_DrawTiltedSplat_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1168,8 +1168,8 @@ void R_DrawTiltedSplat_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -1672,8 +1672,8 @@ void R_DrawTiltedFloorSprite_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1712,8 +1712,8 @@ void R_DrawTiltedFloorSprite_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -1781,8 +1781,8 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { @@ -1821,8 +1821,8 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index a34a20e9a..b5614898c 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -133,15 +133,15 @@ void R_DrawTiltedSpan_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -181,16 +181,16 @@ void R_DrawTiltedSpan_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -220,8 +220,8 @@ void R_DrawTiltedSpan_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -248,16 +248,16 @@ void R_DrawTiltedSpan_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -326,14 +326,14 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -373,16 +373,16 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -412,8 +412,8 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -440,16 +440,16 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -517,15 +517,15 @@ void R_DrawTiltedSplat_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -569,16 +569,16 @@ void R_DrawTiltedSplat_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -610,8 +610,8 @@ void R_DrawTiltedSplat_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -640,8 +640,8 @@ void R_DrawTiltedSplat_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { @@ -649,8 +649,8 @@ void R_DrawTiltedSplat_NPO2_8(void) val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1002,14 +1002,14 @@ void R_DrawTiltedFloorSprite_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1040,8 +1040,8 @@ void R_DrawTiltedFloorSprite_NPO2_8(void) v = (INT64)(startv); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1070,14 +1070,14 @@ void R_DrawTiltedFloorSprite_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1152,14 +1152,14 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1190,8 +1190,8 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) v = (INT64)(startv); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1220,14 +1220,14 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { // Lactozilla: Non-powers-of-two - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1429,14 +1429,14 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) do { double z = 1.f/iz; - u = (INT64)(uz*z) + viewx; - v = (INT64)(vz*z) + viewy; + u = (INT64)(uz*z); + v = (INT64)(vz*z); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1476,16 +1476,16 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) endv = vz*endz; stepu = (INT64)((endu - startu) * INVSPAN); stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (i = SPANSIZE-1; i >= 0; i--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1515,8 +1515,8 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) @@ -1543,16 +1543,16 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) left = 1.f/left; stepu = (INT64)((endu - startu) * left); stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu) + viewx; - v = (INT64)(startv) + viewy; + u = (INT64)(startu); + v = (INT64)(startv); for (; width != 0; width--) { colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); // Lactozilla: Non-powers-of-two { - fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); - fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); // Carefully align all of my Friends. if (x < 0) diff --git a/src/r_plane.c b/src/r_plane.c index ea4dfa4e8..a936b0911 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -104,6 +104,7 @@ fixed_t cachedxstep[MAXVIDHEIGHT]; fixed_t cachedystep[MAXVIDHEIGHT]; static fixed_t xoffs, yoffs; +static floatv3_t ds_slope_origin, ds_slope_u, ds_slope_v; // // R_InitPlanes @@ -662,69 +663,91 @@ static void R_DrawSkyPlane(visplane_t *pl) } } -// Potentially override other stuff for now cus we're mean. :< But draw a slope plane! -// I copied ZDoom's code and adapted it to SRB2... -Red -void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge) +// Sets the origin vector of the sloped plane. +static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) { - floatv3_t p, m, n; - float ang; - float vx, vy, vz; - float xscale = FIXED_TO_FLOAT(planexscale); - float yscale = FIXED_TO_FLOAT(planeyscale); - // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly - // use this as a temp var to store P_GetSlopeZAt's return value each time - fixed_t temp; + floatv3_t *p = &ds_slope_origin; - vx = FIXED_TO_FLOAT(planeviewx+planexoffset); - vy = FIXED_TO_FLOAT(planeviewy-planeyoffset); - vz = FIXED_TO_FLOAT(planeviewz); + float vx = FixedToFloat(xpos + xoff); + float vy = FixedToFloat(ypos - yoff); + float vz = FixedToFloat(zpos); + float ang = ANG2RAD(ANGLE_270 - angle); - temp = P_GetSlopeZAt(slope, planeviewx, planeviewy); - zeroheight = FIXED_TO_FLOAT(temp); + zeroheight = FixedToFloat(P_GetSlopeZAt(slope, xpos, ypos)); // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - ang = ANG2RAD(ANGLE_270 - planeviewangle); - p.x = vx * cos(ang) - vy * sin(ang); - p.z = vx * sin(ang) + vy * cos(ang); - temp = P_GetSlopeZAt(slope, -planexoffset, planeyoffset); - p.y = FIXED_TO_FLOAT(temp) - vz; + p->x = vx * cos(ang) - vy * sin(ang); + p->z = vx * sin(ang) + vy * cos(ang); + p->y = FixedToFloat(P_GetSlopeZAt(slope, -xoff, yoff)) - vz; +} + +// This function calculates all of the vectors necessary for drawing a tilted span. +void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +{ + // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! + // I copied ZDoom's code and adapted it to SRB2... -Red + floatv3_t *m = &ds_slope_v, *n = &ds_slope_u; + fixed_t temp; + float ang; + + R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); // m is the v direction vector in view space - ang = ANG2RAD(ANGLE_180 - (planeviewangle + planeangle)); - m.x = yscale * cos(ang); - m.z = yscale * sin(ang); + ang = ANG2RAD(ANGLE_180 - (angle + plangle)); + m->x = cos(ang); + m->z = sin(ang); // n is the u direction vector in view space - n.x = xscale * sin(ang); - n.z = -xscale * cos(ang); + n->x = sin(ang); + n->z = -cos(ang); - ang = ANG2RAD(planeangle); - temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(yscale * sin(ang)), planeviewy + FLOAT_TO_FIXED(yscale * cos(ang))); - m.y = FIXED_TO_FLOAT(temp) - zeroheight; - temp = P_GetSlopeZAt(slope, planeviewx + FLOAT_TO_FIXED(xscale * cos(ang)), planeviewy - FLOAT_TO_FIXED(xscale * sin(ang))); - n.y = FIXED_TO_FLOAT(temp) - zeroheight; + ang = ANG2RAD(plangle); + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(sin(ang)), ypos + FloatToFixed(cos(ang))); + m->y = FixedToFloat(temp) - zeroheight; + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(cos(ang)), ypos - FloatToFixed(sin(ang))); + n->y = FixedToFloat(temp) - zeroheight; +} - if (ds_powersoftwo) - { - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; +// This function calculates all of the vectors necessary for drawing a scaled, tilted span. +void R_SetSlopePlaneScaled(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +{ + floatv3_t *m = &ds_slope_v, *n = &ds_slope_u; + fixed_t temp; - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; - } + float xscale = FixedToFloat(xs); + float yscale = FixedToFloat(ys); + float ang; + R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); + + // m is the v direction vector in view space + ang = ANG2RAD(ANGLE_180 - (angle + plangle)); + m->x = yscale * cos(ang); + m->z = yscale * sin(ang); + + // n is the u direction vector in view space + n->x = xscale * sin(ang); + n->z = -xscale * cos(ang); + + ang = ANG2RAD(plangle); + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(yscale * sin(ang)), ypos + FloatToFixed(yscale * cos(ang))); + m->y = FixedToFloat(temp) - zeroheight; + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(xscale * cos(ang)), ypos - FloatToFixed(xscale * sin(ang))); + n->y = FixedToFloat(temp) - zeroheight; +} + +void R_CalculateSlopeVectors(void) +{ // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ d->x = (v1.y * v2.z) - (v1.z * v2.y);\ d->y = (v1.z * v2.x) - (v1.x * v2.z);\ d->z = (v1.x * v2.y) - (v1.y * v2.x) - CROSS(ds_sup, p, m); - CROSS(ds_svp, p, n); - CROSS(ds_szp, m, n); + CROSS(ds_sup, ds_slope_origin, ds_slope_v); + CROSS(ds_svp, ds_slope_origin, ds_slope_u); + CROSS(ds_szp, ds_slope_v, ds_slope_u); #undef CROSS ds_sup->z *= focallengthf; @@ -769,10 +792,11 @@ void R_SetTiltedSpan(INT32 span) ds_szp = &ds_sz[span]; } -static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff, float fudge) +static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_t yoff) { R_SetTiltedSpan(y); - R_CalculateSlopeVectors(pl->slope, pl->viewx, pl->viewy, pl->viewz, FRACUNIT, FRACUNIT, xoff, yoff, pl->viewangle, pl->plangle, fudge); + R_SetSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle); + R_CalculateSlopeVectors(); } void R_DrawSinglePlane(visplane_t *pl) @@ -782,8 +806,8 @@ void R_DrawSinglePlane(visplane_t *pl) INT32 x; INT32 stop, angle; ffloor_t *rover; - int type; - int spanfunctype = BASEDRAWFUNC; + INT32 type; + INT32 spanfunctype = BASEDRAWFUNC; if (!(pl->minx <= pl->maxx)) return; @@ -953,61 +977,38 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - float fudgecanyon = 0; - angle_t hack = (pl->plangle & (ANGLE_90-1)); + const fixed_t modmaskw = (ds_flatwidth << FRACBITS) - 1; + const fixed_t modmaskh = (ds_flatheight << FRACBITS) - 1; - yoffs *= 1; + /* + Essentially: We can't & the components along the regular axes when the plane is rotated. + This is because the distance on each regular axis in order to loop is different. + We rotate them, & the components, add them together, & them again, and then rotate them back. + These three seperate & operations are done per axis in order to prevent overflows. + toast 10/04/17 + */ + const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); - if (ds_powersoftwo) - { - fixed_t temp; - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red - fudgecanyon = ((1<>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmaskw) - (FixedMul(pl->slope->o.y,sinecomponent) & modmaskh); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmaskw) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmaskh); - const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + fixed_t temp = ox & modmaskw; + oy &= modmaskh; + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmaskw) + (FixedMul(yoffs,sinecomponent) & modmaskh); + yoffs = (-FixedMul(temp,sinecomponent) & modmaskw) + (FixedMul(yoffs,cosinecomponent) & modmaskh); - temp = ox & modmask; - oy &= modmask; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + temp = xoffs & modmaskw; + yoffs &= modmaskh; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); - } - else - { - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - } - - xoffs = (fixed_t)(xoffs*fudgecanyon); - yoffs = (fixed_t)(yoffs/fudgecanyon); - } + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); if (planeripple.active) { @@ -1018,11 +1019,11 @@ void R_DrawSinglePlane(visplane_t *pl) for (x = pl->high; x < pl->low; x++) { R_CalculatePlaneRipple(pl, x, plheight, true); - R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac), fudgecanyon); + R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac)); } } else - R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs, fudgecanyon); + R_SetSlopePlaneVectors(pl, 0, xoffs, yoffs); switch (spanfunctype) { diff --git a/src/r_plane.h b/src/r_plane.h index 0d11c5b72..8f7574744 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -94,7 +94,9 @@ boolean R_CheckPowersOfTwo(void); void R_DrawSinglePlane(visplane_t *pl); // Calculates the slope vectors needed for tilted span drawing. -void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge); +void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); +void R_SetSlopePlaneScaled(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); +void R_CalculateSlopeVectors(void); // Sets the slope vector pointers for the current tilted span. void R_SetTiltedSpan(INT32 span); diff --git a/src/r_splats.c b/src/r_splats.c index 72cac9fd9..49b66304b 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -419,7 +419,8 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (pSplat->tilted) { R_SetTiltedSpan(0); - R_CalculateSlopeVectors(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle, 1.0f); + R_SetSlopePlaneScaled(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle); + R_CalculateSlopeVectors(); spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; } else From d5e9005dd0f49b66e7fa384eaaa6360e535638f1 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Wed, 14 Apr 2021 11:34:36 -0300 Subject: [PATCH 096/241] Fix NPOT flats, other minor changes. --- src/r_plane.c | 42 ++++++++++++++++-------------------------- src/r_plane.h | 2 +- src/r_splats.c | 2 +- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index a936b0911..10d87b9cc 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -663,7 +663,7 @@ static void R_DrawSkyPlane(visplane_t *pl) } } -// Sets the origin vector of the sloped plane. +// Sets the texture origin vector of the sloped plane. static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) { floatv3_t *p = &ds_slope_origin; @@ -683,7 +683,7 @@ static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, f p->y = FixedToFloat(P_GetSlopeZAt(slope, -xoff, yoff)) - vz; } -// This function calculates all of the vectors necessary for drawing a tilted span. +// This function calculates all of the vectors necessary for drawing a sloped plane. void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) { // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! @@ -710,8 +710,8 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, n->y = FixedToFloat(temp) - zeroheight; } -// This function calculates all of the vectors necessary for drawing a scaled, tilted span. -void R_SetSlopePlaneScaled(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +// This function calculates all of the vectors necessary for drawing a sloped and scaled plane. +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) { floatv3_t *m = &ds_slope_v, *n = &ds_slope_u; fixed_t temp; @@ -740,6 +740,8 @@ void R_SetSlopePlaneScaled(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t void R_CalculateSlopeVectors(void) { + float sfmult = 65536.f; + // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. #define CROSS(d, v1, v2) \ d->x = (v1.y * v2.z) - (v1.z * v2.y);\ @@ -755,27 +757,15 @@ d->z = (v1.x * v2.y) - (v1.y * v2.x) ds_szp->z *= focallengthf; // Premultiply the texture vectors with the scale factors -#define SFMULT 65536.f if (ds_powersoftwo) - { - ds_sup->x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<x *= (SFMULT * (1<y *= (SFMULT * (1<z *= (SFMULT * (1<x *= SFMULT; - ds_sup->y *= SFMULT; - ds_sup->z *= SFMULT; - ds_svp->x *= SFMULT; - ds_svp->y *= SFMULT; - ds_svp->z *= SFMULT; - } -#undef SFMULT + sfmult *= (1 << nflatshiftup); + + ds_sup->x *= sfmult; + ds_sup->y *= sfmult; + ds_sup->z *= sfmult; + ds_svp->x *= sfmult; + ds_svp->y *= sfmult; + ds_svp->z *= sfmult; } void R_SetTiltedSpan(INT32 span) @@ -977,8 +967,8 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - const fixed_t modmaskw = (ds_flatwidth << FRACBITS) - 1; - const fixed_t modmaskh = (ds_flatheight << FRACBITS) - 1; + const fixed_t modmaskw = (ds_powersoftwo) ? (ds_flatwidth << FRACBITS) - 1 : (signed)(0xFFFFFFFF); + const fixed_t modmaskh = (ds_powersoftwo) ? (ds_flatheight << FRACBITS) - 1 : (signed)(0xFFFFFFFF); /* Essentially: We can't & the components along the regular axes when the plane is rotated. diff --git a/src/r_plane.h b/src/r_plane.h index 8f7574744..9b7e31e3e 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -95,7 +95,7 @@ void R_DrawSinglePlane(visplane_t *pl); // Calculates the slope vectors needed for tilted span drawing. void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); -void R_SetSlopePlaneScaled(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); void R_CalculateSlopeVectors(void); // Sets the slope vector pointers for the current tilted span. diff --git a/src/r_splats.c b/src/r_splats.c index 49b66304b..4783fb640 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -419,7 +419,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (pSplat->tilted) { R_SetTiltedSpan(0); - R_SetSlopePlaneScaled(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle); + R_SetScaledSlopePlane(&pSplat->slope, viewx, viewy, viewz, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewangle, pSplat->angle); R_CalculateSlopeVectors(); spanfunctype = SPANDRAWFUNC_TILTEDSPRITE; } From d59f25a6cdd16fd1133c089bf6ba740dbc42e657 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 18 Apr 2021 12:59:49 -0400 Subject: [PATCH 097/241] stagefailed is more useful - Can now apply to normal stages, simply defaults to "false" in normal stages. - Post-level cutscenes are now always skipped when the stage was failed. - Exposed the boolean as a Lua read+write global. Desired for SUGOI, as it allows for visited flags not be updated, and level completion emblems to not be awarded. Which means a lot less crappy non-ideal workarounds. Normal stage intermission currently does not reflect failure state at all. Maybe it could always skip, never award score bonuses, have different text... etc. Probably would leave that up to vanilla dev opinion. --- src/doomstat.h | 2 +- src/g_game.c | 15 +++++++++++---- src/lua_script.c | 5 +++++ src/p_setup.c | 6 ++++-- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 2d28b81af..2dbb144e6 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -496,7 +496,7 @@ extern UINT32 lastcustomtol; extern tic_t totalplaytime; -extern UINT8 stagefailed; +extern boolean stagefailed; // Emeralds stored as bits to throw savegame hackers off. extern UINT16 emeralds; diff --git a/src/g_game.c b/src/g_game.c index 2b304b4fd..e6c445d68 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -169,7 +169,7 @@ static boolean exitgame = false; static boolean retrying = false; static boolean retryingmodeattack = false; -UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage. +boolean stagefailed = false; // Used for GEMS BONUS? Also to see if you beat the stage. UINT16 emeralds; INT32 luabanks[NUM_LUABANKS]; @@ -3742,7 +3742,7 @@ static void G_UpdateVisited(void) // Update visitation flags? if ((!modifiedgame || savemoddata) // Not modified && !multiplayer && !demoplayback && (gametype == GT_COOP) // SP/RA/NiGHTS mode - && !(spec && stagefailed)) // Not failed the special stage + && !stagefailed) // Did not fail the stage { UINT8 earnedEmblems; @@ -3963,7 +3963,7 @@ static void G_DoCompleted(void) // If the current gametype has no intermission screen set, then don't start it. Y_DetermineIntermissionType(); - if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed) || (intertype == int_none)) + if ((skipstats && !modeattacking) || (modeattacking && stagefailed) || (intertype == int_none)) { G_UpdateVisited(); G_HandleSaveLevel(); @@ -3994,8 +3994,15 @@ void G_AfterIntermission(void) HU_ClearCEcho(); - if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene. + if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum + && !modeattacking + && skipstats <= 1 + && (gamecomplete || !(marathonmode & MA_NOCUTSCENES)) + && stagefailed == false) + { + // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); + } else { if (nextmap < 1100-1) diff --git a/src/lua_script.c b/src/lua_script.c index 7fd5a98e6..0a7e44422 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -380,6 +380,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word, "gamestate")) { lua_pushinteger(L, gamestate); return 1; + } else if (fastcmp(word, "stagefailed")) { + lua_pushboolean(L, stagefailed); + return 1; } return 0; } @@ -429,6 +432,8 @@ int LUA_CheckGlobals(lua_State *L, const char *word) } else if (fastcmp(word, "mapmusflags")) mapmusflags = (UINT16)luaL_checkinteger(L, 2); + else if (fastcmp(word, "stagefailed")) + stagefailed = luaL_checkboolean(L, 2); else return 0; diff --git a/src/p_setup.c b/src/p_setup.c index 40dd1a284..2e7db1055 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3394,8 +3394,10 @@ static void P_InitLevelSettings(void) numstarposts = 0; ssspheres = timeinmap = 0; - // special stage - stagefailed = true; // assume failed unless proven otherwise - P_GiveEmerald or emerald touchspecial + // Assume Special Stages were failed in unless proven otherwise - via P_GiveEmerald or emerald touchspecial + // Normal stages will default to be OK, unless a Lua script sets to false. + stagefailed = G_IsSpecialStage(gamemap); + // Reset temporary record data memset(&ntemprecords, 0, sizeof(nightsdata_t)); From b026a6991cb87b870de07daa191b9fa87a2ac087 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 19 Apr 2021 15:52:07 -0300 Subject: [PATCH 098/241] Easing functions --- src/CMakeLists.txt | 2 + src/Makefile | 1 + src/m_easing.c | 399 +++++++++++++++++++++++++++++++++++++++++++++ src/m_easing.h | 95 +++++++++++ 4 files changed, 497 insertions(+) create mode 100644 src/m_easing.c create mode 100644 src/m_easing.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 87a0499b6..cd6e17386 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ set(SRB2_CORE_SOURCES m_bbox.c m_cheat.c m_cond.c + m_easing.c m_fixed.c m_menu.c m_misc.c @@ -101,6 +102,7 @@ set(SRB2_CORE_HEADERS m_cheat.h m_cond.h m_dllist.h + m_easing.h m_fixed.h m_menu.h m_misc.h diff --git a/src/Makefile b/src/Makefile index a4c3c4fdb..bdca6dc08 100644 --- a/src/Makefile +++ b/src/Makefile @@ -503,6 +503,7 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/m_bbox.o \ $(OBJDIR)/m_cheat.o \ $(OBJDIR)/m_cond.o \ + $(OBJDIR)/m_easing.o \ $(OBJDIR)/m_fixed.o \ $(OBJDIR)/m_menu.o \ $(OBJDIR)/m_misc.o \ diff --git a/src/m_easing.c b/src/m_easing.c new file mode 100644 index 000000000..b3ea8842f --- /dev/null +++ b/src/m_easing.c @@ -0,0 +1,399 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. +// +// 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 m_easing.c +/// \brief Easing functions +/// Referenced from https://easings.net/ + +#include "m_easing.h" +#include "tables.h" +#include "doomdef.h" + +/* + For the computation of the logarithm, we choose, by trial and error, from among + a sequence of particular factors those, that when multiplied with the function + argument, normalize it to unity. For every factor chosen, we add up the + corresponding logarithm value stored in a table. The sum then corresponds to + the logarithm of the function argument. + + For the integer portion, we would want to choose + 2^i, i = 1, 2, 4, 8, ... + and for the factional part we choose + 1+2^-i, i = 1, 2, 3, 4, 5 ... + + The algorithm for the exponential is closely related and quite literally the inverse + of the logarithm algorithm. From among the sequence of tabulated logarithms for our + chosen factors, we pick those that when subtracted from the function argument ultimately + reduce it to zero. Starting with unity, we multiply with all the factors whose logarithms + we have subtracted in the process. The resulting product corresponds to the result of the exponentiation. + + Logarithms of values greater than unity can be computed by applying the algorithm to the reciprocal + of the function argument (with the negation of the result as appropriate), likewise exponentiation with + negative function arguments requires us negate the function argument and compute the reciprocal at the end. +*/ + +static fixed_t logtabdec[FRACBITS] = +{ + 0x95c1, 0x526a, 0x2b80, 0x1663, + 0xb5d, 0x5b9, 0x2e0, 0x170, + 0xb8, 0x5c, 0x2e, 0x17, + 0x0b, 0x06, 0x03, 0x01 +}; + +static fixed_t fixlog2(fixed_t a) +{ + UINT32 x = a, y = 0; + INT32 t, i, shift = 8; + + if (x > FRACUNIT) + x = FixedDiv(FRACUNIT, x); + + // Integer part + // 1<<19 = 0x80000 + // 1<<18 = 0x40000 + // 1<<17 = 0x20000 + // 1<<16 = 0x10000 + +#define dologtab(i) \ + t = (x << shift); \ + if (t < FRACUNIT) \ + { \ + x = t; \ + y += (1 << (19 - i)); \ + } \ + shift /= 2; + + dologtab(0) + dologtab(1) + dologtab(2) + dologtab(3) + +#undef dologtab + + // Decimal part + for (i = 0; i < FRACBITS; i++) + { + t = x + (x >> (i + 1)); + if (t < FRACUNIT) + { + x = t; + y += logtabdec[i]; + } + } + + if (a <= FRACUNIT) + return -y; + + return y; +} + +// Notice how this is symmetric to fixlog2. +static INT32 fixexp(fixed_t a) +{ + UINT32 x, y; + fixed_t t, i, shift = 8; + + // Underflow prevention. + if (a <= -15 * FRACUNIT) + return 0; + + x = (a < 0) ? (-a) : (a); + y = FRACUNIT; + + // Integer part (see fixlog2) +#define dologtab(i) \ + t = x - (1 << (19 - i)); \ + if (t >= 0) \ + { \ + x = t; \ + y <<= shift; \ + } \ + shift /= 2; + + dologtab(0) + dologtab(1) + dologtab(2) + dologtab(3) + +#undef dologtab + + // Decimal part + for (i = 0; i < FRACBITS; i++) + { + t = (x - logtabdec[i]); + if (t >= 0) + { + x = t; + y += (y >> (i + 1)); + } + } + + if (a < 0) + return FixedDiv(FRACUNIT, y); + + return y; +} + +#define fixpow(x, y) fixexp(FixedMul((y), fixlog2(x))) +#define fixintmul(x, y) FixedMul((x) * FRACUNIT, y) +#define fixintdiv(x, y) FixedDiv(x, (y) * FRACUNIT) +#define fixinterp(start, end, t) FixedMul((FRACUNIT - (t)), start) + FixedMul(t, end) + +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t start, fixed_t end, fixed_t t) + +// +// Linear +// + +EASINGFUNC(Linear) +{ + return fixinterp(start, end, t); +} + +// +// Sine +// + +// This is equivalent to calculating (x * pi) and converting the result from radians into degrees. +#define fixang(x) FixedMul((x), 180*FRACUNIT) + +EASINGFUNC(InSine) +{ + fixed_t c = fixang(t / 2); + fixed_t x = FRACUNIT - FINECOSINE(FixedAngle(c)>>ANGLETOFINESHIFT); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutSine) +{ + fixed_t c = fixang(t / 2); + fixed_t x = FINESINE(FixedAngle(c)>>ANGLETOFINESHIFT); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutSine) +{ + fixed_t c = fixang(t); + fixed_t x = -(FINECOSINE(FixedAngle(c)>>ANGLETOFINESHIFT) - FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +#undef fixang + +// +// Quad +// + +EASINGFUNC(InQuad) +{ + return fixinterp(start, end, FixedMul(t, t)); +} + +EASINGFUNC(OutQuad) +{ + return fixinterp(start, end, FRACUNIT - FixedMul(FRACUNIT - t, FRACUNIT - t)); +} + +EASINGFUNC(InOutQuad) +{ + fixed_t x = t < (FRACUNIT/2) + ? fixintmul(2, FixedMul(t, t)) + : FRACUNIT - fixpow(FixedMul(-2*FRACUNIT, t) + 2*FRACUNIT, 2*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// Cubic +// + +EASINGFUNC(InCubic) +{ + fixed_t x = FixedMul(t, FixedMul(t, t)); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutCubic) +{ + return fixinterp(start, end, FRACUNIT - fixpow(FRACUNIT - t, 3*FRACUNIT)); +} + +EASINGFUNC(InOutCubic) +{ + fixed_t x = t < (FRACUNIT/2) + ? fixintmul(4, FixedMul(t, FixedMul(t, t))) + : FRACUNIT - fixpow(fixintmul(-2, t) + 2*FRACUNIT, 3*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// "Quart" +// + +EASINGFUNC(InQuart) +{ + fixed_t x = FixedMul(FixedMul(t, t), FixedMul(t, t)); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutQuart) +{ + fixed_t x = FRACUNIT - fixpow(FRACUNIT - t, 4 * FRACUNIT); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutQuart) +{ + fixed_t x = t < (FRACUNIT/2) + ? fixintmul(8, FixedMul(FixedMul(t, t), FixedMul(t, t))) + : FRACUNIT - fixpow(fixintmul(-2, t) + 2*FRACUNIT, 4*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// "Quint" +// + +EASINGFUNC(InQuint) +{ + fixed_t x = FixedMul(t, FixedMul(FixedMul(t, t), FixedMul(t, t))); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutQuint) +{ + fixed_t x = FRACUNIT - fixpow(FRACUNIT - t, 5 * FRACUNIT); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutQuint) +{ + fixed_t x = t < (FRACUNIT/2) + ? FixedMul(16*FRACUNIT, FixedMul(t, FixedMul(FixedMul(t, t), FixedMul(t, t)))) + : FRACUNIT - fixpow(fixintmul(-2, t) + 2*FRACUNIT, 5*FRACUNIT) / 2; + return fixinterp(start, end, x); +} + +// +// Exponential +// + +EASINGFUNC(InExpo) +{ + fixed_t x = (!t) ? 0 : fixpow(2*FRACUNIT, fixintmul(10, t) - 10*FRACUNIT); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutExpo) +{ + fixed_t x = (t >= FRACUNIT) ? FRACUNIT + : FRACUNIT - fixpow(2*FRACUNIT, fixintmul(-10, t)); + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutExpo) +{ + fixed_t x; + + if (!t) + x = 0; + else if (t >= FRACUNIT) + x = FRACUNIT; + else + { + if (t < FRACUNIT / 2) + { + x = fixpow(2*FRACUNIT, fixintmul(20, t) - 10*FRACUNIT); + x = fixintdiv(x, 2); + } + else + { + x = fixpow(2*FRACUNIT, fixintmul(-20, t) + 10*FRACUNIT); + x = fixintdiv((2*FRACUNIT) - x, 2); + } + } + + return fixinterp(start, end, x); +} + +// +// "Back" +// + +#define EASEBACKCONST1 111514 // 1.70158 +#define EASEBACKCONST2 99942 // 1.525 + +EASINGFUNC(InBack) +{ + const fixed_t c1 = EASEBACKCONST1; + const fixed_t c3 = c1 + FRACUNIT; + fixed_t x = FixedMul(FixedMul(t, t), FixedMul(c3, t) - c1); + return fixinterp(start, end, x); +} + +EASINGFUNC(OutBack) +{ + const fixed_t c1 = EASEBACKCONST1; + const fixed_t c3 = c1 + FRACUNIT; + fixed_t x; + t -= FRACUNIT; + x = FRACUNIT + FixedMul(FixedMul(t, t), FixedMul(c3, t) + c1); + return fixinterp(start, end, x); +} + +static fixed_t DoEaseInOutBack(fixed_t start, fixed_t end, fixed_t t, fixed_t c2) +{ + fixed_t x; + + c2 += FRACUNIT; + + if (t < FRACUNIT / 2) + { + x = fixintmul(7, t) - c2; + x = fixintmul(2, x); + x = FixedMul(FixedMul(t, t), x); + } + else + { + t -= FRACUNIT; + x = fixintmul(2, fixintmul(7, t) + c2); + x = FixedMul(FixedMul(t, t), x); + x = FRACUNIT + x; + } + + return fixinterp(start, end, x); +} + +EASINGFUNC(InOutBack) +{ + return DoEaseInOutBack(start, end, t, EASEBACKCONST2); +} + +#undef EASINGFUNC + +// Function list + +#define EASINGFUNC(type) Easing_ ## type +#define COMMA , + +easingfunc_t easing_funclist[EASE_MAX] = +{ + EASINGFUNCLIST(COMMA) +}; + +// Function names + +#undef EASINGFUNC +#define EASINGFUNC(type) #type + +const char *easing_funcnames[EASE_MAX] = +{ + EASINGFUNCLIST(COMMA) +}; + +#undef COMMA +#undef EASINGFUNC diff --git a/src/m_easing.h b/src/m_easing.h new file mode 100644 index 000000000..e5571ece3 --- /dev/null +++ b/src/m_easing.h @@ -0,0 +1,95 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. +// +// 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 m_easing.h +/// \brief Easing functions + +#ifndef __M_EASING_H__ +#define __M_EASING_H__ + +#include "doomtype.h" +#include "m_fixed.h" + +typedef enum +{ + EASE_LINEAR = 0, + + EASE_INSINE, + EASE_OUTSINE, + EASE_INOUTSINE, + + EASE_INQUAD, + EASE_OUTQUAD, + EASE_INOUTQUAD, + + EASE_INCUBIC, + EASE_OUTCUBIC, + EASE_INOUTCUBIC, + + EASE_INQUART, + EASE_OUTQUART, + EASE_INOUTQUART, + + EASE_INQUINT, + EASE_OUTQUINT, + EASE_INOUTQUINT, + + EASE_INEXPO, + EASE_OUTEXPO, + EASE_INOUTEXPO, + + EASE_INBACK, + EASE_OUTBACK, + EASE_INOUTBACK, + + EASE_MAX, +} easing_t; + +typedef fixed_t (*easingfunc_t)(fixed_t, fixed_t, fixed_t); + +extern easingfunc_t easing_funclist[EASE_MAX]; +extern const char *easing_funcnames[EASE_MAX]; + +#define EASINGFUNCLIST(sep) \ + EASINGFUNC(Linear) sep \ + \ + EASINGFUNC(InSine) sep \ + EASINGFUNC(OutSine) sep \ + EASINGFUNC(InOutSine) sep \ + \ + EASINGFUNC(InQuad) sep \ + EASINGFUNC(OutQuad) sep \ + EASINGFUNC(InOutQuad) sep \ + \ + EASINGFUNC(InCubic) sep \ + EASINGFUNC(OutCubic) sep \ + EASINGFUNC(InOutCubic) sep \ + \ + EASINGFUNC(InQuart) sep \ + EASINGFUNC(OutQuart) sep \ + EASINGFUNC(InOutQuart) sep \ + \ + EASINGFUNC(InQuint) sep \ + EASINGFUNC(OutQuint) sep \ + EASINGFUNC(InOutQuint) sep \ + \ + EASINGFUNC(InExpo) sep \ + EASINGFUNC(OutExpo) sep \ + EASINGFUNC(InOutExpo) sep \ + \ + EASINGFUNC(InBack) sep \ + EASINGFUNC(OutBack) sep \ + EASINGFUNC(InOutBack) sep + +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t start, fixed_t end, fixed_t t); + +EASINGFUNCLIST() + +#undef EASINGFUNC + +#endif From d8d3dee46f73d974310a5d18046497087a07a5ad Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 19 Apr 2021 17:20:34 -0400 Subject: [PATCH 099/241] Add linedef executor for toggling stagefailed By default, the executor will fail the stage. If Not Climbable is checked, the stage can be completed normally again. --- src/p_setup.c | 2 +- src/p_spec.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index 2e7db1055..ec516992e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3395,7 +3395,7 @@ static void P_InitLevelSettings(void) ssspheres = timeinmap = 0; // Assume Special Stages were failed in unless proven otherwise - via P_GiveEmerald or emerald touchspecial - // Normal stages will default to be OK, unless a Lua script sets to false. + // Normal stages will default to be OK, until a Lua script / linedef executor says otherwise. stagefailed = G_IsSpecialStage(gamemap); // Reset temporary record data diff --git a/src/p_spec.c b/src/p_spec.c index 226e58d15..be120b686 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3902,6 +3902,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 466: // Set level failure state + { + if (line->flags & ML_NOCLIMB) + { + stagefailed = false; + CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); + } + else + { + stagefailed = true; + CONS_Debug(DBG_GAMELOGIC, "Stage will end in failure...\n"); + } + } + break; + case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing PolyDoor(line); From 30e7455178f43661ad7508ce79fd90bb89020d0d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 19 Apr 2021 17:50:49 -0400 Subject: [PATCH 100/241] Failing a stage just displays the level title --- src/y_inter.c | 51 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index bd3b557d7..4b37b9f61 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1259,24 +1259,40 @@ void Y_StartIntermission(void) usetile = false; // set up the "got through act" message according to skin name - // too long so just show "YOU GOT THROUGH THE ACT" - if (strlen(skins[players[consoleplayer].skin].realname) > 13) + if (stagefailed) { - strcpy(data.coop.passed1, "you got"); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + strcpy(data.coop.passed1, mapheaderinfo[gamemap-1]->lvlttl); + + if (mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) + { + data.spec.passed2[0] = '\0'; + } + else + { + strcpy(data.coop.passed2, "Zone"); + } } - // long enough that "X GOT" won't fit so use "X PASSED THE ACT" - else if (strlen(skins[players[consoleplayer].skin].realname) > 8) - { - strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act"); - } - // length is okay for normal use else { - snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got", - skins[players[consoleplayer].skin].realname); - strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + // too long so just show "YOU GOT THROUGH THE ACT" + if (strlen(skins[players[consoleplayer].skin].realname) > 13) + { + strcpy(data.coop.passed1, "you got"); + strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + } + // long enough that "X GOT" won't fit so use "X PASSED THE ACT" + else if (strlen(skins[players[consoleplayer].skin].realname) > 8) + { + strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); + strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act"); + } + // length is okay for normal use + else + { + snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got", + skins[players[consoleplayer].skin].realname); + strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); + } } // set X positions @@ -1293,6 +1309,13 @@ void Y_StartIntermission(void) // The above value is not precalculated because it needs only be computed once // at the start of intermission, and precalculating it would preclude mods // changing the font to one of a slightly different width. + + if ((stagefailed) && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) + { + // Bit of a hack, offset so that the "Zone" text is right aligned like title cards. + data.coop.passedx2 = (data.coop.passedx1 + V_LevelNameWidth(data.coop.passed1)) - V_LevelNameWidth(data.coop.passed2); + } + break; } From 41f492f2f90225ed55c82c8bee377d0ae2365a4b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 19 Apr 2021 17:59:55 -0400 Subject: [PATCH 101/241] Don't award any potentially cheesable bonuses if the stage was failed. Time Bonus is 0'd out if the stage was failed, since you can defeat the whole point of it if the stage lets you fail it immediately. Same with Guard Bonus -- it's not really a no-hit run if you didn't interact with anything. Kept others that are more effort-based like Ring Bonus to give the player a little bit of partial credit, especially since Special Stages do this too. --- src/y_inter.c | 60 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 4b37b9f61..0627a3aa7 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1771,21 +1771,30 @@ static void Y_SetTimeBonus(player_t *player, y_bonus_t *bstruct) strncpy(bstruct->patch, "YB_TIME", sizeof(bstruct->patch)); bstruct->display = true; - // calculate time bonus - secs = player->realtime / TICRATE; - if (secs < 30) /* :30 */ bonus = 50000; - else if (secs < 60) /* 1:00 */ bonus = 10000; - else if (secs < 90) /* 1:30 */ bonus = 5000; - else if (secs < 120) /* 2:00 */ bonus = 4000; - else if (secs < 180) /* 3:00 */ bonus = 3000; - else if (secs < 240) /* 4:00 */ bonus = 2000; - else if (secs < 300) /* 5:00 */ bonus = 1000; - else if (secs < 360) /* 6:00 */ bonus = 500; - else if (secs < 420) /* 7:00 */ bonus = 400; - else if (secs < 480) /* 8:00 */ bonus = 300; - else if (secs < 540) /* 9:00 */ bonus = 200; - else if (secs < 600) /* 10:00 */ bonus = 100; - else /* TIME TAKEN: TOO LONG */ bonus = 0; + if (stagefailed == true) + { + // Time Bonus would be very easy to cheese by failing immediately. + bonus = 0; + } + else + { + // calculate time bonus + secs = player->realtime / TICRATE; + if (secs < 30) /* :30 */ bonus = 50000; + else if (secs < 60) /* 1:00 */ bonus = 10000; + else if (secs < 90) /* 1:30 */ bonus = 5000; + else if (secs < 120) /* 2:00 */ bonus = 4000; + else if (secs < 180) /* 3:00 */ bonus = 3000; + else if (secs < 240) /* 4:00 */ bonus = 2000; + else if (secs < 300) /* 5:00 */ bonus = 1000; + else if (secs < 360) /* 6:00 */ bonus = 500; + else if (secs < 420) /* 7:00 */ bonus = 400; + else if (secs < 480) /* 8:00 */ bonus = 300; + else if (secs < 540) /* 9:00 */ bonus = 200; + else if (secs < 600) /* 10:00 */ bonus = 100; + else /* TIME TAKEN: TOO LONG */ bonus = 0; + } + bstruct->points = bonus; } @@ -1838,12 +1847,21 @@ static void Y_SetGuardBonus(player_t *player, y_bonus_t *bstruct) strncpy(bstruct->patch, "YB_GUARD", sizeof(bstruct->patch)); bstruct->display = true; - if (player->timeshit == 0) bonus = 10000; - else if (player->timeshit == 1) bonus = 5000; - else if (player->timeshit == 2) bonus = 1000; - else if (player->timeshit == 3) bonus = 500; - else if (player->timeshit == 4) bonus = 100; - else bonus = 0; + if (stagefailed == true) + { + // "No-hit" runs would be very easy to cheese by failing immediately. + bonus = 0; + } + else + { + if (player->timeshit == 0) bonus = 10000; + else if (player->timeshit == 1) bonus = 5000; + else if (player->timeshit == 2) bonus = 1000; + else if (player->timeshit == 3) bonus = 500; + else if (player->timeshit == 4) bonus = 100; + else bonus = 0; + } + bstruct->points = bonus; } From 77b8578d04763398a60d372afcc834e05bc5fe77 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 19 Apr 2021 21:42:00 -0300 Subject: [PATCH 102/241] Add ease Lua library --- src/lua_mathlib.c | 119 +++++++++++++++++++++++++++++++++++++++++++++- src/m_easing.c | 63 +++++++++++++++++------- src/m_easing.h | 52 +++++++++++--------- 3 files changed, 193 insertions(+), 41 deletions(-) diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index b6046ab53..1b7113b36 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -16,6 +16,7 @@ #include "p_local.h" #include "doomstat.h" // for ALL7EMERALDS #include "r_main.h" // for R_PointToDist2 +#include "m_easing.h" #include "lua_script.h" #include "lua_libs.h" @@ -185,7 +186,7 @@ static int lib_coloropposite(lua_State *L) return 2; } -static luaL_Reg lib[] = { +static luaL_Reg lib_math[] = { {"abs", lib_abs}, {"min", lib_min}, {"max", lib_max}, @@ -223,9 +224,123 @@ static luaL_Reg lib[] = { {NULL, NULL} }; +// +// Easing functions +// + +#define EASINGFUNC(easetype) \ +{ \ + fixed_t start = 0; \ + fixed_t end = FRACUNIT; \ + fixed_t t = luaL_checkfixed(L, 1); \ + int n = lua_gettop(L); \ + if (n == 2) \ + end = luaL_checkfixed(L, 2); \ + else if (n >= 3) \ + { \ + start = luaL_checkfixed(L, 2); \ + end = luaL_checkfixed(L, 3); \ + } \ + lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \ + return 1; \ +} \ + +static int lib_easelinear(lua_State *L) { EASINGFUNC(Linear) } + +static int lib_easeinsine(lua_State *L) { EASINGFUNC(InSine) } +static int lib_easeoutsine(lua_State *L) { EASINGFUNC(OutSine) } +static int lib_easeinoutsine(lua_State *L) { EASINGFUNC(InOutSine) } + +static int lib_easeinquad(lua_State *L) { EASINGFUNC(InQuad) } +static int lib_easeoutquad(lua_State *L) { EASINGFUNC(OutQuad) } +static int lib_easeinoutquad(lua_State *L) { EASINGFUNC(InOutQuad) } + +static int lib_easeincubic(lua_State *L) { EASINGFUNC(InCubic) } +static int lib_easeoutcubic(lua_State *L) { EASINGFUNC(OutCubic) } +static int lib_easeinoutcubic(lua_State *L) { EASINGFUNC(InOutCubic) } + +static int lib_easeinquart(lua_State *L) { EASINGFUNC(InQuart) } +static int lib_easeoutquart(lua_State *L) { EASINGFUNC(OutQuart) } +static int lib_easeinoutquart(lua_State *L) { EASINGFUNC(InOutQuart) } + +static int lib_easeinquint(lua_State *L) { EASINGFUNC(InQuint) } +static int lib_easeoutquint(lua_State *L) { EASINGFUNC(OutQuint) } +static int lib_easeinoutquint(lua_State *L) { EASINGFUNC(InOutQuint) } + +static int lib_easeinexpo(lua_State *L) { EASINGFUNC(InExpo) } +static int lib_easeoutexpo(lua_State *L) { EASINGFUNC(OutExpo) } +static int lib_easeinoutexpo(lua_State *L) { EASINGFUNC(InOutExpo) } + +#undef EASINGFUNC + +#define EASINGFUNC(easetype) \ +{ \ + boolean useparam = false; \ + fixed_t param = 0; \ + fixed_t start = 0; \ + fixed_t end = FRACUNIT; \ + fixed_t t = luaL_checkfixed(L, 1); \ + int n = lua_gettop(L); \ + if (n == 2) \ + end = luaL_checkfixed(L, 2); \ + else if (n >= 3) \ + { \ + start = (fixed_t)luaL_optinteger(L, 2, start); \ + end = (fixed_t)luaL_optinteger(L, 3, end); \ + if ((n >= 4) && (useparam = (!lua_isnil(L, 4)))) \ + param = luaL_checkfixed(L, 4); \ + } \ + if (useparam) \ + lua_pushfixed(L, (Easing_ ## easetype ## Parameterized)(t, start, end, param)); \ + else \ + lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \ + return 1; \ +} \ + +static int lib_easeinback(lua_State *L) { EASINGFUNC(InBack) } +static int lib_easeoutback(lua_State *L) { EASINGFUNC(OutBack) } +static int lib_easeinoutback(lua_State *L) { EASINGFUNC(InOutBack) } + +#undef EASINGFUNC + +static luaL_Reg lib_ease[] = { + {"linear", lib_easelinear}, + + {"insine", lib_easeinsine}, + {"outsine", lib_easeoutsine}, + {"inoutsine", lib_easeinoutsine}, + + {"inquad", lib_easeinquad}, + {"outquad", lib_easeoutquad}, + {"inoutquad", lib_easeinoutquad}, + + {"incubic", lib_easeincubic}, + {"outcubic", lib_easeoutcubic}, + {"inoutcubic", lib_easeinoutcubic}, + + {"inquart", lib_easeinquart}, + {"outquart", lib_easeoutquart}, + {"inoutquart", lib_easeinoutquart}, + + {"inquint", lib_easeinquint}, + {"outquint", lib_easeoutquint}, + {"inoutquint", lib_easeinoutquint}, + + {"inexpo", lib_easeinexpo}, + {"outexpo", lib_easeoutexpo}, + {"inoutexpo", lib_easeinoutexpo}, + + {"inback", lib_easeinback}, + {"outback", lib_easeoutback}, + {"inoutback", lib_easeinoutback}, + + {NULL, NULL} +}; + int LUA_MathLib(lua_State *L) { lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_register(L, NULL, lib); + luaL_register(L, NULL, lib_math); + luaL_register(L, "ease", lib_ease); return 0; } diff --git a/src/m_easing.c b/src/m_easing.c index b3ea8842f..c871d3106 100644 --- a/src/m_easing.c +++ b/src/m_easing.c @@ -144,7 +144,11 @@ static INT32 fixexp(fixed_t a) #define fixintdiv(x, y) FixedDiv(x, (y) * FRACUNIT) #define fixinterp(start, end, t) FixedMul((FRACUNIT - (t)), start) + FixedMul(t, end) -#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t start, fixed_t end, fixed_t t) +// ================== +// EASING FUNCTIONS +// ================== + +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end) // // Linear @@ -327,17 +331,20 @@ EASINGFUNC(InOutExpo) #define EASEBACKCONST1 111514 // 1.70158 #define EASEBACKCONST2 99942 // 1.525 -EASINGFUNC(InBack) +static fixed_t EaseInBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c1) { - const fixed_t c1 = EASEBACKCONST1; const fixed_t c3 = c1 + FRACUNIT; fixed_t x = FixedMul(FixedMul(t, t), FixedMul(c3, t) - c1); return fixinterp(start, end, x); } -EASINGFUNC(OutBack) +EASINGFUNC(InBack) +{ + return EaseInBack(t, start, end, EASEBACKCONST1); +} + +static fixed_t EaseOutBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c1) { - const fixed_t c1 = EASEBACKCONST1; const fixed_t c3 = c1 + FRACUNIT; fixed_t x; t -= FRACUNIT; @@ -345,32 +352,56 @@ EASINGFUNC(OutBack) return fixinterp(start, end, x); } -static fixed_t DoEaseInOutBack(fixed_t start, fixed_t end, fixed_t t, fixed_t c2) +EASINGFUNC(OutBack) { - fixed_t x; + return EaseOutBack(t, start, end, EASEBACKCONST1); +} - c2 += FRACUNIT; +static fixed_t EaseInOutBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c2) +{ + fixed_t x, y; + const fixed_t f2 = 2*FRACUNIT; if (t < FRACUNIT / 2) { - x = fixintmul(7, t) - c2; - x = fixintmul(2, x); - x = FixedMul(FixedMul(t, t), x); + x = fixpow(FixedMul(t, f2), f2); + y = FixedMul(c2 + FRACUNIT, FixedMul(t, f2)); + x = FixedMul(x, y - c2); } else { - t -= FRACUNIT; - x = fixintmul(2, fixintmul(7, t) + c2); - x = FixedMul(FixedMul(t, t), x); - x = FRACUNIT + x; + x = fixpow(-(FixedMul(t, f2) - f2), f2); + y = FixedMul(c2 + FRACUNIT, FixedMul(t, f2) - f2); + x = FixedMul(x, y + c2); + x += f2; } + x /= 2; + return fixinterp(start, end, x); } EASINGFUNC(InOutBack) { - return DoEaseInOutBack(start, end, t, EASEBACKCONST2); + return EaseInOutBack(t, start, end, EASEBACKCONST2); +} + +#undef EASINGFUNC +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end, fixed_t param) + +EASINGFUNC(InBackParameterized) +{ + return EaseInBack(t, start, end, param); +} + +EASINGFUNC(OutBackParameterized) +{ + return EaseOutBack(t, start, end, param); +} + +EASINGFUNC(InOutBackParameterized) +{ + return EaseInOutBack(t, start, end, param); } #undef EASINGFUNC diff --git a/src/m_easing.h b/src/m_easing.h index e5571ece3..435ad35e7 100644 --- a/src/m_easing.h +++ b/src/m_easing.h @@ -56,40 +56,46 @@ extern easingfunc_t easing_funclist[EASE_MAX]; extern const char *easing_funcnames[EASE_MAX]; #define EASINGFUNCLIST(sep) \ - EASINGFUNC(Linear) sep \ + EASINGFUNC(Linear) sep /* Easing_Linear */ \ \ - EASINGFUNC(InSine) sep \ - EASINGFUNC(OutSine) sep \ - EASINGFUNC(InOutSine) sep \ + EASINGFUNC(InSine) sep /* Easing_InSine */ \ + EASINGFUNC(OutSine) sep /* Easing_OutSine */ \ + EASINGFUNC(InOutSine) sep /* Easing_InOutSine */ \ \ - EASINGFUNC(InQuad) sep \ - EASINGFUNC(OutQuad) sep \ - EASINGFUNC(InOutQuad) sep \ + EASINGFUNC(InQuad) sep /* Easing_InQuad */ \ + EASINGFUNC(OutQuad) sep /* Easing_OutQuad */ \ + EASINGFUNC(InOutQuad) sep /* Easing_InOutQuad */ \ \ - EASINGFUNC(InCubic) sep \ - EASINGFUNC(OutCubic) sep \ - EASINGFUNC(InOutCubic) sep \ + EASINGFUNC(InCubic) sep /* Easing_InCubic */ \ + EASINGFUNC(OutCubic) sep /* Easing_OutCubic */ \ + EASINGFUNC(InOutCubic) sep /* Easing_InOutCubic */ \ \ - EASINGFUNC(InQuart) sep \ - EASINGFUNC(OutQuart) sep \ - EASINGFUNC(InOutQuart) sep \ + EASINGFUNC(InQuart) sep /* Easing_InQuart */ \ + EASINGFUNC(OutQuart) sep /* Easing_OutQuart */ \ + EASINGFUNC(InOutQuart) sep /* Easing_InOutQuart */ \ \ - EASINGFUNC(InQuint) sep \ - EASINGFUNC(OutQuint) sep \ - EASINGFUNC(InOutQuint) sep \ + EASINGFUNC(InQuint) sep /* Easing_InQuint */ \ + EASINGFUNC(OutQuint) sep /* Easing_OutQuint */ \ + EASINGFUNC(InOutQuint) sep /* Easing_InOutQuint */ \ \ - EASINGFUNC(InExpo) sep \ - EASINGFUNC(OutExpo) sep \ - EASINGFUNC(InOutExpo) sep \ + EASINGFUNC(InExpo) sep /* Easing_InExpo */ \ + EASINGFUNC(OutExpo) sep /* Easing_OutExpo */ \ + EASINGFUNC(InOutExpo) sep /* Easing_InOutExpo */ \ \ - EASINGFUNC(InBack) sep \ - EASINGFUNC(OutBack) sep \ - EASINGFUNC(InOutBack) sep + EASINGFUNC(InBack) sep /* Easing_InBack */ \ + EASINGFUNC(OutBack) sep /* Easing_OutBack */ \ + EASINGFUNC(InOutBack) sep /* Easing_InOutBack */ -#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t start, fixed_t end, fixed_t t); +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end); EASINGFUNCLIST() #undef EASINGFUNC +#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end, fixed_t param); +EASINGFUNC(InBackParameterized) /* Easing_InBackParameterized */ +EASINGFUNC(OutBackParameterized) /* Easing_OutBackParameterized */ +EASINGFUNC(InOutBackParameterized) /* Easing_InOutBackParameterized */ + +#undef EASINGFUNC #endif From 6c4e7e13e09e2d0a93c019a0ca93985133afb038 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Mon, 14 Dec 2020 01:23:57 -0600 Subject: [PATCH 103/241] Allow Lua to disable the emeralds that appear in the Special Stage intermission. --- src/lua_hud.h | 1 + src/lua_hudlib.c | 1 + src/y_inter.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/lua_hud.h b/src/lua_hud.h index 1e9dca00b..4be20c815 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -38,6 +38,7 @@ enum hud { // Intermission hud_intermissiontally, hud_intermissionmessages, + hud_intermissionemeralds, hud_MAX }; diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 8d451e99c..51c7f91ae 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -64,6 +64,7 @@ static const char *const hud_disable_options[] = { "intermissiontally", "intermissionmessages", + "intermissionemeralds", NULL}; enum hudinfo { diff --git a/src/y_inter.c b/src/y_inter.c index dca8cd377..d6baf06c6 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -638,6 +638,7 @@ void Y_IntermissionDrawer(void) // draw the emeralds //if (intertic & 1) + if (LUA_HudEnabled(hud_intermissionemeralds)) { boolean drawthistic = !(ALL7EMERALDS(emeralds) && (intertic & 1)); INT32 emeraldx = 152 - 3*28; From aa54a04c9e38ae0fb4c0b4ed834a32258e1ec409 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 17 Dec 2020 02:30:57 -0600 Subject: [PATCH 104/241] Allow Lua to stop the intermission level title strings from drawing --- src/lua_hud.h | 1 + src/lua_hudlib.c | 1 + src/y_inter.c | 72 +++++++++++++++++++++++++++--------------------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/lua_hud.h b/src/lua_hud.h index 4be20c815..0a83b6de7 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -37,6 +37,7 @@ enum hud { hud_tabemblems, // Intermission hud_intermissiontally, + hud_intermissiontitletext, hud_intermissionmessages, hud_intermissionemeralds, hud_MAX diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 51c7f91ae..862ab4423 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -63,6 +63,7 @@ static const char *const hud_disable_options[] = { "tabemblems", "intermissiontally", + "intermissiontitletext", "intermissionmessages", "intermissionemeralds", NULL}; diff --git a/src/y_inter.c b/src/y_inter.c index d6baf06c6..6240663fa 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -471,14 +471,17 @@ void Y_IntermissionDrawer(void) } } - // draw the "got through act" lines and act number - V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1); + if (LUA_HudEnabled(hud_intermissiontitletext)) { - INT32 h = V_LevelNameHeight(data.coop.passed2); - V_DrawLevelTitle(data.coop.passedx2, 49+h+2, 0, data.coop.passed2); + // draw the "got through act" lines and act number + V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1); + { + INT32 h = V_LevelNameHeight(data.coop.passed2); + V_DrawLevelTitle(data.coop.passedx2, 49+h+2, 0, data.coop.passed2); - if (data.coop.actnum) - V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum); + if (data.coop.actnum) + V_DrawLevelActNum(244, 42+h, 0, data.coop.actnum); + } } bonusy = 150; @@ -562,37 +565,44 @@ void Y_IntermissionDrawer(void) if (drawsection == 1) { - const char *ringtext = "\x82" "50 rings, no shield"; - const char *tut1text = "\x82" "press " "\x80" "spin"; - const char *tut2text = "\x82" "mid-" "\x80" "jump"; - ttheight = 8; - V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); - ttheight += V_LevelNameHeight(data.spec.passed3) + 2; - V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); - ttheight += V_LevelNameHeight(data.spec.passed4) + 2; - V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4); + if (LUA_HudEnabled(hud_intermissiontitletext)) + { + const char *ringtext = "\x82" "50 rings, no shield"; + const char *tut1text = "\x82" "press " "\x80" "spin"; + const char *tut2text = "\x82" "mid-" "\x80" "jump"; + ttheight = 8; + V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); + ttheight += V_LevelNameHeight(data.spec.passed3) + 2; + V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); + ttheight += V_LevelNameHeight(data.spec.passed4) + 2; + V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4); - ttheight = 108; - V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext); - ttheight += V_LevelNameHeight(tut1text) + 2; - V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text); - ttheight += V_LevelNameHeight(tut2text) + 2; - V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text); + ttheight = 108; + V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext); + ttheight += V_LevelNameHeight(tut1text) + 2; + V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text); + ttheight += V_LevelNameHeight(tut2text) + 2; + V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text); + } } else { INT32 yoffset = 0; - if (data.spec.passed1[0] != '\0') + + if (LUA_HudEnabled(hud_intermissiontitletext)) { - ttheight = 24; - V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); - ttheight += V_LevelNameHeight(data.spec.passed2) + 2; - V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2); - } - else - { - ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2; - V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); + if (data.spec.passed1[0] != '\0') + { + ttheight = 24; + V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); + ttheight += V_LevelNameHeight(data.spec.passed2) + 2; + V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2); + } + else + { + ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2; + V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); + } } V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatches[0]); From 43c21edcbd9185dacb3f271a6c7d7733500951eb Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Thu, 17 Dec 2020 03:09:20 -0600 Subject: [PATCH 105/241] Send IntermissionThinker and intermission hud hooks `stagefailed`. --- src/lua_hook.h | 2 +- src/lua_hooklib.c | 7 +++++-- src/lua_hud.h | 2 +- src/lua_hudlib.c | 12 ++++++++---- src/y_inter.c | 4 ++-- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 0d631aa4e..fa6df2ee9 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -111,7 +111,7 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnM boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting -void LUAh_IntermissionThinker(void); // Hook for Y_Ticker +void LUAh_IntermissionThinker(boolean stagefailed); // Hook for Y_Ticker boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 1665e36b0..130fc0a28 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1633,7 +1633,7 @@ void LUAh_PlayerQuit(player_t *plr, kickreason_t reason) } // Hook for Y_Ticker -void LUAh_IntermissionThinker(void) +void LUAh_IntermissionThinker(boolean failedstage) { hook_p hookp; if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8)))) @@ -1646,8 +1646,11 @@ void LUAh_IntermissionThinker(void) if (hookp->type != hook_IntermissionThinker) continue; + lua_pushboolean(gL, failedstage); // stagefailed + PushHook(gL, hookp); - if (lua_pcall(gL, 0, 0, 1)) { + lua_pushvalue(gL, -2); // stagefailed + if (lua_pcall(gL, 1, 0, 1)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); diff --git a/src/lua_hud.h b/src/lua_hud.h index 0a83b6de7..a7f17aab5 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -51,4 +51,4 @@ void LUAh_GameHUD(player_t *stplyr); void LUAh_ScoresHUD(void); void LUAh_TitleHUD(void); void LUAh_TitleCardHUD(player_t *stplayr); -void LUAh_IntermissionHUD(void); +void LUAh_IntermissionHUD(boolean failedstage); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 862ab4423..3dacd121e 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1386,7 +1386,7 @@ void LUAh_TitleCardHUD(player_t *stplayr) hud_running = false; } -void LUAh_IntermissionHUD(void) +void LUAh_IntermissionHUD(boolean failedstage) { if (!gL || !(hudAvailable & (1< Date: Thu, 17 Dec 2020 12:26:27 -0600 Subject: [PATCH 106/241] Allow Lua to draw level title strings, and get the width and height of what would be drawn --- src/lua_hudlib.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 3dacd121e..951c63e54 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -859,6 +859,26 @@ static int libd_drawScaledNameTag(lua_State *L) return 0; } +static int libd_drawLevelTitle(lua_State *L) +{ + INT32 x; + INT32 y; + const char *str; + INT32 flags; + + HUDONLY + + x = luaL_checkinteger(L, 1); + y = luaL_checkinteger(L, 2); + str = luaL_checkstring(L, 3); + flags = luaL_optinteger(L, 4, 0); + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + + V_DrawLevelTitle(x, y, flags, str); + return 0; +} + static int libd_stringWidth(lua_State *L) { const char *str = luaL_checkstring(L, 1); @@ -888,6 +908,20 @@ static int libd_nameTagWidth(lua_State *L) return 1; } +static int libd_levelTitleWidth(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, V_LevelNameWidth(luaL_checkstring(L, 1))); + return 1; +} + +static int libd_levelTitleHeight(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, V_LevelNameHeight(luaL_checkstring(L, 1))); + return 1; +} + static int libd_getColormap(lua_State *L) { INT32 skinnum = TC_DEFAULT; @@ -1093,10 +1127,13 @@ static luaL_Reg lib_draw[] = { {"drawString", libd_drawString}, {"drawNameTag", libd_drawNameTag}, {"drawScaledNameTag", libd_drawScaledNameTag}, + {"drawLevelTitle", libd_drawLevelTitle}, {"fadeScreen", libd_fadeScreen}, // misc {"stringWidth", libd_stringWidth}, {"nameTagWidth", libd_nameTagWidth}, + {"levelTitleWidth", libd_levelTitleWidth}, + {"levelTitleHeight", libd_levelTitleHeight}, // m_random {"RandomFixed",libd_RandomFixed}, {"RandomByte",libd_RandomByte}, From 57d81ddb21464680d51854be890225c8bf321517 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 21 Apr 2021 19:58:14 -0400 Subject: [PATCH 107/241] Kart cmd->latency port Nev3r was talking about something that would've been drastically improved with this, and it is really simple, so I ported it :) --- src/d_ticcmd.h | 3 +++ src/g_demo.c | 12 ++++++++++++ src/g_game.c | 8 ++++++++ src/lua_playerlib.c | 6 ++++++ 4 files changed, 29 insertions(+) diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 2a5ef0981..04cbeef19 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -21,6 +21,8 @@ #pragma interface #endif +#define MAXPREDICTTICS 12 + // Button/action code definitions. typedef enum { @@ -63,6 +65,7 @@ typedef struct INT16 angleturn; // <<16 for angle delta - saved as 1 byte into demos INT16 aiming; // vertical aiming, see G_BuildTicCmd UINT16 buttons; + UINT8 latency; // Netgames: how many tics ago was this ticcmd generated from this player's end? } ATTRPACK ticcmd_t; #if defined(_MSC_VER) diff --git a/src/g_demo.c b/src/g_demo.c index 593fd7723..16477ab48 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -109,6 +109,7 @@ demoghost *ghosts = NULL; #define ZT_ANGLE 0x04 #define ZT_BUTTONS 0x08 #define ZT_AIMING 0x10 +#define ZT_LATENCY 0x20 #define DEMOMARKER 0x80 // demoend #define METALDEATH 0x44 #define METALSNICE 0x69 @@ -181,6 +182,8 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) oldcmd.buttons = (oldcmd.buttons & (BT_CAMLEFT|BT_CAMRIGHT)) | (READUINT16(demo_p) & ~(BT_CAMLEFT|BT_CAMRIGHT)); if (ziptic & ZT_AIMING) oldcmd.aiming = READINT16(demo_p); + if (ziptic & ZT_LATENCY) + oldcmd.latency = READUINT8(demo_p); G_CopyTiccmd(cmd, &oldcmd, 1); players[playernum].angleturn = cmd->angleturn; @@ -238,6 +241,13 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) ziptic |= ZT_AIMING; } + if (cmd->latency != oldcmd.latency) + { + WRITEUINT8(demo_p,cmd->latency); + oldcmd.latency = cmd->latency; + ziptic |= ZT_LATENCY; + } + *ziptic_p = ziptic; // attention here for the ticcmd size! @@ -679,6 +689,8 @@ void G_GhostTicker(void) g->p += 2; if (ziptic & ZT_AIMING) g->p += 2; + if (ziptic & ZT_LATENCY) + g->p++; // Grab ghost data. ziptic = READUINT8(g->p); diff --git a/src/g_game.c b/src/g_game.c index 13423ce77..c6b3292b0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1693,6 +1693,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->angleturn = origangle + extra; *myangle += extra << 16; *myaiming += (cmd->aiming - origaiming) << 16; + + // Send leveltime when this tic was generated to the server for control lag calculations. + // Only do this when in a level. Also do this after the hook, so that it can't overwrite this. + cmd->latency = (leveltime & 0xFF); } //Reset away view if a command is given. @@ -1724,6 +1728,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) dest[i].angleturn = SHORT(src[i].angleturn); dest[i].aiming = (INT16)SHORT(src[i].aiming); dest[i].buttons = (UINT16)SHORT(src[i].buttons); + dest[i].latency = src[i].latency; } return dest; } @@ -2306,6 +2311,9 @@ void G_Ticker(boolean run) players[i].cmd.angleturn &= ~TICCMD_RECEIVED; players[i].cmd.angleturn |= received; + + // Use the leveltime sent in the player's ticcmd to determine control lag + players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1); } } diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0eb54808f..d37d46c42 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -795,6 +795,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) static int ticcmd_get(lua_State *L) { @@ -813,6 +814,8 @@ static int ticcmd_get(lua_State *L) lua_pushinteger(L, cmd->aiming); else if (fastcmp(field,"buttons")) lua_pushinteger(L, cmd->buttons); + else if (fastcmp(field,"latency")) + lua_pushinteger(L, cmd->latency); else return NOFIELD; @@ -839,6 +842,8 @@ static int ticcmd_set(lua_State *L) cmd->aiming = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"buttons")) cmd->buttons = (UINT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"latency")) + return NOSET; else return NOFIELD; @@ -846,6 +851,7 @@ static int ticcmd_set(lua_State *L) } #undef NOFIELD +#undef NOSET int LUA_PlayerLib(lua_State *L) { From e510e71617a2102001d5038dbc48c7abdf855792 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Fri, 23 Apr 2021 15:50:48 -0400 Subject: [PATCH 108/241] Remove fire shield flash --- src/p_mobj.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 7ba6d1fad..59f306d1d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3283,11 +3283,9 @@ void P_MobjCheckWater(mobj_t *mobj) boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC); if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER) && !(mobj->eflags & MFE_TOUCHLAVA))) { // Water removes electric and non-water fire shields... - P_FlashPal(p, - electric - ? PAL_WHITE - : PAL_NUKE, - 1); + if (electric) + P_FlashPal(p, PAL_WHITE, 1); + p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; } } From 8278e621fb5cbe685c014c1e72c9145e9c906909 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Apr 2021 07:18:32 -0400 Subject: [PATCH 109/241] Removed skin->availability Locked skins now are a specific unlockable type, instead of being tied to the skin's properties. This has plagued custom gamedata since 2.2 launch. It's extremely obnoxious having to set aside random numbers as dummy unlockables just to ensure that Amy Fang & Metal are unlocked from the start in a custom map pack. Other changes made to accommodate this: - R_GetSkinAvailabilities is now created from the list of unlockables set to skin type. (1st skin unlockable defined is (1), 2nd skin unlockable defined is (1 << 1), etc...) - The "Added skin x" print shows up when loading addons but not at all for the base game, because the previous behavior of hiding based on if the skin was locked would now require iterating unlockables, which felt wrong to do during that stage of the loading process - I noticed in my test wad that Sonic&Tails would give you Sonic&Sonic out if Tails was locked. I fixed that by making both skins required to show the character select option. Mods that reserved empty dummy unlockables for Amy Fang and Metal won't have to do anything. Mods that wanted to re-lock them behind different requirements will have to update, but in the future they will not have to be in specific slots. Additionally, now Sonic Tails and Knuckles can also be locked for mods. --- src/d_netcmd.c | 26 ++++++++-- src/deh_soc.c | 23 ++++++--- src/lua_skinlib.c | 5 -- src/m_cond.h | 1 + src/m_menu.c | 9 +++- src/p_enemy.c | 29 +++++++++-- src/p_setup.c | 4 +- src/r_skins.c | 120 ++++++++++++++++++++++++++++++++++++---------- src/r_skins.h | 6 +-- src/r_things.c | 4 +- 10 files changed, 175 insertions(+), 52 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 09f9d4651..9261770c7 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1475,7 +1475,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer])) { boolean kick = false; - INT32 s; + UINT32 unlockShift = 0; + UINT32 i; // team colors if (G_GametypeHasTeams()) @@ -1491,12 +1492,29 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) kick = true; // availabilities - for (s = 0; s < MAXSKINS; s++) + for (i = 0; i < MAXUNLOCKABLES; i++) { - if (!skins[s].availability && (p->availabilities & (1 << s))) + if (unlockables[i].type != SECRET_SKIN) + { + continue; + } + + unlockShift++; + } + + // If they set an invalid bit to true, then likely a modified client + if (unlockShift < 32) // 32 is the max the data type allows + { + UINT32 illegalMask = UINT32_MAX; + + for (i = 0; i < unlockShift; i++) + { + illegalMask &= ~(1 << i); + } + + if ((p->availabilities & illegalMask) != 0) { kick = true; - break; } } diff --git a/src/deh_soc.c b/src/deh_soc.c index 5b12ea1b0..e5cba5185 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3219,19 +3219,30 @@ void readunlockable(MYFILE *f, INT32 num) unlockables[num].type = SECRET_WARP; else if (fastcmp(word2, "SOUNDTEST")) unlockables[num].type = SECRET_SOUNDTEST; + else if (fastcmp(word2, "SKIN")) + unlockables[num].type = SECRET_SKIN; else unlockables[num].type = (INT16)i; } else if (fastcmp(word, "VAR")) { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. + INT32 skinnum = R_SkinAvailable(word2); - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - i = M_MapNumber(word2[0], word2[1]); + if (skinnum != -1) + { + unlockables[num].variable = (INT16)skinnum; + } + else + { + // Support using the actual map name, + // i.e., Level AB, Level FZ, etc. - unlockables[num].variable = (INT16)i; + // Convert to map number + if (word2[0] >= 'A' && word2[0] <= 'Z') + i = M_MapNumber(word2[0], word2[1]); + + unlockables[num].variable = (INT16)i; + } } else deh_warning("Unlockable %d: unknown word '%s'", num+1, word); diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 56be6bf4f..f6c0879bd 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -53,7 +53,6 @@ enum skin { skin_contspeed, skin_contangle, skin_soundsid, - skin_availability, skin_sprites }; static const char *const skin_opt[] = { @@ -91,7 +90,6 @@ static const char *const skin_opt[] = { "contspeed", "contangle", "soundsid", - "availability", "sprites", NULL}; @@ -209,9 +207,6 @@ static int skin_get(lua_State *L) case skin_soundsid: LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID); break; - case skin_availability: - lua_pushinteger(L, skin->availability); - break; case skin_sprites: LUA_PushLightUserdata(L, skin->sprites, META_SKINSPRITES); break; diff --git a/src/m_cond.h b/src/m_cond.h index 9bb162ff3..08b47c63a 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -132,6 +132,7 @@ typedef struct #define SECRET_WARP 2 // Selectable warp #define SECRET_SOUNDTEST 3 // Sound Test #define SECRET_CREDITS 4 // Enables Credits +#define SECRET_SKIN 5 // Unlocks a skin // If you have more secrets than these variables allow in your game, // you seriously need to get a life. diff --git a/src/m_menu.c b/src/m_menu.c index 0fca39801..651dbecc6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8963,7 +8963,7 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) static UINT8 M_SetupChoosePlayerDirect(INT32 choice) { - INT32 skinnum; + INT32 skinnum, botskin; UINT8 i; UINT8 firstvalid = 255, lastvalid = 255; boolean allowed = false; @@ -8995,6 +8995,13 @@ static UINT8 M_SetupChoosePlayerDirect(INT32 choice) skinnum = description[i].skinnum[0]; if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) { + botskin = description[i].skinnum[1]; + if ((botskin != -1) && (!R_SkinUsable(-1, botskin))) + { + // Bot skin isn't unlocked + continue; + } + // Handling order. if (firstvalid == 255) firstvalid = i; diff --git a/src/p_enemy.c b/src/p_enemy.c index 59176d6cc..306b8b399 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -25,6 +25,7 @@ #include "i_video.h" #include "z_zone.h" #include "lua_hook.h" +#include "m_cond.h" // SECRET_SKIN #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -5101,6 +5102,28 @@ void A_SignSpin(mobj_t *actor) } } +static boolean SignSkinCheck(player_t *player, INT32 num) +{ + INT32 i; + + if (player != NULL) + { + // Use player's availabilities + return R_SkinUsable(player - players, num); + } + + // Player invalid, only show characters that are unlocked from the start. + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (unlockables[i].type == SECRET_SKIN && unlockables[i].variable == num) + { + return false; + } + } + + return true; +} + // Function: A_SignPlayer // // Description: Changes the state of a level end sign to reflect the player that hit it. @@ -5161,23 +5184,21 @@ void A_SignPlayer(mobj_t *actor) // I turned this function into a fucking mess. I'm so sorry. -Lach if (locvar1 == -2) // random skin { -#define skincheck(num) (player ? !R_SkinUsable(player-players, num) : skins[num].availability > 0) player_t *player = actor->target ? actor->target->player : NULL; UINT8 skinnum; UINT8 skincount = 0; for (skinnum = 0; skinnum < numskins; skinnum++) - if (!skincheck(skinnum)) + if (SignSkinCheck(player, skinnum)) skincount++; skinnum = P_RandomKey(skincount); for (skincount = 0; skincount < numskins; skincount++) { if (skincount > skinnum) break; - if (skincheck(skincount)) + if (!SignSkinCheck(player, skincount)) skinnum++; } skin = &skins[skinnum]; -#undef skincheck } else // specific skin skin = &skins[locvar1]; diff --git a/src/p_setup.c b/src/p_setup.c index 40dd1a284..ae68bac80 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4527,8 +4527,8 @@ boolean P_AddWadFile(const char *wadfilename) // // look for skins // - R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] - R_PatchSkins(wadnum); // toast: PATCH PATCH + R_AddSkins(wadnum, false); // faB: wadfile index in wadfiles[] + R_PatchSkins(wadnum, false); // toast: PATCH PATCH ST_ReloadSkinFaceGraphics(); // diff --git a/src/r_skins.c b/src/r_skins.c index 6f150f234..587259ae0 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -148,8 +148,6 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->contspeed = 17; skin->contangle = 0; - skin->availability = 0; - for (i = 0; i < sfx_skinsoundslot0; i++) if (S_sfx[i].skinsound != -1) skin->soundsid[S_sfx[i].skinsound] = i; @@ -176,14 +174,34 @@ void R_InitSkins(void) UINT32 R_GetSkinAvailabilities(void) { - INT32 s; UINT32 response = 0; + UINT32 unlockShift = 0; + INT32 i; - for (s = 0; s < MAXSKINS; s++) + for (i = 0; i < MAXUNLOCKABLES; i++) { - if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) - response |= (1 << s); + if (unlockables[i].type != SECRET_SKIN) + { + continue; + } + + if (unlockShift >= 32) + { + // 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"); + return 0; + } + + if (unlockables[i].unlocked) + { + response |= (1 << unlockShift); + } + + unlockShift++; } + return response; } @@ -191,14 +209,74 @@ UINT32 R_GetSkinAvailabilities(void) // warning don't use with an invalid skinnum other than -1 which always returns true boolean R_SkinUsable(INT32 playernum, INT32 skinnum) { - return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... - || (!skins[skinnum].availability) - || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) - || (modeattacking) // If you have someone else's run you might as well take a look - || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. - || (netgame && (cv_forceskin.value == skinnum)) // Force 2. - || (metalrecording && skinnum == 5) // Force 3. - ); + INT32 unlockID = -1; + UINT32 unlockShift = 0; + INT32 i; + + if (skinnum == -1) + { + // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... + return true; + } + + if (modeattacking) + { + // If you have someone else's run you might as well take a look + return true; + } + + if (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) + { + // Force 1. + return true; + } + + if (netgame && (cv_forceskin.value == skinnum)) + { + // Force 2. + return true; + } + + if (metalrecording && skinnum == 5) + { + // Force 3. + return true; + } + + // We will now check if this skin is supposed to be locked or not. + + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (unlockables[i].type != SECRET_SKIN) + { + continue; + } + + if (unlockables[i].variable == skinnum) + { + unlockID = i; + break; + } + + unlockShift++; + } + + if (unlockID == -1) + { + // This skin isn't locked at all, we're good. + return true; + } + + if ((netgame || multiplayer) && playernum != -1) + { + // We want to check per-player unlockables. + return (players[playernum].availabilities & (1 << unlockShift)); + } + else + { + // We want to check our global unlockables. + return (unlockables[unlockID].unlocked); + } } // returns true if the skin name is found (loaded from pwad) @@ -558,7 +636,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) // // Find skin sprites, sounds & optional status bar face, & add them // -void R_AddSkins(UINT16 wadnum) +void R_AddSkins(UINT16 wadnum, boolean mainfile) { UINT16 lump, lastlump = 0; char *buf; @@ -673,12 +751,6 @@ void R_AddSkins(UINT16 wadnum) if (!realname) STRBUFCPY(skin->realname, skin->hudname); } - else if (!stricmp(stoken, "availability")) - { - skin->availability = atoi(value); - if (skin->availability >= MAXUNLOCKABLES) - skin->availability = 0; - } else if (!R_ProcessPatchableFields(skin, stoken, value)) CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); @@ -693,7 +765,7 @@ next_token: R_FlushTranslationColormapCache(); - if (!skin->availability) // Safe to print... + if (mainfile == false) CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); #ifdef SKINVALUES skin_cons_t[numskins].value = numskins; @@ -713,7 +785,7 @@ next_token: // // Patch skin sprites // -void R_PatchSkins(UINT16 wadnum) +void R_PatchSkins(UINT16 wadnum, boolean mainfile) { UINT16 lump, lastlump = 0; char *buf; @@ -826,7 +898,7 @@ next_token: R_FlushTranslationColormapCache(); - if (!skin->availability) // Safe to print... + if (mainfile == false) CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); } return; diff --git a/src/r_skins.h b/src/r_skins.h index fbbb38743..5efd70307 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -80,8 +80,6 @@ typedef struct // contains super versions too spritedef_t sprites[NUMPLAYERSPRITES*2]; spriteinfo_t sprinfo[NUMPLAYERSPRITES*2]; - - UINT8 availability; // lock? } skin_t; /// Externs @@ -96,8 +94,8 @@ void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 boolean R_SkinUsable(INT32 playernum, INT32 skinnum); UINT32 R_GetSkinAvailabilities(void); INT32 R_SkinAvailable(const char *name); -void R_PatchSkins(UINT16 wadnum); -void R_AddSkins(UINT16 wadnum); +void R_AddSkins(UINT16 wadnum, boolean mainfile); +void R_PatchSkins(UINT16 wadnum, boolean mainfile); UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); diff --git a/src/r_things.c b/src/r_things.c index a7c44c237..c5cf3aeae 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -547,8 +547,8 @@ void R_InitSprites(void) R_InitSkins(); for (i = 0; i < numwadfiles; i++) { - R_AddSkins((UINT16)i); - R_PatchSkins((UINT16)i); + R_AddSkins((UINT16)i, true); + R_PatchSkins((UINT16)i, true); R_LoadSpriteInfoLumps(i, wadfiles[i]->numlumps); } ST_ReloadSkinFaceGraphics(); From 382c0aa7de42b38e647bdfd3b157ff239d1bb5fc Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Apr 2021 16:27:15 -0400 Subject: [PATCH 110/241] Fix overshadowed declaration --- 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 651dbecc6..eb330c9e9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8963,7 +8963,7 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) static UINT8 M_SetupChoosePlayerDirect(INT32 choice) { - INT32 skinnum, botskin; + INT32 skinnum, botskinnum; UINT8 i; UINT8 firstvalid = 255, lastvalid = 255; boolean allowed = false; @@ -8995,8 +8995,8 @@ static UINT8 M_SetupChoosePlayerDirect(INT32 choice) skinnum = description[i].skinnum[0]; if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) { - botskin = description[i].skinnum[1]; - if ((botskin != -1) && (!R_SkinUsable(-1, botskin))) + botskinnum = description[i].skinnum[1]; + if ((botskinnum != -1) && (!R_SkinUsable(-1, botskinnum))) { // Bot skin isn't unlocked continue; From f0b9e0e415982f5dfee3942bb8cbdabc80a2b16f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Apr 2021 16:38:33 -0400 Subject: [PATCH 111/241] Default to first usable skin instead of 0, I_Error if none are usable --- src/r_skins.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/r_skins.c b/src/r_skins.c index 587259ae0..758d0980d 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -294,6 +294,23 @@ INT32 R_SkinAvailable(const char *name) return -1; } +// Gets the player to the first usuable skin in the game. (If your mod locked them all, then you kinda stupid) +void SetPlayerDefaultSkin(INT32 playernum) +{ + INT32 i; + + for (i = 0; i < numskins; i++) + { + if (R_SkinUsable(playernum, i)) + { + SetPlayerSkinByNum(playernum, i); + return; + } + } + + I_Error("All characters are locked."); +} + // network code calls this when a 'skin change' is received void SetPlayerSkin(INT32 playernum, const char *skinname) { @@ -311,7 +328,7 @@ void SetPlayerSkin(INT32 playernum, const char *skinname) else if(server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); - SetPlayerSkinByNum(playernum, 0); + SetPlayerDefaultSkin(playernum); } // Same as SetPlayerSkin, but uses the skin #. @@ -402,7 +419,8 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum); else if(server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); - SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin + + SetPlayerDefaultSkin(playernum); } // From 92107f28d5dc48e7cb01f0c274aef85911f0ebdd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Apr 2021 17:54:47 -0400 Subject: [PATCH 112/241] Add string variable for unlockables and emblems Skin unlockables / skin emblems are now checked at runtime to see if there's any matches. --- src/d_netcmd.c | 5 +++-- src/deh_soc.c | 54 +++++++++++++++++++++++++++++++++++++------------- src/deh_soc.h | 2 ++ src/dehacked.c | 7 ++----- src/m_cond.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ src/m_cond.h | 5 +++++ src/p_enemy.c | 9 +++++++-- src/p_mobj.c | 16 +++++++++++++-- src/r_skins.c | 25 +++++++++++++++-------- src/r_skins.h | 2 ++ 10 files changed, 140 insertions(+), 33 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9261770c7..17ab52eb5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1313,8 +1313,9 @@ static void SendNameAndColor(void) cv_skin.value = R_SkinAvailable(cv_skin.string); if ((cv_skin.value < 0) || !R_SkinUsable(consoleplayer, cv_skin.value)) { - CV_StealthSet(&cv_skin, DEFAULTSKIN); - cv_skin.value = 0; + INT32 defaultSkinNum = GetPlayerDefaultSkin(consoleplayer); + CV_StealthSet(&cv_skin, skins[defaultSkinNum].name); + cv_skin.value = defaultSkinNum; } // Finally write out the complete packet and send it off. diff --git a/src/deh_soc.c b/src/deh_soc.c index e5cba5185..1dde6c9f0 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -127,6 +127,33 @@ static float searchfvalue(const char *s) #endif // These are for clearing all of various things +void clear_emblems(void) +{ + INT32 i; + + for (i = 0; i < MAXEMBLEMS; ++i) + { + Z_Free(emblemlocations[i].stringVar); + emblemlocations[i].stringVar = NULL; + } + + memset(&emblemlocations, 0, sizeof(emblemlocations)); + numemblems = 0; +} + +void clear_unlockables(void) +{ + INT32 i; + + for (i = 0; i < MAXUNLOCKABLES; ++i) + { + Z_Free(unlockables[i].stringVar); + unlockables[i].stringVar = NULL; + } + + memset(&unlockables, 0, sizeof(unlockables)); +} + void clear_conditionsets(void) { UINT8 i; @@ -3017,7 +3044,12 @@ void reademblemdata(MYFILE *f, INT32 num) else if (fastcmp(word, "COLOR")) emblemlocations[num-1].color = get_number(word2); else if (fastcmp(word, "VAR")) + { + Z_Free(emblemlocations[num-1].stringVar); + emblemlocations[num-1].stringVar = Z_StrDup(word2); + emblemlocations[num-1].var = get_number(word2); + } else deh_warning("Emblem %d: unknown word '%s'", num, word); } @@ -3226,23 +3258,17 @@ void readunlockable(MYFILE *f, INT32 num) } else if (fastcmp(word, "VAR")) { - INT32 skinnum = R_SkinAvailable(word2); + Z_Free(unlockables[num].stringVar); + unlockables[num].stringVar = Z_StrDup(word2); - if (skinnum != -1) - { - unlockables[num].variable = (INT16)skinnum; - } - else - { - // Support using the actual map name, - // i.e., Level AB, Level FZ, etc. + // Support using the actual map name, + // i.e., Level AB, Level FZ, etc. - // Convert to map number - if (word2[0] >= 'A' && word2[0] <= 'Z') - i = M_MapNumber(word2[0], word2[1]); + // Convert to map number + if (word2[0] >= 'A' && word2[0] <= 'Z') + i = M_MapNumber(word2[0], word2[1]); - unlockables[num].variable = (INT16)i; - } + unlockables[num].variable = (INT16)i; } else deh_warning("Unlockable %d: unknown word '%s'", num+1, word); diff --git a/src/deh_soc.h b/src/deh_soc.h index 2bcb52e70..9a3b0884d 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -84,6 +84,8 @@ void readskincolor(MYFILE *f, INT32 num); void readthing(MYFILE *f, INT32 num); void readfreeslots(MYFILE *f); void readPlayer(MYFILE *f, INT32 num); +void clear_emblems(void); +void clear_unlockables(void); void clear_levels(void); void clear_conditionsets(void); #endif diff --git a/src/dehacked.c b/src/dehacked.c index c2ea28d27..a68537f77 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -562,13 +562,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) } if (clearall || fastcmp(word2, "UNLOCKABLES")) - memset(&unlockables, 0, sizeof(unlockables)); + clear_unlockables(); if (clearall || fastcmp(word2, "EMBLEMS")) - { - memset(&emblemlocations, 0, sizeof(emblemlocations)); - numemblems = 0; - } + clear_emblems(); if (clearall || fastcmp(word2, "EXTRAEMBLEMS")) { diff --git a/src/m_cond.c b/src/m_cond.c index 36fcd7cf2..ee8e96d64 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -496,6 +496,54 @@ UINT8 M_GotHighEnoughRings(INT32 trings) return false; } +// Gets the skin number for a SECRET_SKIN unlockable. +INT32 M_UnlockableSkinNum(unlockable_t *unlock) +{ + if (unlock->type != SECRET_SKIN) + { + // This isn't a skin unlockable... + return -1; + } + + if (unlock->stringVar && strcmp(unlock->stringVar, "")) + { + // Get the skin from the string. + return R_SkinAvailable(unlock->stringVar); + } + else if (unlock->variable >= 0 && unlock->variable < numskins) + { + // Use the number directly. + return unlock->variable; + } + + // Invalid skin unlockable. + return -1; +} + +// Gets the skin number for a ET_SKIN emblem. +INT32 M_EmblemSkinNum(emblem_t *emblem) +{ + if (emblem->type != ET_SKIN) + { + // This isn't a skin emblem... + return -1; + } + + if (emblem->stringVar && strcmp(emblem->stringVar, "")) + { + // Get the skin from the string. + return R_SkinAvailable(emblem->stringVar); + } + else if (emblem->var >= 0 && emblem->var < numskins) + { + // Use the number directly. + return emblem->var; + } + + // Invalid skin emblem. + return -1; +} + // ---------------- // Misc Emblem shit // ---------------- diff --git a/src/m_cond.h b/src/m_cond.h index 08b47c63a..8003433a7 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -92,6 +92,7 @@ typedef struct UINT8 sprite; ///< emblem sprite to use, 0 - 25 UINT16 color; ///< skincolor to use 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; @@ -116,6 +117,7 @@ typedef struct UINT8 showconditionset; INT16 type; INT16 variable; + char *stringVar; UINT8 nocecho; UINT8 nochecklist; UINT8 unlocked; @@ -186,4 +188,7 @@ UINT8 M_GotHighEnoughScore(INT32 tscore); UINT8 M_GotLowEnoughTime(INT32 tictime); UINT8 M_GotHighEnoughRings(INT32 trings); +INT32 M_UnlockableSkinNum(unlockable_t *unlock); +INT32 M_EmblemSkinNum(emblem_t *emblem); + #define M_Achieved(a) ((a) >= MAXCONDITIONSETS || conditionSets[a].achieved) diff --git a/src/p_enemy.c b/src/p_enemy.c index 306b8b399..44dace26f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5115,9 +5115,14 @@ static boolean SignSkinCheck(player_t *player, INT32 num) // Player invalid, only show characters that are unlocked from the start. for (i = 0; i < MAXUNLOCKABLES; i++) { - if (unlockables[i].type == SECRET_SKIN && unlockables[i].variable == num) + if (unlockables[i].type == SECRET_SKIN) { - return false; + INT32 lockedSkin = M_UnlockableSkinNum(&unlockables[i]); + + if (lockedSkin == num) + { + return false; + } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 49db6daee..540642134 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11964,6 +11964,7 @@ 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) { @@ -11988,8 +11989,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; - if (emblemlocations[j].collected - || (emblemlocations[j].type == ET_SKIN && emblemlocations[j].var != players[0].skin)) + validEmblem = !emblemlocations[j].collected; + + if (emblemlocations[j].type == ET_SKIN) + { + INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]); + + if (players[0].skin != skinnum) + { + validEmblem = false; + } + } + + if (validEmblem == false) { P_UnsetThingPosition(mobj); mobj->flags |= MF_NOCLIP; diff --git a/src/r_skins.c b/src/r_skins.c index 758d0980d..d6021ebbc 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -247,12 +247,16 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) for (i = 0; i < MAXUNLOCKABLES; i++) { + INT32 unlockSkin = -1; + if (unlockables[i].type != SECRET_SKIN) { continue; } - if (unlockables[i].variable == skinnum) + unlockSkin = M_UnlockableSkinNum(&unlockables[i]); + + if (unlockSkin == skinnum) { unlockID = i; break; @@ -294,8 +298,7 @@ INT32 R_SkinAvailable(const char *name) return -1; } -// Gets the player to the first usuable skin in the game. (If your mod locked them all, then you kinda stupid) -void SetPlayerDefaultSkin(INT32 playernum) +INT32 GetPlayerDefaultSkin(INT32 playernum) { INT32 i; @@ -303,12 +306,18 @@ void SetPlayerDefaultSkin(INT32 playernum) { if (R_SkinUsable(playernum, i)) { - SetPlayerSkinByNum(playernum, i); - return; + return i; } } - I_Error("All characters are locked."); + I_Error("All characters are locked!"); + return 0; +} + +// Gets the player to the first usuable skin in the game. (If your mod locked them all, then you kinda stupid) +void SetPlayerDefaultSkin(INT32 playernum) +{ + SetPlayerSkinByNum(playernum, GetPlayerDefaultSkin(playernum)); } // network code calls this when a 'skin change' is received @@ -325,7 +334,7 @@ void SetPlayerSkin(INT32 playernum, const char *skinname) if (P_IsLocalPlayer(player)) CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); - else if(server || IsPlayerAdmin(consoleplayer)) + else if (server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); SetPlayerDefaultSkin(playernum); @@ -417,7 +426,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (P_IsLocalPlayer(player)) CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum); - else if(server || IsPlayerAdmin(consoleplayer)) + else if (server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); SetPlayerDefaultSkin(playernum); diff --git a/src/r_skins.h b/src/r_skins.h index 5efd70307..675eac5cc 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -89,6 +89,8 @@ extern skin_t skins[MAXSKINS]; /// Function prototypes void R_InitSkins(void); +INT32 GetPlayerDefaultSkin(INT32 playernum); +void SetPlayerDefaultSkin(INT32 playernum); void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 boolean R_SkinUsable(INT32 playernum, INT32 skinnum); From 4bafd622716f74df2c5d0b71a317c27257b83b4d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Apr 2021 18:44:07 -0400 Subject: [PATCH 113/241] Only return skin string number if it existed --- src/m_cond.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/m_cond.c b/src/m_cond.c index ee8e96d64..2fc730d3f 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -508,9 +508,14 @@ INT32 M_UnlockableSkinNum(unlockable_t *unlock) if (unlock->stringVar && strcmp(unlock->stringVar, "")) { // Get the skin from the string. - return R_SkinAvailable(unlock->stringVar); + INT32 skinnum = R_SkinAvailable(unlock->stringVar); + if (skinnum != -1) + { + return skinnum; + } } - else if (unlock->variable >= 0 && unlock->variable < numskins) + + if (unlock->variable >= 0 && unlock->variable < numskins) { // Use the number directly. return unlock->variable; @@ -532,9 +537,14 @@ INT32 M_EmblemSkinNum(emblem_t *emblem) if (emblem->stringVar && strcmp(emblem->stringVar, "")) { // Get the skin from the string. - return R_SkinAvailable(emblem->stringVar); + INT32 skinnum = R_SkinAvailable(emblem->stringVar); + if (skinnum != -1) + { + return skinnum; + } } - else if (emblem->var >= 0 && emblem->var < numskins) + + if (emblem->var >= 0 && emblem->var < numskins) { // Use the number directly. return emblem->var; From 7cd41a8eb7ef8285255a65d5c1776608e77a486d Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Mon, 26 Apr 2021 03:48:38 -0400 Subject: [PATCH 114/241] Compile with -rdynamic on UNIXCOMMON platforms --- src/sdl/MakeNIX.cfg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sdl/MakeNIX.cfg b/src/sdl/MakeNIX.cfg index 47c944eb5..c2f3ff0b6 100644 --- a/src/sdl/MakeNIX.cfg +++ b/src/sdl/MakeNIX.cfg @@ -18,9 +18,11 @@ endif # #here is GNU/Linux and other # - OPTS=-DUNIXCOMMON +#Use -rdynamic so a backtrace log shows function names instead of addresses + LDFLAGS+=-rdynamic + #LDFLAGS = -L/usr/local/lib LIBS=-lm ifdef LINUX From f437d6afec08bebab2d44f0d383c316f11df4934 Mon Sep 17 00:00:00 2001 From: Vincent Robinson Date: Mon, 26 Apr 2021 16:27:39 -0700 Subject: [PATCH 115/241] Add linedef specials for multitagging in binary maps --- extras/conf/SRB2-22.cfg | 18 ++++++++++++++++++ src/p_setup.c | 21 +++++++++++++++++++++ src/taglist.c | 6 ++++-- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 3fd4b6ccd..9a8484df5 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -640,6 +640,24 @@ linedeftypes prefix = "(63)"; } + 97 + { + title = "Apply Tag to Front Sector"; + prefix = "(97)"; + } + + 98 + { + title = "Apply Tag to Back Sector"; + prefix = "(98)"; + } + + 99 + { + title = "Apply Tag to Front and Back Sectors"; + prefix = "(99)"; + } + 540 { title = "Floor Friction"; diff --git a/src/p_setup.c b/src/p_setup.c index 40dd1a284..1b060660d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2950,6 +2950,24 @@ static void P_LinkMapData(void) } } +// For maps in binary format, add multi-tags from linedef specials. This must be done +// before any linedef specials have been processed. +static void P_AddBinaryMapTags(void) +{ + size_t i; + + for (i = 0; i < numlines; i++) + { + // 97: Apply Tag to Front Sector + // 98: Apply Tag to Back Sector + // 99: Apply Tag to Front and Back Sectors + if (lines[i].special == 97 || lines[i].special == 99) + Tag_Add(&lines[i].frontsector->tags, Tag_FGet(&lines[i].tags)); + if (lines[i].special == 98 || lines[i].special == 99) + Tag_Add(&lines[i].backsector->tags, Tag_FGet(&lines[i].tags)); + } +} + //For maps in binary format, converts setup of specials to UDMF format. static void P_ConvertBinaryMap(void) { @@ -3287,6 +3305,9 @@ static boolean P_LoadMapFromFile(void) P_LinkMapData(); + if (!udmf) + P_AddBinaryMapTags(); + Taglist_InitGlobalTables(); if (!udmf) diff --git a/src/taglist.c b/src/taglist.c index a759f4d02..e8b64d3f4 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -27,11 +27,13 @@ taggroup_t* tags_sectors[MAXTAGS + 1]; taggroup_t* tags_lines[MAXTAGS + 1]; taggroup_t* tags_mapthings[MAXTAGS + 1]; -/// Adds a tag to a given element's taglist. +/// Adds a tag to a given element's taglist. It will not add a duplicate. /// \warning This does not rebuild the global taggroups, which are used for iteration. void Tag_Add (taglist_t* list, const mtag_t tag) { - list->tags = Z_Realloc(list->tags, (list->count + 1) * sizeof(list->tags), PU_LEVEL, NULL); + if (Tag_Find(list, tag)) + return; + list->tags = Z_Realloc(list->tags, (list->count + 1) * sizeof(mtag_t), PU_LEVEL, NULL); list->tags[list->count++] = tag; } From 85c53b35cd3a00ddd8d30fbca15499e3b529179b Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 26 Apr 2021 22:17:03 -0300 Subject: [PATCH 116/241] Use old routine for PO2 spans --- src/r_plane.c | 108 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 10d87b9cc..ea5a7a3c3 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -789,6 +789,78 @@ static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_ R_CalculateSlopeVectors(); } +/* + Essentially: We can't & the components along the regular axes when the plane is rotated. + This is because the distance on each regular axis in order to loop is different. + We rotate them, & the components, add them together, & them again, and then rotate them back. + These three seperate & operations are done per axis in order to prevent overflows. + toast 10/04/17 +*/ +static inline void R_AdjustSlopeCoordinates(visplane_t *pl) +{ + const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + + const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); + + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + + fixed_t temp = ox & modmask; + oy &= modmask; + + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + + if (xoffs || yoffs) + { + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + + temp = xoffs & modmask; + yoffs &= modmask; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + } + + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); +} + +static inline void R_AdjustSlopeCoordinatesNPO2(visplane_t *pl) +{ + const fixed_t modmaskw = (ds_flatwidth << FRACBITS); + const fixed_t modmaskh = (ds_flatheight << FRACBITS); + + const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); + + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,sinecomponent) % modmaskh); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,cosinecomponent) % modmaskh); + + fixed_t temp = ox % modmaskw; + oy %= modmaskh; + + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + + if (xoffs || yoffs) + { + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) % modmaskw) + (FixedMul(yoffs,sinecomponent) % modmaskh); + yoffs = (-FixedMul(temp,sinecomponent) % modmaskw) + (FixedMul(yoffs,cosinecomponent) % modmaskh); + + temp = xoffs % modmaskw; + yoffs %= modmaskh; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + } + + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); +} + void R_DrawSinglePlane(visplane_t *pl) { levelflat_t *levelflat; @@ -967,38 +1039,10 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - const fixed_t modmaskw = (ds_powersoftwo) ? (ds_flatwidth << FRACBITS) - 1 : (signed)(0xFFFFFFFF); - const fixed_t modmaskh = (ds_powersoftwo) ? (ds_flatheight << FRACBITS) - 1 : (signed)(0xFFFFFFFF); - - /* - Essentially: We can't & the components along the regular axes when the plane is rotated. - This is because the distance on each regular axis in order to loop is different. - We rotate them, & the components, add them together, & them again, and then rotate them back. - These three seperate & operations are done per axis in order to prevent overflows. - toast 10/04/17 - */ - const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); - - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmaskw) - (FixedMul(pl->slope->o.y,sinecomponent) & modmaskh); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmaskw) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmaskh); - - fixed_t temp = ox & modmaskw; - oy &= modmaskh; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmaskw) + (FixedMul(yoffs,sinecomponent) & modmaskh); - yoffs = (-FixedMul(temp,sinecomponent) & modmaskw) + (FixedMul(yoffs,cosinecomponent) & modmaskh); - - temp = xoffs & modmaskw; - yoffs &= modmaskh; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); + if (ds_powersoftwo) + R_AdjustSlopeCoordinates(pl); + else + R_AdjustSlopeCoordinatesNPO2(pl); if (planeripple.active) { From 548554431b945d684725459bab14a6a00951244f Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 27 Apr 2021 00:20:41 -0300 Subject: [PATCH 117/241] Handle invalid blend modes properly --- src/hardware/hw_main.c | 15 ++++++--------- src/hardware/hw_main.h | 2 +- src/lua_mobjlib.c | 8 +++++++- src/r_draw.c | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e94c637e4..41de5ddcf 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -712,13 +712,12 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) #endif //doplanes -FBITFIELD HWR_GetBlendModeFlag(INT32 ast) +FBITFIELD HWR_GetBlendModeFlag(INT32 style) { - switch (ast) + switch (style) { - case AST_COPY: - case AST_OVERLAY: - return PF_Masked; + case AST_TRANSLUCENT: + return PF_Translucent; case AST_ADD: return PF_Additive; case AST_SUBTRACT: @@ -728,10 +727,8 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast) case AST_MODULATE: return PF_Multiplicative; default: - return PF_Translucent; + return PF_Masked; } - - return 0; } UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) @@ -757,7 +754,7 @@ UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf) { - if (!transtablenum || style == AST_COPY || style == AST_OVERLAY) + if (!transtablenum || style <= AST_COPY || style >= AST_OVERLAY) { pSurf->PolyColor.s.alpha = 0xff; return PF_Masked; diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4ad09aa3d..2c7d237bf 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -69,7 +69,7 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work UINT8 HWR_GetTranstableAlpha(INT32 transtablenum); -FBITFIELD HWR_GetBlendModeFlag(INT32 ast); +FBITFIELD HWR_GetBlendModeFlag(INT32 style); FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf); FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 65adceb15..994f6a789 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -12,6 +12,7 @@ #include "doomdef.h" #include "fastcmp.h" +#include "r_data.h" #include "r_skins.h" #include "p_local.h" #include "g_game.h" @@ -654,8 +655,13 @@ static int mobj_set(lua_State *L) break; } case mobj_blendmode: - mo->blendmode = (INT32)luaL_checkinteger(L, 3); + { + INT32 blendmode = (INT32)luaL_checkinteger(L, 3); + if (blendmode < 0 || blendmode > AST_OVERLAY) + return luaL_error(L, "mobj.blendmode %d out of range (0 - %d).", blendmode, AST_OVERLAY); + mo->blendmode = blendmode; break; + } case mobj_bnext: return NOSETPOS; case mobj_bprev: diff --git a/src/r_draw.c b/src/r_draw.c index 9a835ee58..1d2d8352f 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -341,7 +341,7 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel) { size_t offs; - if (style == AST_COPY || style == AST_OVERLAY) + if (style <= AST_COPY || style >= AST_OVERLAY) return NULL; offs = (ClipBlendLevel(style, alphalevel) << FF_TRANSSHIFT); @@ -371,7 +371,7 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel) boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel) { - if (blendmode == AST_COPY || blendmode == AST_SUBTRACT || blendmode == AST_MODULATE || blendmode == AST_OVERLAY) + if (blendmode <= AST_COPY || blendmode == AST_SUBTRACT || blendmode == AST_MODULATE || blendmode >= AST_OVERLAY) return true; return (alphalevel < BlendTab_Count[BlendTab_FromStyle[blendmode]]); From e4b8dc6584de4fed284cb14801b2dbb9b6dcafe6 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 27 Apr 2021 19:01:09 -0300 Subject: [PATCH 118/241] Fix sloped plane offsets in Software, and fix rotated flat alignment in OpenGL. + unrelated slope plane optimizations in Software --- src/hardware/hw_main.c | 31 ++-- src/r_draw.h | 2 +- src/r_plane.c | 313 +++++++++++++++++++++-------------------- src/r_plane.h | 4 +- 4 files changed, 170 insertions(+), 180 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index f2af1cc40..b261c6460 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -362,10 +362,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool float fflatwidth = 64.0f, fflatheight = 64.0f; INT32 flatflag = 63; boolean texflat = false; - float scrollx = 0.0f, scrolly = 0.0f; + float scrollx = 0.0f, scrolly = 0.0f, anglef = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; - fixed_t tempxsow, tempytow; + float tempxsow, tempytow; pslope_t *slope = NULL; static FOutVector *planeVerts = NULL; @@ -499,24 +499,15 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool } } - if (angle) // Only needs to be done if there's an altered angle { + tempxsow = flatxref; + tempytow = flatyref; - angle = (InvAngle(angle))>>ANGLETOFINESHIFT; + anglef = ANG2RAD(InvAngle(angle)); - // This needs to be done so that it scrolls in a different direction after rotation like software - /*tempxsow = FLOAT_TO_FIXED(scrollx); - tempytow = FLOAT_TO_FIXED(scrolly); - scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));*/ - - // This needs to be done so everything aligns after rotation - // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does - tempxsow = FLOAT_TO_FIXED(flatxref); - tempytow = FLOAT_TO_FIXED(flatyref); - flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef)); + flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef)); } #define SETUP3DVERT(vert, vx, vy) {\ @@ -535,10 +526,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool /* Need to rotate before translate */\ if (angle) /* Only needs to be done if there's an altered angle */\ {\ - tempxsow = FLOAT_TO_FIXED(vert->s);\ - tempytow = FLOAT_TO_FIXED(vert->t);\ - vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ - vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ + tempxsow = vert->s;\ + tempytow = vert->t;\ + vert->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));\ + vert->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));\ }\ \ vert->x = (vx);\ diff --git a/src/r_draw.h b/src/r_draw.h index caf43fd89..2173c7a5a 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -177,7 +177,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); -#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan)) +#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan)) void R_DrawSpan_8(void); void R_DrawTranslucentSpan_8(void); diff --git a/src/r_plane.c b/src/r_plane.c index ea5a7a3c3..ee7b161da 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -31,13 +31,6 @@ #include "z_zone.h" #include "p_tick.h" -#ifdef TIMING -#include "p5prof.h" - INT64 mycount; - INT64 mytotal = 0; - UINT32 nombre = 100000; -#endif - // // opening // @@ -128,21 +121,20 @@ struct boolean active; } planeripple; -static void R_CalculatePlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight, boolean calcfrac) +// ripples da water texture +static fixed_t R_CalculateRippleOffset(INT32 y) { - fixed_t distance = FixedMul(plheight, yslope[y]); + fixed_t distance = FixedMul(planeheight, yslope[y]); const INT32 yay = (planeripple.offset + (distance>>9)) & 8191; + return FixedDiv(FINESINE(yay), (1<<12) + (distance>>11)); +} - // ripples da water texture - ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; - - if (calcfrac) - { - angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT; - angle = (angle + 2048) & 8191; // 90 degrees - planeripple.xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs<>= ANGLETOFINESHIFT; + angle = (angle + 2048) & 8191; // 90 degrees + planeripple.xfrac = FixedMul(FINECOSINE(angle), ds_bgofs); + planeripple.yfrac = FixedMul(FINESINE(angle), ds_bgofs); } static void R_UpdatePlaneRipple(void) @@ -160,7 +152,7 @@ static void R_UpdatePlaneRipple(void) // baseyscale // centerx -void R_MapPlane(INT32 y, INT32 x1, INT32 x2) +static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; fixed_t distance = 0, span; @@ -174,60 +166,50 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) if (x1 >= vid.width) x1 = vid.width - 1; - if (!currentplane->slope) + angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; + planecos = FINECOSINE(angle); + planesin = FINESINE(angle); + + if (planeheight != cachedheight[y]) { - angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT; - planecos = FINECOSINE(angle); - planesin = FINESINE(angle); + cachedheight[y] = planeheight; + cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); + span = abs(centery - y); - if (planeheight != cachedheight[y]) + if (span) // don't divide by zero { - cachedheight[y] = planeheight; - cacheddistance[y] = distance = FixedMul(planeheight, yslope[y]); - span = abs(centery - y); - - if (span) // don't divide by zero - { - ds_xstep = FixedMul(planesin, planeheight) / span; - ds_ystep = FixedMul(planecos, planeheight) / span; - } - else - { - ds_xstep = FixedMul(distance, basexscale); - ds_ystep = FixedMul(distance, baseyscale); - } - - cachedxstep[y] = ds_xstep; - cachedystep[y] = ds_ystep; + ds_xstep = FixedMul(planesin, planeheight) / span; + ds_ystep = FixedMul(planecos, planeheight) / span; } else { - distance = cacheddistance[y]; - ds_xstep = cachedxstep[y]; - ds_ystep = cachedystep[y]; + ds_xstep = FixedMul(distance, basexscale); + ds_ystep = FixedMul(distance, baseyscale); } - ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; - ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; + cachedxstep[y] = ds_xstep; + cachedystep[y] = ds_ystep; } + else + { + distance = cacheddistance[y]; + ds_xstep = cachedxstep[y]; + ds_ystep = cachedystep[y]; + } + + ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep; + ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep; // Water ripple effect if (planeripple.active) { - // Needed for ds_bgofs - R_CalculatePlaneRipple(currentplane, y, planeheight, (!currentplane->slope)); + ds_bgofs = R_CalculateRippleOffset(y); - if (currentplane->slope) - { - ds_sup = &ds_su[y]; - ds_svp = &ds_sv[y]; - ds_szp = &ds_sz[y]; - } - else - { - ds_xfrac += planeripple.xfrac; - ds_yfrac += planeripple.yfrac; - } + R_CalculatePlaneRipple(currentplane->viewangle + currentplane->plangle); + + ds_xfrac += planeripple.xfrac; + ds_yfrac += planeripple.yfrac; + ds_bgofs >>= FRACBITS; if ((y + ds_bgofs) >= viewheight) ds_bgofs = viewheight-y-1; @@ -235,16 +217,11 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_bgofs = -y; } - if (currentplane->slope) - ds_colormap = colormaps; - else - { - pindex = distance >> LIGHTZSHIFT; - if (pindex >= MAXLIGHTZ) - pindex = MAXLIGHTZ - 1; - ds_colormap = planezlight[pindex]; - } + pindex = distance >> LIGHTZSHIFT; + if (pindex >= MAXLIGHTZ) + pindex = MAXLIGHTZ - 1; + ds_colormap = planezlight[pindex]; if (currentplane->extra_colormap) ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); @@ -252,19 +229,46 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ds_x1 = x1; ds_x2 = x2; - // profile drawer -#ifdef TIMING - ProfZeroTimer(); + spanfunc(); +} + +static void R_MapTiltedPlane(INT32 y, INT32 x1, INT32 x2) +{ +#ifdef RANGECHECK + if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) + I_Error("R_MapTiltedPlane: %d, %d at %d", x1, x2, y); #endif + if (x1 >= vid.width) + x1 = vid.width - 1; + + // Water ripple effect + if (planeripple.active) + { + ds_bgofs = R_CalculateRippleOffset(y); + + ds_sup = &ds_su[y]; + ds_svp = &ds_sv[y]; + ds_szp = &ds_sz[y]; + + ds_bgofs >>= FRACBITS; + + if ((y + ds_bgofs) >= viewheight) + ds_bgofs = viewheight-y-1; + if ((y + ds_bgofs) < 0) + ds_bgofs = -y; + } + + if (currentplane->extra_colormap) + ds_colormap = currentplane->extra_colormap->colormap; + else + ds_colormap = colormaps; + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + spanfunc(); - -#ifdef TIMING - RDMSR(0x10, &mycount); - mytotal += mycount; // 64bit add - if (!(nombre--)) - I_Error("spanfunc() CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1), (INT32)mytotal); -#endif } void R_ClearFFloorClips (void) @@ -572,10 +576,7 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) } -// -// R_MakeSpans -// -void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) +static void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) { // Alam: from r_splats's R_RasterizeFloorSplat if (t1 >= vid.height) t1 = vid.height-1; @@ -601,6 +602,32 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) spanstart[b2--] = x; } +static void R_MakeTiltedSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) +{ + // Alam: from r_splats's R_RasterizeFloorSplat + if (t1 >= vid.height) t1 = vid.height-1; + if (b1 >= vid.height) b1 = vid.height-1; + if (t2 >= vid.height) t2 = vid.height-1; + if (b2 >= vid.height) b2 = vid.height-1; + if (x-1 >= vid.width) x = vid.width; + + while (t1 < t2 && t1 <= b1) + { + R_MapTiltedPlane(t1, spanstart[t1], x - 1); + t1++; + } + while (b1 > b2 && b1 >= t1) + { + R_MapTiltedPlane(b1, spanstart[b1], x - 1); + b1--; + } + + while (t2 < t1 && t2 <= b2) + spanstart[t2++] = x; + while (b2 > b1 && b2 >= t2) + spanstart[b2--] = x; +} + void R_DrawPlanes(void) { visplane_t *pl; @@ -670,17 +697,14 @@ static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, f float vx = FixedToFloat(xpos + xoff); float vy = FixedToFloat(ypos - yoff); - float vz = FixedToFloat(zpos); float ang = ANG2RAD(ANGLE_270 - angle); - zeroheight = FixedToFloat(P_GetSlopeZAt(slope, xpos, ypos)); - // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. p->x = vx * cos(ang) - vy * sin(ang); p->z = vx * sin(ang) + vy * cos(ang); - p->y = FixedToFloat(P_GetSlopeZAt(slope, -xoff, yoff)) - vz; + p->y = FixedToFloat(P_GetSlopeZAt(slope, -xoff, yoff) - zpos); } // This function calculates all of the vectors necessary for drawing a sloped plane. @@ -689,10 +713,12 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! // I copied ZDoom's code and adapted it to SRB2... -Red floatv3_t *m = &ds_slope_v, *n = &ds_slope_u; - fixed_t temp; + fixed_t height, temp; float ang; R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); + height = P_GetSlopeZAt(slope, xpos, ypos); + zeroheight = FixedToFloat(height - zpos); // m is the v direction vector in view space ang = ANG2RAD(ANGLE_180 - (angle + plangle)); @@ -703,24 +729,26 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, n->x = sin(ang); n->z = -cos(ang); - ang = ANG2RAD(plangle); - temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(sin(ang)), ypos + FloatToFixed(cos(ang))); - m->y = FixedToFloat(temp) - zeroheight; - temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(cos(ang)), ypos - FloatToFixed(sin(ang))); - n->y = FixedToFloat(temp) - zeroheight; + plangle >>= ANGLETOFINESHIFT; + temp = P_GetSlopeZAt(slope, xpos + FINESINE(plangle), ypos + FINECOSINE(plangle)); + m->y = FixedToFloat(temp - height); + temp = P_GetSlopeZAt(slope, xpos + FINECOSINE(plangle), ypos - FINESINE(plangle)); + n->y = FixedToFloat(temp - height); } // This function calculates all of the vectors necessary for drawing a sloped and scaled plane. void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) { floatv3_t *m = &ds_slope_v, *n = &ds_slope_u; - fixed_t temp; + fixed_t height, temp; float xscale = FixedToFloat(xs); float yscale = FixedToFloat(ys); float ang; R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); + height = P_GetSlopeZAt(slope, xpos, ypos); + zeroheight = FixedToFloat(height - zpos); // m is the v direction vector in view space ang = ANG2RAD(ANGLE_180 - (angle + plangle)); @@ -733,9 +761,9 @@ void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t ang = ANG2RAD(plangle); temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(yscale * sin(ang)), ypos + FloatToFixed(yscale * cos(ang))); - m->y = FixedToFloat(temp) - zeroheight; + m->y = FixedToFloat(temp - height); temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(xscale * cos(ang)), ypos - FloatToFixed(xscale * sin(ang))); - n->y = FixedToFloat(temp) - zeroheight; + n->y = FixedToFloat(temp - height); } void R_CalculateSlopeVectors(void) @@ -803,29 +831,14 @@ static inline void R_AdjustSlopeCoordinates(visplane_t *pl) const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + fixed_t temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - fixed_t temp = ox & modmask; - oy &= modmask; - - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - - if (xoffs || yoffs) - { - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - } - - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); + temp = xoffs & modmask; + yoffs &= modmask; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // negative sine for opposite direction + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); } static inline void R_AdjustSlopeCoordinatesNPO2(visplane_t *pl) @@ -836,29 +849,14 @@ static inline void R_AdjustSlopeCoordinatesNPO2(visplane_t *pl) const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,sinecomponent) % modmaskh); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,cosinecomponent) % modmaskh); + fixed_t temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) % modmaskw) + (FixedMul(yoffs,sinecomponent) % modmaskh); + yoffs = (-FixedMul(temp,sinecomponent) % modmaskw) + (FixedMul(yoffs,cosinecomponent) % modmaskh); - fixed_t temp = ox % modmaskw; - oy %= modmaskh; - - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - - if (xoffs || yoffs) - { - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) % modmaskw) + (FixedMul(yoffs,sinecomponent) % modmaskh); - yoffs = (-FixedMul(temp,sinecomponent) % modmaskw) + (FixedMul(yoffs,cosinecomponent) % modmaskh); - - temp = xoffs % modmaskw; - yoffs %= modmaskh; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - } - - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); + temp = xoffs % modmaskw; + yoffs %= modmaskh; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); } void R_DrawSinglePlane(visplane_t *pl) @@ -1029,7 +1027,6 @@ void R_DrawSinglePlane(visplane_t *pl) xoffs = pl->xoffs; yoffs = pl->yoffs; - planeheight = abs(pl->height - pl->viewz); if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; @@ -1039,20 +1036,24 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - if (ds_powersoftwo) - R_AdjustSlopeCoordinates(pl); - else - R_AdjustSlopeCoordinatesNPO2(pl); + if (xoffs || yoffs) + { + if (ds_powersoftwo) + R_AdjustSlopeCoordinates(pl); + else + R_AdjustSlopeCoordinatesNPO2(pl); + } if (planeripple.active) { - fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); + planeheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); R_PlaneBounds(pl); for (x = pl->high; x < pl->low; x++) { - R_CalculatePlaneRipple(pl, x, plheight, true); + ds_bgofs = R_CalculateRippleOffset(x); + R_CalculatePlaneRipple(pl->viewangle + pl->plangle); R_SetSlopePlaneVectors(pl, x, (xoffs + planeripple.xfrac), (yoffs + planeripple.yfrac)); } } @@ -1078,7 +1079,10 @@ void R_DrawSinglePlane(visplane_t *pl) planezlight = scalelight[light]; } else + { + planeheight = abs(pl->height - pl->viewz); planezlight = zlight[light]; + } // Use the correct span drawer depending on the powers-of-twoness if (!ds_powersoftwo) @@ -1099,18 +1103,15 @@ void R_DrawSinglePlane(visplane_t *pl) stop = pl->maxx + 1; - if (viewx != pl->viewx || viewy != pl->viewy) + if (pl->slope) { - viewx = pl->viewx; - viewy = pl->viewy; + for (x = pl->minx; x <= stop; x++) + R_MakeTiltedSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); } - if (viewz != pl->viewz) - viewz = pl->viewz; - - for (x = pl->minx; x <= stop; x++) + else { - R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], - pl->top[x], pl->bottom[x]); + for (x = pl->minx; x <= stop; x++) + R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], pl->top[x], pl->bottom[x]); } /* diff --git a/src/r_plane.h b/src/r_plane.h index 9b7e31e3e..bdad77930 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -78,8 +78,6 @@ void R_InitPlanes(void); void R_ClearPlanes(void); void R_ClearFFloorClips (void); -void R_MapPlane(INT32 y, INT32 x1, INT32 x2); -void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2); void R_DrawPlanes(void); visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope); From 1c6296653a0e8010642e1acd0e749bb547de79c1 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 27 Apr 2021 20:32:41 -0300 Subject: [PATCH 119/241] Use floating point GetSlopeZAt for the texture origin vector --- src/r_plane.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/r_plane.c b/src/r_plane.c index ee7b161da..355260a11 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -690,6 +690,18 @@ static void R_DrawSkyPlane(visplane_t *pl) } } +// Returns the height of the sloped plane at (px, py) as a floating point number +static float R_GetSlopeZAt(const pslope_t *slope, fixed_t px, fixed_t py) +{ + float x = FixedToFloat(px - slope->o.x); + float y = FixedToFloat(py - slope->o.y); + + x = (x * FixedToFloat(slope->d.x)); + y = (y * FixedToFloat(slope->d.y)); + + return FixedToFloat(slope->o.z) + ((x + y) * FixedToFloat(slope->zdelta)); +} + // Sets the texture origin vector of the sloped plane. static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) { @@ -697,6 +709,7 @@ static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, f float vx = FixedToFloat(xpos + xoff); float vy = FixedToFloat(ypos - yoff); + float vz = FixedToFloat(zpos); float ang = ANG2RAD(ANGLE_270 - angle); // p is the texture origin in view space @@ -704,7 +717,7 @@ static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, f // errors if the flat is rotated. p->x = vx * cos(ang) - vy * sin(ang); p->z = vx * sin(ang) + vy * cos(ang); - p->y = FixedToFloat(P_GetSlopeZAt(slope, -xoff, yoff) - zpos); + p->y = R_GetSlopeZAt(slope, -xoff, yoff) - vz; } // This function calculates all of the vectors necessary for drawing a sloped plane. From 63761a2d07f7b336eb4f7a26778fffd04a38f810 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 27 Apr 2021 20:42:59 -0300 Subject: [PATCH 120/241] Use floating point trig in R_SetSlopePlane --- src/r_plane.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 355260a11..3ea046595 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -742,10 +742,10 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, n->x = sin(ang); n->z = -cos(ang); - plangle >>= ANGLETOFINESHIFT; - temp = P_GetSlopeZAt(slope, xpos + FINESINE(plangle), ypos + FINECOSINE(plangle)); + ang = ANG2RAD(plangle); + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(sin(ang)), ypos + FloatToFixed(cos(ang))); m->y = FixedToFloat(temp - height); - temp = P_GetSlopeZAt(slope, xpos + FINECOSINE(plangle), ypos - FINESINE(plangle)); + temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(cos(ang)), ypos - FloatToFixed(sin(ang))); n->y = FixedToFloat(temp - height); } From 0fba870a3526eb4397f261fe77388095173b82f8 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 27 Apr 2021 22:54:56 -0300 Subject: [PATCH 121/241] Revert "Use floating point trig in R_SetSlopePlane" This reverts commit 63761a2d07f7b336eb4f7a26778fffd04a38f810. --- src/r_plane.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 3ea046595..355260a11 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -742,10 +742,10 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, n->x = sin(ang); n->z = -cos(ang); - ang = ANG2RAD(plangle); - temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(sin(ang)), ypos + FloatToFixed(cos(ang))); + plangle >>= ANGLETOFINESHIFT; + temp = P_GetSlopeZAt(slope, xpos + FINESINE(plangle), ypos + FINECOSINE(plangle)); m->y = FixedToFloat(temp - height); - temp = P_GetSlopeZAt(slope, xpos + FloatToFixed(cos(ang)), ypos - FloatToFixed(sin(ang))); + temp = P_GetSlopeZAt(slope, xpos + FINECOSINE(plangle), ypos - FINESINE(plangle)); n->y = FixedToFloat(temp - height); } From 8f47a7e9cc98af4b1631e32e98ff4421f03c49d9 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 27 Apr 2021 22:59:06 -0300 Subject: [PATCH 122/241] Prevent texture wobbling on planes with no flat alignment --- src/r_plane.c | 102 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 30 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 355260a11..acbbc8a5c 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -690,16 +690,16 @@ static void R_DrawSkyPlane(visplane_t *pl) } } -// Returns the height of the sloped plane at (px, py) as a floating point number -static float R_GetSlopeZAt(const pslope_t *slope, fixed_t px, fixed_t py) +// Returns the height of the sloped plane at (x, y) as a 32.16 fixed_t +static INT64 R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) { - float x = FixedToFloat(px - slope->o.x); - float y = FixedToFloat(py - slope->o.y); + x = ((INT64)x - (INT64)slope->o.x); + y = ((INT64)y - (INT64)slope->o.y); - x = (x * FixedToFloat(slope->d.x)); - y = (y * FixedToFloat(slope->d.y)); + x = (x * (INT64)slope->d.x) / FRACUNIT; + y = (y * (INT64)slope->d.y) / FRACUNIT; - return FixedToFloat(slope->o.z) + ((x + y) * FixedToFloat(slope->zdelta)); + return (INT64)slope->o.z + ((x + y) * (INT64)slope->zdelta) / FRACUNIT; } // Sets the texture origin vector of the sloped plane. @@ -709,7 +709,6 @@ static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, f float vx = FixedToFloat(xpos + xoff); float vy = FixedToFloat(ypos - yoff); - float vz = FixedToFloat(zpos); float ang = ANG2RAD(ANGLE_270 - angle); // p is the texture origin in view space @@ -717,7 +716,7 @@ static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, f // errors if the flat is rotated. p->x = vx * cos(ang) - vy * sin(ang); p->z = vx * sin(ang) + vy * cos(ang); - p->y = R_GetSlopeZAt(slope, -xoff, yoff) - vz; + p->y = (R_GetSlopeZAt(slope, -xoff, yoff) - zpos) / (float)FRACUNIT; } // This function calculates all of the vectors necessary for drawing a sloped plane. @@ -844,14 +843,37 @@ static inline void R_AdjustSlopeCoordinates(visplane_t *pl) const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); - fixed_t temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + fixed_t ox, oy, temp; - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // negative sine for opposite direction - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + if (!pl->plangle) + { + ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); + oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + + temp = ox & modmask; + oy &= modmask; + + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + } + + if (xoffs || yoffs) + { + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + + temp = xoffs & modmask; + yoffs &= modmask; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + } + + if (!pl->plangle) + { + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); + } } static inline void R_AdjustSlopeCoordinatesNPO2(visplane_t *pl) @@ -862,14 +884,37 @@ static inline void R_AdjustSlopeCoordinatesNPO2(visplane_t *pl) const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); - fixed_t temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) % modmaskw) + (FixedMul(yoffs,sinecomponent) % modmaskh); - yoffs = (-FixedMul(temp,sinecomponent) % modmaskw) + (FixedMul(yoffs,cosinecomponent) % modmaskh); + fixed_t ox, oy, temp; - temp = xoffs % modmaskw; - yoffs %= modmaskh; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + if (!pl->plangle) + { + ox = (FixedMul(pl->slope->o.x,cosinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,sinecomponent) % modmaskh); + oy = (-FixedMul(pl->slope->o.x,sinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,cosinecomponent) % modmaskh); + + temp = ox % modmaskw; + oy %= modmaskh; + + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + } + + if (xoffs || yoffs) + { + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) % modmaskw) + (FixedMul(yoffs,sinecomponent) % modmaskh); + yoffs = (-FixedMul(temp,sinecomponent) % modmaskw) + (FixedMul(yoffs,cosinecomponent) % modmaskh); + + temp = xoffs % modmaskw; + yoffs %= modmaskh; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); + } + + if (!pl->plangle) + { + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); + } } void R_DrawSinglePlane(visplane_t *pl) @@ -1049,13 +1094,10 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - if (xoffs || yoffs) - { - if (ds_powersoftwo) - R_AdjustSlopeCoordinates(pl); - else - R_AdjustSlopeCoordinatesNPO2(pl); - } + if (ds_powersoftwo) + R_AdjustSlopeCoordinates(pl); + else + R_AdjustSlopeCoordinatesNPO2(pl); if (planeripple.active) { From 090f304f3368d96cb02c2ffb89701864d07c2191 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Wed, 28 Apr 2021 22:00:20 -0300 Subject: [PATCH 123/241] Use 64-bit x/y in R_GetSlopeZAt --- src/r_plane.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index acbbc8a5c..8db4801b5 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -693,13 +693,13 @@ static void R_DrawSkyPlane(visplane_t *pl) // Returns the height of the sloped plane at (x, y) as a 32.16 fixed_t static INT64 R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) { - x = ((INT64)x - (INT64)slope->o.x); - y = ((INT64)y - (INT64)slope->o.y); + INT64 x64 = ((INT64)x - (INT64)slope->o.x); + INT64 y64 = ((INT64)y - (INT64)slope->o.y); - x = (x * (INT64)slope->d.x) / FRACUNIT; - y = (y * (INT64)slope->d.y) / FRACUNIT; + x64 = (x64 * (INT64)slope->d.x) / FRACUNIT; + y64 = (y64 * (INT64)slope->d.y) / FRACUNIT; - return (INT64)slope->o.z + ((x + y) * (INT64)slope->zdelta) / FRACUNIT; + return (INT64)slope->o.z + ((x64 + y64) * (INT64)slope->zdelta) / FRACUNIT; } // Sets the texture origin vector of the sloped plane. From 9d41325843d9c63c5e9862034e06863f7be0d65c Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Wed, 28 Apr 2021 22:15:05 -0300 Subject: [PATCH 124/241] Only adjust slope offsets if the plane isn't rotated --- src/r_plane.c | 98 +++++++++++---------------------------------------- 1 file changed, 21 insertions(+), 77 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 8db4801b5..c56a222df 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -829,92 +829,33 @@ static void R_SetSlopePlaneVectors(visplane_t *pl, INT32 y, fixed_t xoff, fixed_ R_CalculateSlopeVectors(); } -/* - Essentially: We can't & the components along the regular axes when the plane is rotated. - This is because the distance on each regular axis in order to loop is different. - We rotate them, & the components, add them together, & them again, and then rotate them back. - These three seperate & operations are done per axis in order to prevent overflows. - toast 10/04/17 -*/ -static inline void R_AdjustSlopeCoordinates(visplane_t *pl) +static inline void R_AdjustSlopeCoordinates(vector3_t *origin) { const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); - const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); + fixed_t ox = (origin->x & modmask); + fixed_t oy = -(origin->y & modmask); - fixed_t ox, oy, temp; + xoffs &= modmask; + yoffs &= modmask; - if (!pl->plangle) - { - ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - - temp = ox & modmask; - oy &= modmask; - - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - } - - if (xoffs || yoffs) - { - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - } - - if (!pl->plangle) - { - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); - } + xoffs -= (origin->x - ox); + yoffs += (origin->y + oy); } -static inline void R_AdjustSlopeCoordinatesNPO2(visplane_t *pl) +static inline void R_AdjustSlopeCoordinatesNPO2(vector3_t *origin) { const fixed_t modmaskw = (ds_flatwidth << FRACBITS); const fixed_t modmaskh = (ds_flatheight << FRACBITS); - const fixed_t cosinecomponent = FINECOSINE(pl->plangle>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(pl->plangle>>ANGLETOFINESHIFT); + fixed_t ox = (origin->x % modmaskw); + fixed_t oy = -(origin->y % modmaskh); - fixed_t ox, oy, temp; + xoffs %= modmaskw; + yoffs %= modmaskh; - if (!pl->plangle) - { - ox = (FixedMul(pl->slope->o.x,cosinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,sinecomponent) % modmaskh); - oy = (-FixedMul(pl->slope->o.x,sinecomponent) % modmaskw) - (FixedMul(pl->slope->o.y,cosinecomponent) % modmaskh); - - temp = ox % modmaskw; - oy %= modmaskh; - - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - } - - if (xoffs || yoffs) - { - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) % modmaskw) + (FixedMul(yoffs,sinecomponent) % modmaskh); - yoffs = (-FixedMul(temp,sinecomponent) % modmaskw) + (FixedMul(yoffs,cosinecomponent) % modmaskh); - - temp = xoffs % modmaskw; - yoffs %= modmaskh; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - } - - if (!pl->plangle) - { - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); - } + xoffs -= (origin->x - ox); + yoffs += (origin->y + oy); } void R_DrawSinglePlane(visplane_t *pl) @@ -1094,10 +1035,13 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - if (ds_powersoftwo) - R_AdjustSlopeCoordinates(pl); - else - R_AdjustSlopeCoordinatesNPO2(pl); + if (!pl->plangle) + { + if (ds_powersoftwo) + R_AdjustSlopeCoordinates(&pl->slope->o); + else + R_AdjustSlopeCoordinatesNPO2(&pl->slope->o); + } if (planeripple.active) { From b4a09405a77d5bb5ec1c677a123f763ff2193ebb Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Thu, 29 Apr 2021 19:24:37 -0300 Subject: [PATCH 125/241] Use 64-bit math for calculating the texture origin X/Z --- src/r_plane.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index c56a222df..d26c124ef 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -707,15 +707,18 @@ static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, f { floatv3_t *p = &ds_slope_origin; - float vx = FixedToFloat(xpos + xoff); - float vy = FixedToFloat(ypos - yoff); + INT64 vx = (INT64)xpos + (INT64)xoff; + INT64 vy = (INT64)ypos - (INT64)yoff; + + float vxf = vx / (float)FRACUNIT; + float vyf = vy / (float)FRACUNIT; float ang = ANG2RAD(ANGLE_270 - angle); // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - p->x = vx * cos(ang) - vy * sin(ang); - p->z = vx * sin(ang) + vy * cos(ang); + p->x = vxf * cos(ang) - vyf * sin(ang); + p->z = vxf * sin(ang) + vyf * cos(ang); p->y = (R_GetSlopeZAt(slope, -xoff, yoff) - zpos) / (float)FRACUNIT; } From 381ead4d7e378b557f135a39d582d6a11a8d8af7 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 30 Apr 2021 21:46:09 -0400 Subject: [PATCH 126/241] Level select no longer assumes that games will always be linear - If a level is in-between two with the same header, it would previously create two headers with the same name. Now it groups all levels with the same header together. - Previously, a header would only be visible if its first map was visible. Now it will show the header if you've visited any level under the header. For SUGOI. --- src/m_menu.c | 195 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 148 insertions(+), 47 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 0fca39801..5a5c98241 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5166,34 +5166,75 @@ static boolean M_GametypeHasLevels(INT32 gt) static INT32 M_CountRowsToShowOnPlatter(INT32 gt) { - INT32 mapnum = 0, prevmapnum = 0, col = 0, rows = 0; + INT32 col = 0, rows = 0; + INT32 mapIterate = 0; + INT32 headingIterate = 0; + boolean mapAddedAlready[NUMMAPS]; - while (mapnum < NUMMAPS) + memset(mapAddedAlready, 0, sizeof mapAddedAlready); + + for (mapIterate = 0; mapIterate < NUMMAPS; mapIterate++) { - if (M_CanShowLevelOnPlatter(mapnum, gt)) + boolean forceNewRow = true; + + if (mapAddedAlready[mapIterate] == true) { - if (rows == 0) + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(mapIterate, gt) == false) + { + // Don't show this one + continue; + } + + for (headingIterate = mapIterate; headingIterate < NUMMAPS; headingIterate++) + { + boolean wide = false; + + if (mapAddedAlready[headingIterate] == true) + { + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(headingIterate, gt) == false) + { + // Don't show this one + continue; + } + + if (!fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[headingIterate]->selectheading)) + { + // Headers don't match + continue; + } + + wide = (mapheaderinfo[headingIterate]->menuflags & LF2_WIDEICON); + + // preparing next position to drop mapnum into + if (col == 2 // no more space on the row? + || wide || forceNewRow) + { + col = 0; rows++; + } else { - if (col == 2 - || (mapheaderinfo[prevmapnum]->menuflags & LF2_WIDEICON) - || (mapheaderinfo[mapnum]->menuflags & LF2_WIDEICON) - || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading))) - { - col = 0; - rows++; - } - else - col++; + col++; } - prevmapnum = mapnum; + + // Done adding this one + mapAddedAlready[headingIterate] = true; + forceNewRow = wide; } - mapnum++; } if (levellistmode == LLM_CREATESERVER) + { rows++; + } return rows; } @@ -5223,7 +5264,10 @@ static void M_CacheLevelPlatter(void) static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) { INT32 numrows = M_CountRowsToShowOnPlatter(gt); - INT32 mapnum = 0, prevmapnum = 0, col = 0, row = 0, startrow = 0; + INT32 col = 0, row = 0, startrow = 0; + INT32 mapIterate = 0; // First level of map loop -- find starting points for select headings + INT32 headingIterate = 0; // Second level of map loop -- finding maps that match mapIterate's heading. + boolean mapAddedAlready[NUMMAPS]; if (!numrows) return false; @@ -5240,6 +5284,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) // done here so lsrow and lscol can be set if cv_nextmap is on the platter lsrow = lscol = lshli = lsoffs[0] = lsoffs[1] = 0; + memset(mapAddedAlready, 0, sizeof mapAddedAlready); + if (levellistmode == LLM_CREATESERVER) { sprintf(levelselect.rows[0].header, "Gametype"); @@ -5251,31 +5297,75 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) char_notes = NULL; } - while (mapnum < NUMMAPS) + for (mapIterate = 0; mapIterate < NUMMAPS; mapIterate++) { - if (M_CanShowLevelOnPlatter(mapnum, gt)) + INT32 headerRow = -1; + boolean anyAvailable = false; + boolean forceNewRow = true; + + if (mapAddedAlready[mapIterate] == true) { - const UINT8 actnum = mapheaderinfo[mapnum]->actnum; - const boolean headingisname = (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl)); - const boolean wide = (mapheaderinfo[mapnum]->menuflags & LF2_WIDEICON); + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(mapIterate, gt) == false) + { + // Don't show this one + continue; + } + + for (headingIterate = mapIterate; headingIterate < NUMMAPS; headingIterate++) + { + UINT8 actnum = 0; + boolean headingisname = false; + boolean wide = false; + + if (mapAddedAlready[headingIterate] == true) + { + // Already added under another heading + continue; + } + + if (M_CanShowLevelOnPlatter(headingIterate, gt) == false) + { + // Don't show this one + continue; + } + + if (!fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[headingIterate]->selectheading)) + { + // Headers don't match + continue; + } + + actnum = mapheaderinfo[headingIterate]->actnum; + headingisname = (fastcmp(mapheaderinfo[headingIterate]->selectheading, mapheaderinfo[headingIterate]->lvlttl)); + wide = (mapheaderinfo[headingIterate]->menuflags & LF2_WIDEICON); // preparing next position to drop mapnum into if (levelselect.rows[startrow].maplist[0]) { if (col == 2 // no more space on the row? - || wide - || (mapheaderinfo[prevmapnum]->menuflags & LF2_WIDEICON) - || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading))) // a new heading is starting? + || wide || forceNewRow) { col = 0; row++; } else + { col++; + } } - levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter - levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum); + if (headerRow == -1) + { + // Set where the header row is meant to be + headerRow = row; + } + + levelselect.rows[row].maplist[col] = headingIterate+1; // putting the map on the platter + levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(headingIterate); if ((lswide(row) = wide)) // intentionally assignment { @@ -5283,7 +5373,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) levelselect.rows[row].mapavailable[2] = levelselect.rows[row].mapavailable[1] = levelselect.rows[row].mapavailable[0]; } - if (nextmappick && cv_nextmap.value == mapnum+1) // A little quality of life improvement. + if (nextmappick && cv_nextmap.value == headingIterate+1) // A little quality of life improvement. { lsrow = row; lscol = col; @@ -5292,6 +5382,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) // individual map name if (levelselect.rows[row].mapavailable[col]) { + anyAvailable = true; + if (headingisname) { if (actnum) @@ -5302,7 +5394,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) else if (wide) { // Yes, with LF2_WIDEICON it'll continue on over into the next 17+1 char block. That's alright; col is always zero, the string is contiguous, and the maximum length is lvlttl[22] + ' ' + ZONE + ' ' + INT32, which is about 39 or so - barely crossing into the third column. - char* mapname = G_BuildMapTitle(mapnum+1); + char* mapname = G_BuildMapTitle(headingIterate+1); strcpy(levelselect.rows[row].mapnames[col], (const char *)mapname); Z_Free(mapname); } @@ -5311,9 +5403,9 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) char mapname[22+1+11]; // lvlttl[22] + ' ' + INT32 if (actnum) - sprintf(mapname, "%s %d", mapheaderinfo[mapnum]->lvlttl, actnum); + sprintf(mapname, "%s %d", mapheaderinfo[headingIterate]->lvlttl, actnum); else - strcpy(mapname, mapheaderinfo[mapnum]->lvlttl); + strcpy(mapname, mapheaderinfo[headingIterate]->lvlttl); if (strlen(mapname) >= 17) strcpy(mapname+17-3, "..."); @@ -5322,27 +5414,36 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick) } } else - sprintf(levelselect.rows[row].mapnames[col], "???"); - - // creating header text - if (!col && ((row == startrow) || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row-1].maplist[0]-1]->selectheading)))) { - if (!levelselect.rows[row].mapavailable[col]) - sprintf(levelselect.rows[row].header, "???"); - else - { - sprintf(levelselect.rows[row].header, "%s", mapheaderinfo[mapnum]->selectheading); - if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && headingisname) - { - sprintf(levelselect.rows[row].header + strlen(levelselect.rows[row].header), " ZONE"); - } - } + sprintf(levelselect.rows[row].mapnames[col], "???"); } - prevmapnum = mapnum; + // Done adding this one + mapAddedAlready[headingIterate] = true; + forceNewRow = wide; } - mapnum++; + if (headerRow == -1) + { + // Shouldn't happen + continue; + } + + // creating header text + if (anyAvailable == false) + { + sprintf(levelselect.rows[headerRow].header, "???"); + } + else + { + sprintf(levelselect.rows[headerRow].header, "%s", mapheaderinfo[mapIterate]->selectheading); + + if (!(mapheaderinfo[mapIterate]->levelflags & LF_NOZONE) + && fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[mapIterate]->lvlttl)) + { + sprintf(levelselect.rows[headerRow].header + strlen(levelselect.rows[headerRow].header), " ZONE"); + } + } } #ifdef SYMMETRICAL_PLATTER From ab84bd5370a390fdf048027624c1c2d40a8b2c88 Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sun, 2 May 2021 00:03:35 -0500 Subject: [PATCH 127/241] Fix the console splitting up halfway through startup. --- src/v_video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index 4713db0d8..2e7d7e4ea 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -455,7 +455,8 @@ void VID_BlitLinearScreen_ASM(const UINT8 *srcptr, UINT8 *destptr, INT32 width, static void CV_constextsize_OnChange(void) { - con_recalc = true; + if (!con_refresh) + con_recalc = true; } From 44d217807f71d15bd7ca69dad226458e7060ccab Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 1 May 2021 19:07:44 -0700 Subject: [PATCH 128/241] Collect makefiles --- src/{blua/Makefile.cfg => Makefile.d/lua.mk} | 0 src/{sdl/MakeNIX.cfg => Makefile.d/nix.mk} | 0 src/{sdl/Makefile.cfg => Makefile.d/sdl.mk} | 0 src/{Makefile.cfg => Makefile.d/versions.mk} | 0 src/{win32/Makefile.cfg => Makefile.d/win32.mk} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/{blua/Makefile.cfg => Makefile.d/lua.mk} (100%) rename src/{sdl/MakeNIX.cfg => Makefile.d/nix.mk} (100%) rename src/{sdl/Makefile.cfg => Makefile.d/sdl.mk} (100%) rename src/{Makefile.cfg => Makefile.d/versions.mk} (100%) rename src/{win32/Makefile.cfg => Makefile.d/win32.mk} (100%) diff --git a/src/blua/Makefile.cfg b/src/Makefile.d/lua.mk similarity index 100% rename from src/blua/Makefile.cfg rename to src/Makefile.d/lua.mk diff --git a/src/sdl/MakeNIX.cfg b/src/Makefile.d/nix.mk similarity index 100% rename from src/sdl/MakeNIX.cfg rename to src/Makefile.d/nix.mk diff --git a/src/sdl/Makefile.cfg b/src/Makefile.d/sdl.mk similarity index 100% rename from src/sdl/Makefile.cfg rename to src/Makefile.d/sdl.mk diff --git a/src/Makefile.cfg b/src/Makefile.d/versions.mk similarity index 100% rename from src/Makefile.cfg rename to src/Makefile.d/versions.mk diff --git a/src/win32/Makefile.cfg b/src/Makefile.d/win32.mk similarity index 100% rename from src/win32/Makefile.cfg rename to src/Makefile.d/win32.mk From f637e28d0c1877c44acd7b01f7130625d5ea4099 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 4 May 2021 04:14:00 -0700 Subject: [PATCH 129/241] Remove bin, objs and dep directories --- bin/FreeBSD/Debug/.gitignore | 2 -- bin/FreeBSD/Release/.gitignore | 2 -- bin/Linux/Debug/.gitignore | 1 - bin/Linux/Release/.gitignore | 3 --- bin/Linux64/Debug/.gitignore | 1 - bin/Linux64/Release/.gitignore | 1 - bin/Mingw/Debug/.gitignore | 3 --- bin/Mingw/Release/.gitignore | 4 ---- bin/Mingw64/Debug/.gitignore | 3 --- bin/Mingw64/Release/.gitignore | 3 --- bin/SDL/Debug/.gitignore | 2 -- bin/SDL/Release/.gitignore | 2 -- bin/VC/.gitignore | 2 -- bin/VC9/.gitignore | 2 -- bin/dummy/.gitignore | 2 -- dep/.gitignore | 2 -- dep/FreeBSD/SDL/Debug/.gitignore | 2 -- dep/FreeBSD/SDL/Release/.gitignore | 2 -- dep/Linux/SDL/Debug/.gitignore | 2 -- dep/Linux/SDL/Release/.gitignore | 2 -- dep/Linux64/SDL/Debug/.gitignore | 2 -- dep/Linux64/SDL/Release/.gitignore | 2 -- dep/MasterClient/.gitignore | 2 -- dep/MasterServer/.gitignore | 2 -- dep/Mingw/Debug/.gitignore | 2 -- dep/Mingw/Release/.gitignore | 2 -- dep/Mingw/SDL/Debug/.gitignore | 2 -- dep/Mingw/SDL/Release/.gitignore | 2 -- dep/Mingw64/Debug/.gitignore | 2 -- dep/Mingw64/Release/.gitignore | 2 -- dep/Mingw64/SDL/Debug/.gitignore | 2 -- dep/Mingw64/SDL/Release/.gitignore | 2 -- dep/SDL/Release/.gitignore | 2 -- dep/VC/.gitignore | 2 -- dep/VC9/.gitignore | 2 -- dep/cygwin/Debug/.gitignore | 2 -- dep/cygwin/Release/.gitignore | 2 -- dep/dummy/.gitignore | 2 -- objs/.gitignore | 8 -------- objs/FreeBSD/SDL/Debug/.gitignore | 2 -- objs/FreeBSD/SDL/Release/.gitignore | 2 -- objs/Linux/SDL/Debug/.gitignore | 2 -- objs/Linux/SDL/Release/.gitignore | 2 -- objs/Linux64/SDL/Debug/.gitignore | 2 -- objs/Linux64/SDL/Release/.gitignore | 2 -- objs/MasterClient/.gitignore | 2 -- objs/MasterServer/.gitignore | 2 -- objs/Mingw/Debug/.gitignore | 2 -- objs/Mingw/Release/.gitignore | 2 -- objs/Mingw/SDL/Debug/.gitignore | 2 -- objs/Mingw/SDL/Release/.gitignore | 2 -- objs/Mingw64/Debug/.gitignore | 2 -- objs/Mingw64/Release/.gitignore | 2 -- objs/Mingw64/SDL/Debug/.gitignore | 2 -- objs/Mingw64/SDL/Release/.gitignore | 2 -- objs/SDL/Release/.gitignore | 2 -- objs/VC/.gitignore | 2 -- objs/VC9/.gitignore | 2 -- objs/cygwin/Debug/.gitignore | 2 -- objs/cygwin/Release/.gitignore | 2 -- objs/dummy/.gitignore | 2 -- 61 files changed, 131 deletions(-) delete mode 100644 bin/FreeBSD/Debug/.gitignore delete mode 100644 bin/FreeBSD/Release/.gitignore delete mode 100644 bin/Linux/Debug/.gitignore delete mode 100644 bin/Linux/Release/.gitignore delete mode 100644 bin/Linux64/Debug/.gitignore delete mode 100644 bin/Linux64/Release/.gitignore delete mode 100644 bin/Mingw/Debug/.gitignore delete mode 100644 bin/Mingw/Release/.gitignore delete mode 100644 bin/Mingw64/Debug/.gitignore delete mode 100644 bin/Mingw64/Release/.gitignore delete mode 100644 bin/SDL/Debug/.gitignore delete mode 100644 bin/SDL/Release/.gitignore delete mode 100644 bin/VC/.gitignore delete mode 100644 bin/VC9/.gitignore delete mode 100644 bin/dummy/.gitignore delete mode 100644 dep/.gitignore delete mode 100644 dep/FreeBSD/SDL/Debug/.gitignore delete mode 100644 dep/FreeBSD/SDL/Release/.gitignore delete mode 100644 dep/Linux/SDL/Debug/.gitignore delete mode 100644 dep/Linux/SDL/Release/.gitignore delete mode 100644 dep/Linux64/SDL/Debug/.gitignore delete mode 100644 dep/Linux64/SDL/Release/.gitignore delete mode 100644 dep/MasterClient/.gitignore delete mode 100644 dep/MasterServer/.gitignore delete mode 100644 dep/Mingw/Debug/.gitignore delete mode 100644 dep/Mingw/Release/.gitignore delete mode 100644 dep/Mingw/SDL/Debug/.gitignore delete mode 100644 dep/Mingw/SDL/Release/.gitignore delete mode 100644 dep/Mingw64/Debug/.gitignore delete mode 100644 dep/Mingw64/Release/.gitignore delete mode 100644 dep/Mingw64/SDL/Debug/.gitignore delete mode 100644 dep/Mingw64/SDL/Release/.gitignore delete mode 100644 dep/SDL/Release/.gitignore delete mode 100644 dep/VC/.gitignore delete mode 100644 dep/VC9/.gitignore delete mode 100644 dep/cygwin/Debug/.gitignore delete mode 100644 dep/cygwin/Release/.gitignore delete mode 100644 dep/dummy/.gitignore delete mode 100644 objs/.gitignore delete mode 100644 objs/FreeBSD/SDL/Debug/.gitignore delete mode 100644 objs/FreeBSD/SDL/Release/.gitignore delete mode 100644 objs/Linux/SDL/Debug/.gitignore delete mode 100644 objs/Linux/SDL/Release/.gitignore delete mode 100644 objs/Linux64/SDL/Debug/.gitignore delete mode 100644 objs/Linux64/SDL/Release/.gitignore delete mode 100644 objs/MasterClient/.gitignore delete mode 100644 objs/MasterServer/.gitignore delete mode 100644 objs/Mingw/Debug/.gitignore delete mode 100644 objs/Mingw/Release/.gitignore delete mode 100644 objs/Mingw/SDL/Debug/.gitignore delete mode 100644 objs/Mingw/SDL/Release/.gitignore delete mode 100644 objs/Mingw64/Debug/.gitignore delete mode 100644 objs/Mingw64/Release/.gitignore delete mode 100644 objs/Mingw64/SDL/Debug/.gitignore delete mode 100644 objs/Mingw64/SDL/Release/.gitignore delete mode 100644 objs/SDL/Release/.gitignore delete mode 100644 objs/VC/.gitignore delete mode 100644 objs/VC9/.gitignore delete mode 100644 objs/cygwin/Debug/.gitignore delete mode 100644 objs/cygwin/Release/.gitignore delete mode 100644 objs/dummy/.gitignore diff --git a/bin/FreeBSD/Debug/.gitignore b/bin/FreeBSD/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/FreeBSD/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/FreeBSD/Release/.gitignore b/bin/FreeBSD/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/FreeBSD/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/Linux/Debug/.gitignore b/bin/Linux/Debug/.gitignore deleted file mode 100644 index 56dee6f95..000000000 --- a/bin/Linux/Debug/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/lsdlsrb2 diff --git a/bin/Linux/Release/.gitignore b/bin/Linux/Release/.gitignore deleted file mode 100644 index 5b5c54a54..000000000 --- a/bin/Linux/Release/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/lsdlsrb2 -/pnd -/*.mo diff --git a/bin/Linux64/Debug/.gitignore b/bin/Linux64/Debug/.gitignore deleted file mode 100644 index 56dee6f95..000000000 --- a/bin/Linux64/Debug/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/lsdlsrb2 diff --git a/bin/Linux64/Release/.gitignore b/bin/Linux64/Release/.gitignore deleted file mode 100644 index 56dee6f95..000000000 --- a/bin/Linux64/Release/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/lsdlsrb2 diff --git a/bin/Mingw/Debug/.gitignore b/bin/Mingw/Debug/.gitignore deleted file mode 100644 index 834f313e3..000000000 --- a/bin/Mingw/Debug/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.exe -*.mo -r_opengl.dll diff --git a/bin/Mingw/Release/.gitignore b/bin/Mingw/Release/.gitignore deleted file mode 100644 index 3458ff764..000000000 --- a/bin/Mingw/Release/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.exe -*.mo -r_opengl.dll -*.bat diff --git a/bin/Mingw64/Debug/.gitignore b/bin/Mingw64/Debug/.gitignore deleted file mode 100644 index e431dca5d..000000000 --- a/bin/Mingw64/Debug/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/srb2sdl.exe -/srb2win.exe -/r_opengl.dll diff --git a/bin/Mingw64/Release/.gitignore b/bin/Mingw64/Release/.gitignore deleted file mode 100644 index e431dca5d..000000000 --- a/bin/Mingw64/Release/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/srb2sdl.exe -/srb2win.exe -/r_opengl.dll diff --git a/bin/SDL/Debug/.gitignore b/bin/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/SDL/Release/.gitignore b/bin/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/VC/.gitignore b/bin/VC/.gitignore deleted file mode 100644 index e52f825b2..000000000 --- a/bin/VC/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/Release -/Debug diff --git a/bin/VC9/.gitignore b/bin/VC9/.gitignore deleted file mode 100644 index 205fe45de..000000000 --- a/bin/VC9/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/Win32 -/x64 diff --git a/bin/dummy/.gitignore b/bin/dummy/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/dummy/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/.gitignore b/dep/.gitignore deleted file mode 100644 index fb941664f..000000000 --- a/dep/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -#All folders -*.d diff --git a/dep/FreeBSD/SDL/Debug/.gitignore b/dep/FreeBSD/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/FreeBSD/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/FreeBSD/SDL/Release/.gitignore b/dep/FreeBSD/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/FreeBSD/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux/SDL/Debug/.gitignore b/dep/Linux/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux/SDL/Release/.gitignore b/dep/Linux/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux64/SDL/Debug/.gitignore b/dep/Linux64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Linux64/SDL/Release/.gitignore b/dep/Linux64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Linux64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/MasterClient/.gitignore b/dep/MasterClient/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/MasterClient/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/MasterServer/.gitignore b/dep/MasterServer/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/MasterServer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/Debug/.gitignore b/dep/Mingw/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/Release/.gitignore b/dep/Mingw/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/SDL/Debug/.gitignore b/dep/Mingw/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw/SDL/Release/.gitignore b/dep/Mingw/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/Debug/.gitignore b/dep/Mingw64/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/Release/.gitignore b/dep/Mingw64/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/SDL/Debug/.gitignore b/dep/Mingw64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/Mingw64/SDL/Release/.gitignore b/dep/Mingw64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/Mingw64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/SDL/Release/.gitignore b/dep/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/VC/.gitignore b/dep/VC/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/VC/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/VC9/.gitignore b/dep/VC9/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/VC9/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/cygwin/Debug/.gitignore b/dep/cygwin/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/cygwin/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/cygwin/Release/.gitignore b/dep/cygwin/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/cygwin/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/dep/dummy/.gitignore b/dep/dummy/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/dep/dummy/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/.gitignore b/objs/.gitignore deleted file mode 100644 index 35ecd6def..000000000 --- a/objs/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -#All folders -SRB2.res -depend.dep -depend.ped -*.o -#VC9 folder only -/VC9/Win32 -/VC9/x64 diff --git a/objs/FreeBSD/SDL/Debug/.gitignore b/objs/FreeBSD/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/FreeBSD/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/FreeBSD/SDL/Release/.gitignore b/objs/FreeBSD/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/FreeBSD/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux/SDL/Debug/.gitignore b/objs/Linux/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux/SDL/Release/.gitignore b/objs/Linux/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux64/SDL/Debug/.gitignore b/objs/Linux64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Linux64/SDL/Release/.gitignore b/objs/Linux64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Linux64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/MasterClient/.gitignore b/objs/MasterClient/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/MasterClient/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/MasterServer/.gitignore b/objs/MasterServer/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/MasterServer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/Debug/.gitignore b/objs/Mingw/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/Release/.gitignore b/objs/Mingw/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/SDL/Debug/.gitignore b/objs/Mingw/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw/SDL/Release/.gitignore b/objs/Mingw/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/Debug/.gitignore b/objs/Mingw64/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/Release/.gitignore b/objs/Mingw64/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/SDL/Debug/.gitignore b/objs/Mingw64/SDL/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/SDL/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/Mingw64/SDL/Release/.gitignore b/objs/Mingw64/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/Mingw64/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/SDL/Release/.gitignore b/objs/SDL/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/SDL/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/VC/.gitignore b/objs/VC/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/VC/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/VC9/.gitignore b/objs/VC9/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/VC9/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/cygwin/Debug/.gitignore b/objs/cygwin/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/cygwin/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/cygwin/Release/.gitignore b/objs/cygwin/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/cygwin/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/objs/dummy/.gitignore b/objs/dummy/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/objs/dummy/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing From b31056c7d977fe3c2a5e0637589fd9521f1f6c04 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 2 May 2021 02:54:51 -0700 Subject: [PATCH 130/241] Rewrite Makefile to be modular as well as more automated Some key points for programmers: - Source code files are mostly listed in a 'Sourcefile'. So you no longer directly edit the object list. There can be multiple Sourcefiles and they can even live in subdirectories--the directory name will be prepended to every filename in the list. Of course, the Makefile still needs to be edited to read from each Sourcefile. - Different rules are no longer required for source code files that live in subdirectories (such as sdl/ or hardware/). Subdirectories Just Work so go ham! In addition to those points, another important change is that the bin directory is no longer divided into platform subdirectories (Linux64, Mingw, etc). Executables now go directly into bin. If you use DEBUGMODE or target 64-bit, then subdirectories for 'debug' and '64' will be made though. Oh by the way, I don't think make clean actually removed files before on Windows. It should now. I also fixed as many little inconsistencies like that as I noticed. And now just an overview of the technical aspects that shouldn't affect anyone who doesn't REALLY care about the Makefile... objs and dep directories have been moved to a make directory. Makefile.cfg and its variants have been moved out of their various subdirectories to src/Makefile.d make distclean removes the bin and make directories entirely, but make clean and cleandep still only affect the current build target. When I say automation, I mean that a lot of copy pasting in the Makefile has been reduced. --- .gitignore | 4 +- CMakeLists.txt | 2 +- src/Makefile | 1087 +++++++++++------------------------- src/Makefile.d/detect.mk | 104 ++++ src/Makefile.d/features.mk | 76 +++ src/Makefile.d/lua.mk | 51 -- src/Makefile.d/nix.mk | 94 +--- src/Makefile.d/platform.mk | 67 +++ src/Makefile.d/sdl.mk | 153 +++-- src/Makefile.d/util.mk | 89 +++ src/Makefile.d/versions.mk | 385 ++----------- src/Makefile.d/win32.mk | 187 +++---- src/Sourcefile | 87 +++ src/blua/Sourcefile | 25 + src/hardware/Sourcefile | 13 + src/sdl/Sourcefile | 7 + 16 files changed, 1017 insertions(+), 1414 deletions(-) create mode 100644 src/Makefile.d/detect.mk create mode 100644 src/Makefile.d/features.mk delete mode 100644 src/Makefile.d/lua.mk create mode 100644 src/Makefile.d/platform.mk create mode 100644 src/Makefile.d/util.mk create mode 100644 src/Sourcefile create mode 100644 src/blua/Sourcefile create mode 100644 src/hardware/Sourcefile create mode 100644 src/sdl/Sourcefile diff --git a/.gitignore b/.gitignore index 3090417dd..7023aaa80 100644 --- a/.gitignore +++ b/.gitignore @@ -13,11 +13,11 @@ Win32_LIB_ASM_Release *.dgb *.debug *.debug.txt -/bin/VC10/ -/objs/VC10/ *.user *.db *.opendb /.vs /debian /assets/debian +/make +/bin diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d2d4a7e6..148f17ef0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ set(SRB2_SDL2_EXE_NAME srb2 CACHE STRING "Executable binary output name") include_directories(${CMAKE_CURRENT_BINARY_DIR}/src) add_subdirectory(src) -add_subdirectory(assets) +#add_subdirectory(assets) ## config.h generation diff --git a/src/Makefile b/src/Makefile index cf06ce904..dafec3645 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,817 +1,402 @@ - -# GNU Make makefile for SRB2 -############################################################################# -# Copyright (C) 1998-2000 by DooM Legacy Team. -# Copyright (C) 2003-2021 by Sonic Team Junior. +# GNU Makefile for SRB2 +# the poly3 Makefile adapted over and over... +# +# Copyright 1998-2000 DooM Legacy Team. +# Copyright 2020-2021 James R. +# Copyright 2003-2021 Sonic Team Junior. # # This program is free software distributed under the # terms of the GNU General Public License, version 2. # See the 'LICENSE' file for more details. # -# -DLINUX -> use for the GNU/Linux specific -# -D_WINDOWS -> use for the Win32/DirectX specific -# -DHAVE_SDL -> use for the SDL interface +# Special targets: # -# Sets: -# Compile the SDL/Mingw version with 'make MINGW=1' -# Compile the SDL/Linux version with 'make LINUX=1' -# Compile the SDL/Solaris version with 'make SOLARIS=1' -# Compile the SDL/FreeBSD version with 'gmake FREEBSD=1' -# Compile the SDL/Cygwin version with 'make CYGWIN32=1' -# Compile the SDL/other version try with 'make SDL=1' +# clean - remove executables and objects for this build +# cleandep - remove dependency files for this build +# distclean - remove entire executable, object and +# dependency file directory structure. +# info - print settings # -# 'Targets': -# clean -# Remove all object files -# cleandep -# Remove dependency files -# distclean -# Remove autogenerated files -# dll -# compile primary HW render DLL/SO -# all_dll -# compile all HW render and 3D sound DLLs for the set -# opengl_dll -# Pure Mingw only, compile OpenGL HW render DLL -# ds3d_dll -# Pure Mingw only, compile DirectX DirectSound HW sound DLL -# fmod_dll -# Pure Mingw only, compile FMOD HW sound DLL -# openal_dll -# Pure Mingw only, compile OpenAL HW sound DLL -# fmod_so -# Non-Mingw, compile FMOD HW sound SO -# openal_so -# Non-Mingw, compile OpenAL HW sound SO +# This Makefile can automatically detect the host system +# as well as the compiler version. If system or compiler +# version cannot be detected, you may need to set a flag +# manually. # +# On Windows machines, 32-bit Windows is always targetted. # -# Addon: -# To Cross-Compile, CC=gcc-version make * PREFIX= -# Compile with GCC 2.97 version, add 'GCC29=1' -# Compile with GCC 4.0x version, add 'GCC40=1' -# Compile with GCC 4.1x version, add 'GCC41=1' -# Compile with GCC 4.2x version, add 'GCC42=1' -# Compile with GCC 4.3x version, add 'GCC43=1' -# Compile with GCC 4.4x version, add 'GCC44=1' -# Compile with GCC 4.5x version, add 'GCC45=1' -# Compile with GCC 4.6x version, add 'GCC46=1' -# Compile a profile version, add 'PROFILEMODE=1' -# Compile a debug version, add 'DEBUGMODE=1' -# Compile with less warnings, add 'RELAXWARNINGS=1' -# Generate compiler errors for most compiler warnings, add 'ERRORMODE=1' -# Compile without NASM's tmap.nas, add 'NOASM=1' -# Compile without 3D hardware support, add 'NOHW=1' -# Compile with GDBstubs, add 'RDB=1' -# Compile without PNG, add 'NOPNG=1' -# Compile without zlib, add 'NOZLIB=1' +# Platform/system flags: # -# Addon for SDL: -# To Cross-Compile, add 'SDL_CONFIG=/usr/*/bin/sdl-config' -# Compile without SDL_Mixer, add 'NOMIXER=1' -# Compile without SDL_Mixer_X, add 'NOMIXERX=1' (Win32 only) -# Compile without GME, add 'NOGME=1' -# Compile without BSD API, add 'NONET=1' -# Compile without IPX/SPX, add 'NOIPX=1' -# Compile Mingw/SDL with S_DS3S, add 'DS3D=1' -# Compile without libopenmpt, add 'NOOPENMPT=1' -# Compile with S_FMOD3D, add 'FMOD=1' (WIP) -# Compile with S_OPENAL, add 'OPENAL=1' (WIP) -# To link with the whole SDL_Image lib to load Icons, add 'SDL_IMAGE=1' but it isn't not realy needed -# To link with SDLMain to hide console or make on a console-less binary, add 'SDLMAIN=1' +# LINUX=1, LINUX64=1 +# MINGW=1, MINGW64=1 - Windows (MinGW toolchain) +# UNIX=1 - Generic Unix like system +# FREEBSD=1 +# SDL=1 - Use SDL backend. SDL is the only backend though +# and thus, always enabled. # -############################################################################# +# A list of supported GCC versions can be found in +# Makefile.d/detect.mk -- search 'gcc_versions'. +# +# Feature flags: +# +# Safe to use online +# ------------------ +# NO_IPV6=1 - Disable IPv6 address support. +# NOHW=1 - Disable OpenGL renderer. +# ZDEBUG=1 - Enable more detailed memory debugging +# HAVE_MINIUPNPC=1 - Enable automated port forwarding. +# Already enabled by default for 32-bit +# Windows. +# NOASM=1 - Disable hand optimized assembly code for the +# Software renderer. +# NOPNG=1 - Disable PNG graphics support. (TODO: double +# check netplay compatible.) +# NOCURL=1 - Disable libcurl--HTTP capability. +# NOGME=1 - Disable game music emu, retro VGM support. +# NOOPENMPT=1 - Disable module (tracker) music support. +# NOMIXER=1 - Disable SDL Mixer (audio playback). +# NOMIXERX=1 - Forgo SDL Mixer X--revert to standard SDL +# Mixer. Mixer X is the default for Windows +# builds. +# HAVE_MIXERX=1 - Enable SDL Mixer X. Outside of Windows +# builds, SDL Mixer X is not the default. +# NOTHREADS=1 - Disable multithreading. +# +# Netplay incompatible +# -------------------- +# NONET=1 - Disable online capability. +# NOMD5=1 - Disable MD5 checksum (validation tool). +# NOPOSTPROCESSING=1 - ? +# MOBJCONSISTANCY=1 - ?? +# PACKETDROP=1 - ?? +# DEBUGMODE=1 - Enable various debugging capabilities. +# Also disables optimizations. +# NOZLIB=1 - Disable some compression capability. Implies +# NOPNG=1. +# +# Development flags: +# +# VALGRIND=1 - Enable Valgrind memory debugging support. +# PROFILEMODE=1 - Enable performance profiling (gprof). +# +# General flags for building: +# +# STATIC=1 - Use static linking. +# DISTCC=1 +# CCACHE=1 +# NOOBJDUMP=1 - Don't disassemble executable. +# NOUPX=1 - Don't compress executable. +# WINDOWSHELL=1 - Use Windows commands. +# PREFIX= - Prefix to many commands, for cross compiling. +# YASM=1 - Use Yasm instead of NASM assembler. +# STABS=1 - ? +# ECHO=1 - Print out each command in the build process. +# NOECHOFILENAMES=1 - Don't print out each that is being +# worked on. +# SILENT=1 - Print absolutely nothing except errors. +# RELAXWARNINGS=1 - Use less compiler warnings/errors. +# ERRORMODE=1 - Treat most compiler warnings as errors. +# NOCASTALIGNWARN=1 - ? +# NOLDWARNING=1 - ? +# NOSDLMAIN=1 - ? +# SDLMAIN=1 - ? +# +# Library configuration flags: +# Everything here is an override. +# +# PNG_PKGCONFIG= - libpng-config command. +# PNG_CFLAGS=, PNG_LDFLAGS= +# +# CURLCONFIG= - curl-config command. +# CURL_CFLAGS=, CURL_LDFLAGS= +# +# VALGRIND_PKGCONFIG= - pkg-config package name. +# VALGRIND_CFLAGS=, VALGRIND_LDFLAGS= +# +# LIBGME_PKGCONFIG=, LIBGME_CFLAGS=, LIBGME_LDFLAGS= -,=, +# LIBOPENMPT_PKGCONFIG= +# LIBOPENMPT_CFLAGS=, LIBOPENMPT_LDFLAGS= +# +# ZLIB_PKGCONFIG=, ZLIB_CFLAGS=, ZLIB_LDFLAGS= +# +# SDL_PKGCONFIG= +# SDL_CONFIG= - sdl-config command. +# SDL_CFLAGS=, SDL_LDFLAGS= -ifeq (,$(filter-out cleandep clean distclean,$(or $(MAKECMDGOALS),all))) -CLEANONLY=1 -else ifndef SILENT -echo=@echo "$(1)" -ifndef MAKE_RESTARTS -print=$(info $(1)) -endif -endif +clean_targets=cleandep clean distclean info -ALL_SYSTEMS=\ - PANDORA\ - LINUX64\ - MINGW64\ - HAIKU\ - DUMMY\ - DJGPPDOS\ - MINGW\ - UNIX\ - LINUX\ - SOLARIS\ - FREEBSD\ - MACOSX\ - SDL\ +.PHONY : $(clean_targets) all -# check for user specified system -ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES))) -ifeq ($(OS),Windows_NT) # all windows are Windows_NT... +goals:=$(or $(MAKECMDGOALS),all) +cleanonly:=$(filter $(clean_targets),$(goals)) +destructive:=$(filter-out info,$(cleanonly)) - $(call print,Detected a Windows system$(,) compiling for 32-bit MinGW SDL2...) +include Makefile.d/util.mk - # go for a 32-bit sdl mingw exe by default - MINGW=1 - WINDOWSHELL=1 - -else # if you on the *nix - - system:=$(shell uname -s) - - ifeq ($(system),Linux) - new_system=LINUX - else - - $(error \ - Could not automatically detect your system,\ - try specifying a system manually) - - endif - - ifeq ($(shell getconf LONG_BIT),64) - system+=64-bit - new_system:=$(new_system)64 - endif - - $(call print,Detected $(system) ($(new_system))...) - $(new_system)=1 - -endif -endif - - -# SRB2 data files -D_DIR?=../bin/Resources -D_FILES=$(D_DIR)/srb2.pk3 \ - $(D_DIR)/player.dta \ - $(D_DIR)/zones.pk3 \ - $(D_DIR)/music.dta \ - -PKG_CONFIG?=pkg-config - -ifdef PANDORA -LINUX=1 -endif - -ifdef LINUX64 -LINUX=1 -NONX86=1 -# LINUX64 does not imply X86_64=1; could mean ARM64 or Itanium -endif - -ifdef MINGW64 -MINGW=1 -NONX86=1 -NOASM=1 -# MINGW64 should not necessarily imply X86_64=1, but we make that assumption elsewhere -# Once that changes, remove this -X86_64=1 -endif #ifdef MINGW64 - -ifdef HAIKU -SDL=1 -endif - -include Makefile.cfg - -ifdef DUMMY -NOPNG=1 -NOZLIB=1 -NONET=1 -NOHW=1 -NOASM=1 -NOIPX=1 -EXENAME?=srb2dummy -OBJS=$(OBJDIR)/i_video.o -LIBS=-lm -endif - -ifdef HAIKU -NOIPX=1 -NOASM=1 -ifndef NONET -LIBS=-lnetwork -endif -CFLAGS+=-DUNIXCOMMON -PNG_CFLAGS?= -PNG_LDFLAGS?=-lpng -endif - -ifdef PANDORA -NONX86=1 -NOHW=1 -endif - -ifndef NOOPENMPT -HAVE_OPENMPT=1 -endif - -ifdef MINGW -include win32/Makefile.cfg -endif #ifdef MINGW - -ifdef UNIX -UNIXCOMMON=1 -endif - -ifdef LINUX -UNIXCOMMON=1 -ifndef NOGME -HAVE_LIBGME=1 -endif -endif - -ifdef SOLARIS -UNIXCOMMON=1 -endif - -ifdef FREEBSD -UNIXCOMMON=1 -endif - -ifdef MACOSX -UNIXCOMMON=1 -endif - -ifdef SDL - include sdl/Makefile.cfg -endif #ifdef SDL - -ifdef DISTCC - CC:=distcc $(CC) -endif - -ifdef CCACHE - CC:=ccache $(CC) -endif - -MSGFMT?=msgfmt - -ifdef WINDOWSHELL - COMPTIME=-..\comptime.bat -else - COMPTIME=-../comptime.sh -endif - -ifndef ECHO - NASM:=@$(NASM) - REMOVE:=@$(REMOVE) - CC:=@$(CC) - CXX:=@$(CXX) - OBJCOPY:=@$(OBJCOPY) - OBJDUMP:=@$(OBJDUMP) - STRIP:=@$(STRIP) - WINDRES:=@$(WINDRES) - MKDIR:=@$(MKDIR) - GZIP:=@$(GZIP) - MSGFMT:=@$(MSGFMT) - UPX:=@$(UPX) - UPX_OPTS+=-q - COMPTIME:=@$(COMPTIME) -endif - -ifdef NONET - OPTS+=-DNONET - NOCURL=1 -else -ifdef NO_IPV6 - OPTS+=-DNO_IPV6 -endif -endif - -ifdef NOHW - OPTS+=-DNOHW -else - OPTS+=-DHWRENDER - OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ - $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o \ - $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o -endif - -OPTS += -DCOMPVERSION - -ifndef NONX86 -ifndef GCC29 - ARCHOPTS?=-msse3 -mfpmath=sse -else - ARCHOPTS?=-mpentium -endif -else -ifdef X86_64 - ARCHOPTS?=-march=nocona -endif -endif - -ifndef NOASM -ifndef NONX86 - OBJS+=$(OBJDIR)/tmap.o $(OBJDIR)/tmap_mmx.o - OPTS+=-DUSEASM -endif -endif - -ifndef NOPNG -OPTS+=-DHAVE_PNG - -ifdef PNG_PKGCONFIG -PNG_CFLAGS?=$(shell $(PKG_CONFIG) $(PNG_PKGCONFIG) --cflags) -PNG_LDFLAGS?=$(shell $(PKG_CONFIG) $(PNG_PKGCONFIG) --libs) -else ifdef PREFIX -PNG_CONFIG?=$(PREFIX)-libpng-config +CC:=$(PREFIX)-gcc +endif + +OBJDUMP_OPTS?=--wide --source --line-numbers + +OBJCOPY:=$(call Prefix,objcopy) +OBJDUMP:=$(call Prefix,objdump) $(OBJDUMP_OPTS) +WINDRES:=$(call Prefix,windres) + +ifdef YASM +NASM?=yasm else -PNG_CONFIG?=libpng-config +NASM?=nasm endif -ifdef PNG_STATIC -PNG_CFLAGS?=$(shell $(PNG_CONFIG) --static --cflags) -PNG_LDFLAGS?=$(shell $(PNG_CONFIG) --static --ldflags) -else -PNG_CFLAGS?=$(shell $(PNG_CONFIG) --cflags) -PNG_LDFLAGS?=$(shell $(PNG_CONFIG) --ldflags) -endif -endif - -ifdef LINUX -PNG_CFLAGS+=-D_LARGEFILE64_SOURCE -endif - -LIBS+=$(PNG_LDFLAGS) -CFLAGS+=$(PNG_CFLAGS) - -OBJS+=$(OBJDIR)/apng.o -endif - -ifdef HAVE_LIBGME -OPTS+=-DHAVE_LIBGME - -LIBGME_PKGCONFIG?=libgme -LIBGME_CFLAGS?=$(shell $(PKG_CONFIG) $(LIBGME_PKGCONFIG) --cflags) -LIBGME_LDFLAGS?=$(shell $(PKG_CONFIG) $(LIBGME_PKGCONFIG) --libs) - -LIBS+=$(LIBGME_LDFLAGS) -CFLAGS+=$(LIBGME_CFLAGS) -endif - -ifdef HAVE_OPENMPT -OPTS+=-DHAVE_OPENMPT - -LIBOPENMPT_PKGCONFIG?=libopenmpt -LIBOPENMPT_CFLAGS?=$(shell $(PKG_CONFIG) $(LIBOPENMPT_PKGCONFIG) --cflags) -LIBOPENMPT_LDFLAGS?=$(shell $(PKG_CONFIG) $(LIBOPENMPT_PKGCONFIG) --libs) - -LIBS+=$(LIBOPENMPT_LDFLAGS) -CFLAGS+=$(LIBOPENMPT_CFLAGS) -endif - -ifndef NOZLIB -OPTS+=-DHAVE_ZLIB -ZLIB_PKGCONFIG?=zlib -ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags) -ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs) - -LIBS+=$(ZLIB_LDFLAGS) -CFLAGS+=$(ZLIB_CFLAGS) -else -NOPNG=1 -endif - -ifndef NOCURL -OPTS+=-DHAVE_CURL -CURLCONFIG?=curl-config -CURL_CFLAGS?=$(shell $(CURLCONFIG) --cflags) -CURL_LDFLAGS?=$(shell $(CURLCONFIG) --libs) - -LIBS+=$(CURL_LDFLAGS) -CFLAGS+=$(CURL_CFLAGS) -endif - -ifdef STATIC -LIBS:=-static $(LIBS) -endif - -ifdef HAVE_MINIUPNPC -ifdef NONET -HAVE_MINIUPNPC='' -else -LIBS+=-lminiupnpc -ifdef MINGW -LIBS+=-lws2_32 -liphlpapi -endif -CFLAGS+=-DHAVE_MINIUPNPC -endif -endif - -include blua/Makefile.cfg - -ifdef NOMD5 - OPTS+=-DNOMD5 -else - OBJS:=$(OBJDIR)/md5.o $(OBJS) -endif - -ifdef NOPOSTPROCESSING - OPTS+=-DNOPOSTPROCESSING -endif - - OPTS:=-fno-exceptions $(OPTS) - -ifdef MOBJCONSISTANCY - OPTS+=-DMOBJCONSISTANCY -endif - -ifdef PACKETDROP - OPTS+=-DPACKETDROP -endif - -ifdef DEBUGMODE - - # build with debugging information - WINDRESFLAGS = -D_DEBUG -ifdef GCC48 - CFLAGS+=-Og -else - CFLAGS+=-O0 -endif - CFLAGS+= -Wall -DPARANOIA -DRANGECHECK -DPACKETDROP -DMOBJCONSISTANCY -else - - - # build a normal optimised version - WINDRESFLAGS = -DNDEBUG - CFLAGS+=-O3 -endif - CFLAGS+=-g $(OPTS) $(ARCHOPTS) $(WINDRESFLAGS) - ifdef YASM ifdef STABS - NASMOPTS?= -g stabs +NASMOPTS?=-g stabs else - NASMOPTS?= -g dwarf2 +NASMOPTS?=-g dwarf2 endif else - NASMOPTS?= -g +NASMOPTS?=-g endif -ifdef PROFILEMODE - # build with profiling information - CFLAGS+=-pg - LDFLAGS+=-pg +GZIP?=gzip +GZIP_OPTS?=-9 -f -n +ifdef WINDOWSHELL +GZIP_OPTS+=--rsyncable endif -ifdef ZDEBUG - CPPFLAGS+=-DZDEBUG +UPX?=upx +UPX_OPTS?=--best --preserve-build-id +ifndef ECHO +UPX_OPTS+=-qq endif -OPTS+=$(CPPFLAGS) +include Makefile.d/detect.mk -# default EXENAME if all else fails +# make would try to remove the implicitly made directories +.PRECIOUS : %/ comptime.c + +# very sophisticated dependency +sources:=\ + $(call List,Sourcefile)\ + $(call List,blua/Sourcefile)\ + +makedir:=../make + +# -DCOMPVERSION: flag to use comptime.h +opts:=-DCOMPVERSION -g +libs:= + +nasm_format:= + +# This is a list of variables names, of which if defined, +# also defines the name as a macro to the compiler. +passthru_opts:= + +include Makefile.d/platform.mk +include Makefile.d/features.mk +include Makefile.d/versions.mk + +ifdef DEBUGMODE +makedir:=$(makedir)/debug +endif + +depdir:=$(makedir)/deps +objdir:=$(makedir)/objs + +depends:=$(basename $(filter %.c %.s,$(sources))) +objects:=$(basename $(filter %.c %.s %.nas,$(sources))) + +depends:=$(depends:%=$(depdir)/%.d) + +# comptime.o added directly to objects instead of thru +# sources because comptime.c includes comptime.h, but +# comptime.h may not exist yet. It's a headache so this is +# easier. +objects:=$(objects:=.o) comptime.o + +# windows resource file +rc_file:=$(basename $(filter %.rc,$(sources))) +ifdef rc_file +objects+=$(rc_file:=.res) +endif + +objects:=$(addprefix $(objdir)/,$(objects)) + +ifdef DEBUGMODE +bin:=../bin/debug +else +bin:=../bin +endif + +# default EXENAME (usually set by platform) EXENAME?=srb2 DBGNAME?=$(EXENAME).debug -# $(OBJDIR)/dstrings.o \ +exe:=$(bin)/$(EXENAME) +dbg:=$(bin)/$(DBGNAME) -# not too sophisticated dependency -OBJS:=$(i_main_o) \ - $(OBJDIR)/string.o \ - $(OBJDIR)/d_main.o \ - $(OBJDIR)/d_clisrv.o \ - $(OBJDIR)/d_net.o \ - $(OBJDIR)/d_netfil.o \ - $(OBJDIR)/d_netcmd.o \ - $(OBJDIR)/dehacked.o \ - $(OBJDIR)/z_zone.o \ - $(OBJDIR)/f_finale.o \ - $(OBJDIR)/f_wipe.o \ - $(OBJDIR)/g_demo.o \ - $(OBJDIR)/g_game.o \ - $(OBJDIR)/g_input.o \ - $(OBJDIR)/am_map.o \ - $(OBJDIR)/command.o \ - $(OBJDIR)/console.o \ - $(OBJDIR)/hu_stuff.o \ - $(OBJDIR)/y_inter.o \ - $(OBJDIR)/st_stuff.o \ - $(OBJDIR)/m_aatree.o \ - $(OBJDIR)/m_anigif.o \ - $(OBJDIR)/m_argv.o \ - $(OBJDIR)/m_bbox.o \ - $(OBJDIR)/m_cheat.o \ - $(OBJDIR)/m_cond.o \ - $(OBJDIR)/m_fixed.o \ - $(OBJDIR)/m_menu.o \ - $(OBJDIR)/m_misc.o \ - $(OBJDIR)/m_random.o \ - $(OBJDIR)/m_queue.o \ - $(OBJDIR)/info.o \ - $(OBJDIR)/p_ceilng.o \ - $(OBJDIR)/p_enemy.o \ - $(OBJDIR)/p_floor.o \ - $(OBJDIR)/p_inter.o \ - $(OBJDIR)/p_lights.o \ - $(OBJDIR)/p_map.o \ - $(OBJDIR)/p_maputl.o \ - $(OBJDIR)/p_mobj.o \ - $(OBJDIR)/p_polyobj.o\ - $(OBJDIR)/p_saveg.o \ - $(OBJDIR)/p_setup.o \ - $(OBJDIR)/p_sight.o \ - $(OBJDIR)/p_spec.o \ - $(OBJDIR)/p_telept.o \ - $(OBJDIR)/p_tick.o \ - $(OBJDIR)/p_user.o \ - $(OBJDIR)/p_slopes.o \ - $(OBJDIR)/tables.o \ - $(OBJDIR)/r_bsp.o \ - $(OBJDIR)/r_data.o \ - $(OBJDIR)/r_draw.o \ - $(OBJDIR)/r_main.o \ - $(OBJDIR)/r_plane.o \ - $(OBJDIR)/r_segs.o \ - $(OBJDIR)/r_skins.o \ - $(OBJDIR)/r_sky.o \ - $(OBJDIR)/r_splats.o \ - $(OBJDIR)/r_things.o \ - $(OBJDIR)/r_textures.o \ - $(OBJDIR)/r_picformats.o \ - $(OBJDIR)/r_portal.o \ - $(OBJDIR)/screen.o \ - $(OBJDIR)/v_video.o \ - $(OBJDIR)/s_sound.o \ - $(OBJDIR)/sounds.o \ - $(OBJDIR)/w_wad.o \ - $(OBJDIR)/filesrch.o \ - $(OBJDIR)/mserv.o \ - $(OBJDIR)/http-mserv.o\ - $(OBJDIR)/i_tcp.o \ - $(OBJDIR)/lzf.o \ - $(OBJDIR)/vid_copy.o \ - $(OBJDIR)/b_bot.o \ - $(i_net_o) \ - $(i_system_o) \ - $(i_sound_o) \ - $(OBJS) +build_done=Build is done, please look for $( srb2.s - $(REMOVE) $(OBJDIR)/tmp.exe - -# executable -# NOTE: DJGPP's objcopy do not have --add-gnu-debuglink - -$(BIN)/$(EXENAME): $(POS) $(OBJS) - -$(MKDIR) $(BIN) - $(call echo,Linking $(EXENAME)...) - $(LD) $(LDFLAGS) $(OBJS) -o $(BIN)/$(EXENAME) $(LIBS) ifndef VALGRIND ifndef NOOBJDUMP - $(call echo,Dumping debugging info) - $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt -ifdef WINDOWSHELL - -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt -else - -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt +all : $(dbg).txt endif endif -# mac os x lsdlsrb2 does not like objcopy -ifndef MACOSX - $(OBJCOPY) $(BIN)/$(EXENAME) $(BIN)/$(DBGNAME) - $(OBJCOPY) --strip-debug $(BIN)/$(EXENAME) - -$(OBJCOPY) --add-gnu-debuglink=$(BIN)/$(DBGNAME) $(BIN)/$(EXENAME) +ifdef STATIC +libs+=-static endif + +# build with profiling information +ifdef PROFILEMODE +opts+=-pg +libs+=-pg +endif + +ifdef DEBUGMODE +debug_opts=-D_DEBUG +else # build a normal optimized version +debug_opts=-DNDEBUG +opts+=-O3 +endif + +# debug_opts also get passed to windres +opts+=$(debug_opts) + +opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v))) + +CFLAGS:=$(opts) $(WFLAGS) $(CPPFLAGS) $(CFLAGS) +LDFLAGS:=$(libs) $(LDFLAGS) +ASFLAGS+=-x assembler-with-cpp + +ifdef DISTCC +CC:=distcc $(CC) +endif + +ifdef CCACHE +CC:=ccache $(CC) +endif + +ifndef SILENT +# makefile will 'restart' when it finishes including the +# dependencies. +ifndef MAKE_RESTARTS +ifndef destrutive +$(shell $(CC) -v) +define flags = + +CC ........ $(CC) + +CFLAGS .... $(CFLAGS) + +LDFLAGS ... $(LDFLAGS) + +endef +$(info $(flags)) +endif +# don't generate dependency files if only cleaning +ifndef cleanonly +$(info Checking dependency files...) +include $(depends) +endif +endif +endif + +LD:=$(CC) +CC:=$(CC) $(CFLAGS) +NASM:=$(NASM) $(NASMOPTS) -f $(nasm_format) +GZIP:=$(GZIP) $(GZIP_OPTS) +UPX:=$(UPX) $(UPX_OPTS) +WINDRES:=$(WINDRES) $(WINDRESFLAGS)\ + $(debug_opts) --include-dir=win32 -O coff + +%/ : + $(.)$(mkdir) $@ + +# this is needed so the target can be referenced in the +# prerequisites +.SECONDEXPANSION : + +# executable stripped of debugging symbols +$(exe) : $(dbg) | $$(@D)/ + $(.)$(OBJCOPY) --strip-debug $< $@ + $(.)-$(OBJCOPY) --add-gnu-debuglink=$< $@ ifndef NOUPX - -$(UPX) $(UPX_OPTS) $(BIN)/$(EXENAME) + $(call Echo,Compressing final executable...) + $(.)-$(UPX) $@ endif -endif - $(call echo,Build is done$(,) please look for $(EXENAME) in $(BIN)$(,) (checking for post steps)) -reobjdump: - $(call echo,Redumping debugging info) - $(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt +# original executable with debugging symbols +$(dbg) : $(objects) | $$(@D)/ + $(call Echo,Linking $(@F)...) + $(.)$(LD) -o $@ $^ $(LDFLAGS) + +# disassembly of executable +$(dbg).txt : $(dbg) + $(call Echo,Dumping debugging info...) + $(.)$(OBJDUMP) $< > $@ + $(.)$(GZIP) $@ + +# '::' means run unconditionally +# this really updates comptime.h +comptime.c :: ifdef WINDOWSHELL - -$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt + $(.)..\comptime.bat . else - -$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt + $(.)../comptime.sh . endif -$(OBJDIR): - -$(MKDIR) $(OBJDIR) +# I wish I could make dependencies out of rc files :( +$(objdir)/win32/Srb2win.res : \ + win32/afxres.h win32/resource.h -ifdef SDL -ifdef MINGW -$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ - doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ - hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ - am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ - p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -else -$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \ - doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \ - command.h hardware/hw_data.h hardware/hw_defs.h \ - hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h \ - hardware/hw_md2load.h hardware/hw_md3load.h hardware/hw_model.h hardware/u_list.h \ - am_map.h d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \ - p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@ -endif -endif - -#dependecy made by gcc itself ! -ifndef DUMMY -ifndef CLEANONLY -$(call print,Checking dependency files...) --include $(DEPS) -endif -endif - -undefine deps_rule - -# windows makes it too hard ! +# dependency recipe template +# 1: source file suffix +# 2: extra flags to gcc +define _recipe = +$(depdir)/%.d : %.$(1) | $$$$(@D)/ ifndef WINDOWSHELL -ifdef echoName -define deps_rule = - @printf "%-20.20s\r" $< - -endef +ifdef Echo_name + @printf '%-20.20s\r' $$< endif endif - -define deps_rule += - $(CC) $(CFLAGS) -M -MF $@ -MT $(OBJDIR)/$(<:.c=.o) $< + $(.)$(CC) -MM -MF $$@ -MT $(objdir)/$$(*F).o $(2) $$< endef -$(DEPDIR)/%.d: %.c - $(deps_rule) +$(eval $(call _recipe,c)) +$(eval $(call _recipe,s,$(ASFLAGS))) -$(DEPDIR)/%.d: $(INTERFACE)/%.c - $(deps_rule) +# compiling recipe template +# 1: target file suffix +# 2: source file suffix +# 3: compile command +define _recipe = +$(objdir)/%.$(1) : %.$(2) | $$$$(@D)/ + $(call Echo_name,$$<) + $(.)$(3) +endef -$(DEPDIR)/%.d: hardware/%.c - $(deps_rule) +$(eval $(call _recipe,o,c,$(CC) -c -o $$@ $$<)) +$(eval $(call _recipe,o,nas,$(NASM) -o $$@ $$<)) +$(eval $(call _recipe,o,s,$(CC) $(ASFLAGS) -c -o $$@ $$<)) +$(eval $(call _recipe,res,rc,$(WINDRES) -i $$< -o $$@)) -$(DEPDIR)/%.d: blua/%.c - $(deps_rule) +cleandep : + $(.)$(rmrf) $(depends) comptime.h -ifdef VALGRIND -$(OBJDIR)/z_zone.o: z_zone.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -DHAVE_VALGRIND $(VALGRIND_CFLAGS) -c $< -o $@ -endif +clean : + $(.)$(rmrf) $(exe) $(dbg) $(dbg).txt $(objects) -$(OBJDIR)/comptime.o:: -ifdef echoName - @echo -- comptime.c ... -endif - $(COMPTIME) . - $(CC) $(CFLAGS) $(WFLAGS) -c comptime.c -o $@ +distclean : + $(.)$(rmrf) ../bin ../objs ../deps comptime.h -$(BIN)/%.mo: locale/%.po - -$(MKDIR) $(BIN) - $(echoName) - $(MSGFMT) -f -o $@ $< - -$(OBJDIR)/%.o: %.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/%.o: $(INTERFACE)/%.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -ifdef MACOSX -$(OBJDIR)/%.o: sdl/macosx/%.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -endif - -$(OBJDIR)/%.o: hardware/%.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/%.o: blua/%.c - $(echoName) - $(CC) $(CFLAGS) $(LUA_CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/%.o: %.nas - $(echoName) - $(NASM) $(NASMOPTS) -o $@ -f $(NASMFORMAT) $< - -$(OBJDIR)/vid_copy.o: vid_copy.s asm_defs.inc - $(echoName) - $(CC) $(OPTS) $(ASFLAGS) -x assembler-with-cpp -c $< -o $@ - -$(OBJDIR)/%.o: %.s - $(echoName) - $(CC) $(OPTS) -x assembler-with-cpp -c $< -o $@ - -$(OBJDIR)/SRB2.res: win32/Srb2win.rc win32/afxres.h win32/resource.h - $(echoName) - $(WINDRES) -i $< -O rc $(WINDRESFLAGS) --include-dir=win32 -o $@ -O coff - - -ifdef SDL - -ifdef MINGW -$(OBJDIR)/win_dbg.o: win32/win_dbg.c - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -endif - -ifdef STATICHS -$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ - -ifdef MINGW -$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@ -endif +info: +ifdef WINDOWSHELL + @REM else - -$(OBJDIR)/s_fmod.o: hardware/s_fmod/s_fmod.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_fmod/s_fmod.c - -$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \ - hardware/hw_dll.h - $(echoName) - $(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o -DHW3SOUND -DUNIXCOMMON -shared -nostartfiles -c hardware/s_openal/s_openal.c + @: endif -endif - -############################################################# -# -############################################################# diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk new file mode 100644 index 000000000..f576bcf78 --- /dev/null +++ b/src/Makefile.d/detect.mk @@ -0,0 +1,104 @@ +# +# Detect the host system and compiler version. +# + +# Previously featured:\ + PANDORA\ + HAIKU\ + DUMMY\ + DJGPPDOS\ + SOLARIS\ + MACOSX\ + +all_systems:=\ + LINUX64\ + MINGW64\ + MINGW\ + UNIX\ + LINUX\ + FREEBSD\ + SDL\ + +# check for user specified system +ifeq (,$(filter $(all_systems),$(.VARIABLES))) +ifeq ($(OS),Windows_NT) # all windows are Windows_NT... + +_m=Detected a Windows system,\ + compiling for 32-bit MinGW SDL...) +$(call Print,$(_m)) + +# go for a 32-bit sdl mingw exe by default +MINGW:=1 +WINDOWSHELL:=1 + +else # if you on the *nix + +system:=$(shell uname -s) + +ifeq ($(system),Linux) +new_system:=LINUX +else + +$(error \ + Could not automatically detect your system,\ + try specifying a system manually) + +endif + +ifeq ($(shell getconf LONG_BIT),64) +system+=64-bit +new_system:=$(new_system)64 +endif + +$(call Print,Detected $(system) ($(new_system))...) +$(new_system):=1 + +endif +endif + +# This must have high to low order. +gcc_versions:=\ + 102 101\ + 93 92 91\ + 84 83 82 81\ + 75 74 73 72 71\ + 64 63 62 61\ + 55 54 53 52 51\ + 49 48 47 46 45 44 43 42 41 40 + +latest_gcc_version:=10.2 + +# Automatically set version flag, but not if one was +# manually set. And don't bother if this is a clean only +# run. +ifeq (,$(call Wildvar,GCC% destructive)) +version:=$(shell $(CC) --version) + +# check if this is in fact GCC +ifneq (,$(or $(findstring gcc,$(version)),\ + $(findstring GCC,$(version)))) + +version:=$(shell $(CC) -dumpversion) + +# Turn version into words of major, minor +v:=$(subst ., ,$(version)) +# concat. major minor +v:=$(word 1,$(v))$(word 2,$(v)) + +# If this version is not in the list, +# default to the latest supported +ifeq (,$(filter $(v),$(gcc_versions))) +define line = +Your compiler version, GCC $(version), \ +is not supported by the Makefile. +The Makefile will assume GCC $(latest_gcc_version).)) +endef +$(call Print,$(line)) +GCC$(subst .,,$(latest_gcc_version)):=1 +else +$(call Print,Detected GCC $(version) (GCC$(v))) +GCC$(v):=1 +endif + +endif +endif diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk new file mode 100644 index 000000000..abdc342b7 --- /dev/null +++ b/src/Makefile.d/features.mk @@ -0,0 +1,76 @@ +# +# Makefile for feature flags. +# + +passthru_opts+=\ + NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\ + MOBJCONSISTANCY PACKETDROP ZDEBUG\ + HAVE_MINIUPNPC\ + +# build with debugging information +ifdef DEBUGMODE +MOBJCONSISTANCY=1 +PACKETDROP=1 +opts+=-DPARANOIA -DRANGECHECK +endif + +ifndef NOHW +opts+=-DHWRENDER +sources+=$(call List,hardware/Sourcefile) +endif + +ifndef NOASM +ifndef NONX86 +sources+=tmap.nas tmap_mmx.nas +opts+=-DUSEASM +endif +endif + +ifndef NOMD5 +sources+=md5.c +endif + +ifndef NOZLIB +ifndef NOPNG +ifdef PNG_PKGCONFIG +$(eval $(call Use_pkg_config,PNG_PKGCONFIG)) +else +PNG_CONFIG?=$(call Prefix,libpng-config) +$(eval $(call Configure,PNG,$(PNG_CONFIG) \ + $(if $(PNG_STATIC),--static),,--ldflags)) +endif +ifdef LINUX +opts+=-D_LARGFILE64_SOURCE +endif +opts+=-DHAVE_PNG +sources+=apng.c +endif +endif + +ifndef NONET +ifndef NOCURL +CURLCONFIG?=curl-config +$(eval $(call Configure,CURL,$(CURLCONFIG))) +opts+=-DHAVE_CURL +endif +endif + +ifdef HAVE_MINIUPNPC +libs+=-lminiupnpc +endif + +# (Valgrind is a memory debugger.) +ifdef VALGRIND +VALGRIND_PKGCONFIG?=valgrind +$(eval $(call Use_pkg_config,VALGRIND)) +ZDEBUG=1 +opts+=-DHAVE_VALGRIND +endif + +default_packages:=\ + GME/libgme/LIBGME\ + OPENMPT/libopenmpt/LIBOPENMPT\ + ZLIB/zlib\ + +$(foreach p,$(default_packages),\ + $(eval $(call Check_pkg_config,$(p)))) diff --git a/src/Makefile.d/lua.mk b/src/Makefile.d/lua.mk deleted file mode 100644 index 12ea064b4..000000000 --- a/src/Makefile.d/lua.mk +++ /dev/null @@ -1,51 +0,0 @@ -ifdef UNIXCOMMON -LUA_CFLAGS+=-DLUA_USE_POSIX -endif -ifdef LINUX -LUA_CFLAGS+=-DLUA_USE_POSIX -endif -ifdef GCC43 -ifndef GCC44 -WFLAGS+=-Wno-logical-op -endif -endif - -OBJS:=$(OBJS) \ - $(OBJDIR)/lapi.o \ - $(OBJDIR)/lbaselib.o \ - $(OBJDIR)/ldo.o \ - $(OBJDIR)/lfunc.o \ - $(OBJDIR)/linit.o \ - $(OBJDIR)/liolib.o \ - $(OBJDIR)/llex.o \ - $(OBJDIR)/lmem.o \ - $(OBJDIR)/lobject.o \ - $(OBJDIR)/lstate.o \ - $(OBJDIR)/lstrlib.o \ - $(OBJDIR)/ltablib.o \ - $(OBJDIR)/lundump.o \ - $(OBJDIR)/lzio.o \ - $(OBJDIR)/lauxlib.o \ - $(OBJDIR)/lcode.o \ - $(OBJDIR)/ldebug.o \ - $(OBJDIR)/ldump.o \ - $(OBJDIR)/lgc.o \ - $(OBJDIR)/lopcodes.o \ - $(OBJDIR)/lparser.o \ - $(OBJDIR)/lstring.o \ - $(OBJDIR)/ltable.o \ - $(OBJDIR)/ltm.o \ - $(OBJDIR)/lvm.o \ - $(OBJDIR)/lua_script.o \ - $(OBJDIR)/lua_baselib.o \ - $(OBJDIR)/lua_mathlib.o \ - $(OBJDIR)/lua_hooklib.o \ - $(OBJDIR)/lua_consolelib.o \ - $(OBJDIR)/lua_infolib.o \ - $(OBJDIR)/lua_mobjlib.o \ - $(OBJDIR)/lua_playerlib.o \ - $(OBJDIR)/lua_skinlib.o \ - $(OBJDIR)/lua_thinkerlib.o \ - $(OBJDIR)/lua_maplib.o \ - $(OBJDIR)/lua_blockmaplib.o \ - $(OBJDIR)/lua_hudlib.o diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk index 47c944eb5..fdcd40d4d 100644 --- a/src/Makefile.d/nix.mk +++ b/src/Makefile.d/nix.mk @@ -1,74 +1,40 @@ # -# sdl/makeNIX.cfg for SRB2/?nix +# Makefile options for unices (linux, bsd...) # -#Valgrind support -ifdef VALGRIND -VALGRIND_PKGCONFIG?=valgrind -VALGRIND_CFLAGS?=$(shell $(PKG_CONFIG) $(VALGRIND_PKGCONFIG) --cflags) -VALGRIND_LDFLAGS?=$(shell $(PKG_CONFIG) $(VALGRIND_PKGCONFIG) --libs) -ZDEBUG=1 -LIBS+=$(VALGRIND_LDFLAGS) -ifdef GCC46 -WFLAGS+=-Wno-error=unused-but-set-variable -WFLAGS+=-Wno-unused-but-set-variable -endif -endif +EXENAME?=lsdl2srb2 -# -#here is GNU/Linux and other -# +opts+=-DUNIXCOMMON -DLUA_USE_POSIX +libs+=-lm - OPTS=-DUNIXCOMMON - - #LDFLAGS = -L/usr/local/lib - LIBS=-lm -ifdef LINUX - LIBS+=-lrt -ifdef NOTERMIOS - OPTS+=-DNOTERMIOS -endif -endif - -ifdef LINUX64 - OPTS+=-DLINUX64 -endif - -# -#here is Solaris -# -ifdef SOLARIS - NOIPX=1 - NOASM=1 - OPTS+=-DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP - OPTS+=-I/usr/local/include -I/opt/sfw/include - LDFLAGS+=-L/opt/sfw/lib - LIBS+=-lsocket -lnsl -endif - -# -#here is FreeBSD -# -ifdef FREEBSD - OPTS+=-DLINUX -DFREEBSD -I/usr/X11R6/include - SDL_CONFIG?=sdl11-config - LDFLAGS+=-L/usr/X11R6/lib - LIBS+=-lipx -lkvm -endif - -# -#here is Mac OS X -# -ifdef MACOSX - OBJS+=$(OBJDIR)/mac_resources.o - OBJS+=$(OBJDIR)/mac_alert.o - LIBS+=-framework CoreFoundation +ifndef nasm_format +nasm_format:=elf -DLINUX endif ifndef NOHW - OPTS+=-I/usr/X11R6/include - LDFLAGS+=-L/usr/X11R6/lib +opts+=-I/usr/X11R6/include +libs+=-L/usr/X11R6/lib endif - # name of the exefile - EXENAME?=lsdl2srb2 +SDL=1 + +# In common usage. +ifdef LINUX +libs+=-lrt +passthru_opts+=NOTERMIOS +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 +endif + +# FIXME +#ifdef SOLARIS +#NOIPX=1 +#NOASM=1 +#opts+=-I/usr/local/include -I/opt/sfw/include \ +# -DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP +#libs+=-L/opt/sfw/lib -lsocket -lnsl +#endif diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk new file mode 100644 index 000000000..ca00806d9 --- /dev/null +++ b/src/Makefile.d/platform.mk @@ -0,0 +1,67 @@ +# +# Platform specific options. +# + +PKG_CONFIG?=pkg-config + +ifdef WINDOWSHELL +rmrf?=DEL /S /Q +mkdir?=MD +else +rmrf?=rm -rf +mkdir?=mkdir -p +endif + +ifdef LINUX64 +LINUX=1 +endif + +ifdef MINGW64 +MINGW=1 +endif + +ifdef LINUX +UNIX=1 +ifdef LINUX64 +NONX86=1 +# LINUX64 does not imply X86_64=1; +# could mean ARM64 or Itanium +platform=linux/64 +else +platform=linux +endif +else ifdef FREEBSD +UNIX=1 +platform=freebsd +else ifdef SOLARIS # FIXME +UNIX=1 +platform=solaris +else ifdef CYGWIN32 # FIXME +nasm_format=win32 +platform=cygwin +else ifdef MINGW +ifdef MINGW64 +NONX86=1 +NOASM=1 +# MINGW64 should not necessarily imply X86_64=1, +# but we make that assumption elsewhere +# Once that changes, remove this +X86_64=1 +platform=mingw +else +platform=mingw/64 +endif +include Makefile.d/win32.mk +endif + +ifdef platform +makedir:=$(makedir)/$(platform) +endif + +ifdef UNIX +include Makefile.d/nix.mk +endif + +ifdef SDL +include Makefile.d/sdl.mk +endif diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index 45d0d6ba7..43a2ffced 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -1,125 +1,98 @@ # -# sdl/makefile.cfg for SRB2/SDL +# Makefile options for SDL2 backend. # # -#SDL...., *looks at Alam*, THIS IS A MESS! +# SDL...., *looks at Alam*, THIS IS A MESS! +# +# ...a little bird flexes its muscles... # -ifdef UNIXCOMMON -include sdl/MakeNIX.cfg -endif +makedir:=$(makedir)/SDL -ifdef PANDORA -include sdl/SRB2Pandora/Makefile.cfg -endif #ifdef PANDORA +sources+=$(call List,sdl/Sourcefile) +opts+=-DDIRECTFULLSCREEN -DHAVE_SDL -ifdef CYGWIN32 -include sdl/MakeCYG.cfg -endif #ifdef CYGWIN32 +# FIXME +#ifdef PANDORA +#include sdl/SRB2Pandora/Makefile.cfg +#endif #ifdef PANDORA -ifdef SDL_PKGCONFIG -SDL_CFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --cflags) -SDL_LDFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --libs) -else -ifdef PREFIX - SDL_CONFIG?=$(PREFIX)-sdl2-config -else - SDL_CONFIG?=sdl2-config -endif - -ifdef STATIC - SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) - SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --static-libs) -else - SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) - SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --libs) -endif -endif - - - #use the x86 asm code -ifndef CYGWIN32 -ifndef NOASM - USEASM=1 -endif -endif - - OBJS+=$(OBJDIR)/i_video.o $(OBJDIR)/dosstr.o $(OBJDIR)/endtxt.o $(OBJDIR)/hwsym_sdl.o - - OPTS+=-DDIRECTFULLSCREEN -DHAVE_SDL +# FIXME +#ifdef CYGWIN32 +#include sdl/MakeCYG.cfg +#endif #ifdef CYGWIN32 ifndef NOHW - OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/ogl_sdl.o +sources+=sdl/ogl_sdl.c endif ifdef NOMIXER - i_sound_o=$(OBJDIR)/sdl_sound.o +sources+=sdl/sdl_sound.c else - i_sound_o=$(OBJDIR)/mixer_sound.o - OPTS+=-DHAVE_MIXER -ifdef HAVE_MIXERX - OPTS+=-DHAVE_MIXERX - SDL_LDFLAGS+=-lSDL2_mixer_ext -else - SDL_LDFLAGS+=-lSDL2_mixer -endif +opts+=-DHAVE_MIXER +sources+=sdl/mixer_sound.c + + ifdef HAVE_MIXERX + opts+=-DHAVE_MIXERX + libs+=-lSDL2_mixer_ext + else + libs+=-lSDL2_mixer + endif endif ifndef NOTHREADS - OPTS+=-DHAVE_THREADS - OBJS+=$(OBJDIR)/i_threads.o +opts+=-DHAVE_THREADS +sources+=sdl/i_threads.c endif -ifdef SDL_TTF - OPTS+=-DHAVE_TTF - SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz - OBJS+=$(OBJDIR)/i_ttf.o +ifdef SDL_PKGCONFIG +$(eval $(call Use_pkg_config,SDL)) +else +SDL_CONFIG?=$(call Prefix,sdl2-config) +SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) +SDL_LDFLAGS?=$(shell $(SDL_CONFIG) \ + $(if $(STATIC),--static-libs,--libs)) +$(eval $(call Propogate_flags,SDL)) endif -ifdef SDL_IMAGE - OPTS+=-DHAVE_IMAGE - SDL_LDFLAGS+=-lSDL2_image +# use the x86 asm code +ifndef CYGWIN32 +ifndef NOASM +USEASM=1 +endif endif -ifdef SDL_NET - OPTS+=-DHAVE_SDLNET - SDL_LDFLAGS+=-lSDL2_net -endif +# FIXME +#ifdef SDL_TTF +# OPTS+=-DHAVE_TTF +# SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz +# OBJS+=$(OBJDIR)/i_ttf.o +#endif + +# FIXME +#ifdef SDL_IMAGE +# OPTS+=-DHAVE_IMAGE +# SDL_LDFLAGS+=-lSDL2_image +#endif + +# FIXME +#ifdef SDL_NET +# OPTS+=-DHAVE_SDLNET +# SDL_LDFLAGS+=-lSDL2_net +#endif ifdef MINGW ifndef NOSDLMAIN - SDLMAIN=1 +SDLMAIN=1 endif endif ifdef SDLMAIN - OPTS+=-DSDLMAIN +opts+=-DSDLMAIN else ifdef MINGW - SDL_CFLAGS+=-Umain - SDL_LDFLAGS+=-mconsole +opts+=-Umain +libs+=-mconsole endif endif - -ifndef NOHW -ifdef OPENAL -ifdef MINGW - LIBS:=-lopenal32 $(LIBS) -else - LIBS:=-lopenal $(LIBS) -endif -else -ifdef MINGW -ifdef DS3D - LIBS:=-ldsound -luuid $(LIBS) -endif -endif -endif -endif - -CFLAGS+=$(SDL_CFLAGS) -LIBS:=$(SDL_LDFLAGS) $(LIBS) -ifdef STATIC - LIBS+=$(shell $(SDL_CONFIG) --static-libs) -endif diff --git a/src/Makefile.d/util.mk b/src/Makefile.d/util.mk new file mode 100644 index 000000000..88f141bee --- /dev/null +++ b/src/Makefile.d/util.mk @@ -0,0 +1,89 @@ +# +# Utility macros for the rest of the Makefiles. +# + +Ifnot=$(if $(1),$(3),$(2)) +Ifndef=$(call Ifnot,$($(1)),$(2),$(3)) + +# Match and expand a list of variables by pattern. +Wildvar=$(foreach v,$(filter $(1),$(.VARIABLES)),$($(v))) + +# Read a list of words from file and prepend each with the +# directory of the file. +List=$(addprefix $(dir $(1)),$(file < $(1))) + +define Propogate_flags = +opts+=$$($(1)_CFLAGS) +libs+=$$($(1)_LDFLAGS) +endef + +# Set library's _CFLAGS and _LDFLAGS from some command. +# Automatically propogates the flags too. +# 1: variable prefix (e.g. CURL) +# 2: start of command (e.g. curl-config) +# --- optional ---- +# 3: CFLAGS command arguments, default '--cflags' +# 4: LDFLAGS command arguments, default '--libs' +# 5: common command arguments at the end of command +define Configure = +$(1)_CFLAGS?=$$(shell $(2) $(or $(3),--cflags) $(5)) +$(1)_LDFLAGS?=$$(shell $(2) $(or $(4),--libs) $(5)) +$(call Propogate_flags,$(1)) +endef + +# Configure library with pkg-config. The package name is +# taken from a _PKGCONFIG variable. +# 1: variable prefix +# +# LIBGME_PKGCONFIG=libgme +# $(eval $(call Use_pkg_config,LIBGME)) +define Use_pkg_config = +$(call Configure,$(1),$(PKG_CONFIG),,,$($(1)_PKGCONFIG)) +endef + +# Check disabling flag and configure package in one step +# according to delimited argument. +# (There is only one argument, but it split by slash.) +# 1/: short form library name (uppercase). This is +# prefixed with 'NO' and 'HAVE_'. E.g. NOGME, HAVE_GME +# /2: package name (e.g. libgme) +# /3: variable prefix +# +# The following example would check if NOGME is not +# defined before attempting to define LIBGME_CFLAGS and +# LIBGME_LDFLAGS as with Use_pkg_config. +# +# $(eval $(call Check_pkg_config,GME/libgme/LIBGME)) +define Check_pkg_config = +_p:=$(subst /, ,$(1)) +_v1:=$$(word 1,$$(_p)) +_v2:=$$(or $$(word 3,$$(_p)),$$(_v1)) +ifndef NO$$(_v1) +$$(_v2)_PKGCONFIG?=$$(word 2,$$(_p)) +$$(eval $$(call Use_pkg_config,$$(_v2))) +opts+=-DHAVE_$$(_v1) +endif +endef + +# $(call Prefix,gcc) +Prefix=$(if $(PREFIX),$(PREFIX)-)$(1) + +Echo= +Echo_name= +Print= + +ifndef SILENT +Echo=@echo "$(1)" +ifndef ECHO +ifndef NOECHOFILENAMES +Echo_name=$(call Echo,-- $(1) ...) +endif +endif +ifndef MAKE_RESTARTS +ifndef destructive +Print=$(info $(1)) +endif +endif +endif + +.=$(call Ifndef,ECHO,@) diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index 075cd2d3a..fe2b6b851 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -1,215 +1,23 @@ -# vim: ft=make # -# Makefile.cfg for SRB2 +# Flags to put a sock in GCC! # -# -# GNU compiler & tools' flags -# and other things -# - -# See the following variable don't start with 'GCC'. This is -# to avoid a false positive with the version detection... - -SUPPORTED_GCC_VERSIONS:=\ - 101 102\ - 91 92 93\ - 81 82 83 84\ - 71 72 73 74 75\ - 61 62 63 64\ - 51 52 53 54 55\ - 40 41 42 43 44 45 46 47 48 49 - -LATEST_GCC_VERSION=10.2 - -# gcc or g++ -ifdef PREFIX - CC=$(PREFIX)-gcc - CXX=$(PREFIX)-g++ - OBJCOPY=$(PREFIX)-objcopy - OBJDUMP=$(PREFIX)-objdump - STRIP=$(PREFIX)-strip - WINDRES=$(PREFIX)-windres -else - OBJCOPY=objcopy - OBJDUMP=objdump - STRIP=strip - WINDRES=windres +# See the versions list in detect.mk +# This will define all version flags going backward. +# Yes, it's magic. +define _predecessor = +ifdef GCC$(firstword $(1)) +GCC$(lastword $(1)):=1 endif +endef +_n:=$(words $(gcc_versions)) +$(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\ + $(addprefix =,$(wordlist 2,$(_n),$(gcc_versions)))),\ + $(and $(findstring =,$(v)),\ + $(eval $(call _predecessor,$(subst =, ,$(v)))))) -# because Apple screws with us on this -# need to get bintools from homebrew -ifdef MACOSX - CC=clang - CXX=clang - OBJCOPY=gobjcopy - OBJDUMP=gobjdump -endif - -# Automatically set version flag, but not if one was manually set -# And don't bother if this is a clean only run -ifeq (,$(filter GCC% CLEANONLY,$(.VARIABLES))) - version:=$(shell $(CC) --version) - # check if this is in fact GCC - ifneq (,$(or $(findstring gcc,$(version)),$(findstring GCC,$(version)))) - version:=$(shell $(CC) -dumpversion) - - # Turn version into words of major, minor - v:=$(subst ., ,$(version)) - # concat. major minor - v:=$(word 1,$(v))$(word 2,$(v)) - - # If this version is not in the list, default to the latest supported - ifeq (,$(filter $(v),$(SUPPORTED_GCC_VERSIONS))) - define line = - Your compiler version, GCC $(version), is not supported by the Makefile. - The Makefile will assume GCC $(LATEST_GCC_VERSION).)) - endef - $(call print,$(line)) - GCC$(subst .,,$(LATEST_GCC_VERSION))=1 - else - $(call print,Detected GCC $(version) (GCC$(v))) - GCC$(v)=1 - endif - endif -endif - -ifdef GCC102 -GCC101=1 -endif - -ifdef GCC101 -GCC93=1 -endif - -ifdef GCC93 -GCC92=1 -endif - -ifdef GCC92 -GCC91=1 -endif - -ifdef GCC91 -GCC84=1 -endif - -ifdef GCC84 -GCC83=1 -endif - -ifdef GCC83 -GCC82=1 -endif - -ifdef GCC82 -GCC81=1 -endif - -ifdef GCC81 -GCC75=1 -endif - -ifdef GCC75 -GCC74=1 -endif - -ifdef GCC74 -GCC73=1 -endif - -ifdef GCC73 -GCC72=1 -endif - -ifdef GCC72 -GCC71=1 -endif - -ifdef GCC71 -GCC64=1 -endif - -ifdef GCC64 -GCC63=1 -endif - -ifdef GCC63 -GCC62=1 -endif - -ifdef GCC62 -GCC61=1 -endif - -ifdef GCC61 -GCC55=1 -endif - -ifdef GCC55 -GCC54=1 -endif - -ifdef GCC54 -GCC53=1 -endif - -ifdef GCC53 -GCC52=1 -endif - -ifdef GCC52 -GCC51=1 -endif - -ifdef GCC51 -GCC49=1 -endif - -ifdef GCC49 -GCC48=1 -endif - -ifdef GCC48 -GCC47=1 -endif - -ifdef GCC47 -GCC46=1 -endif - -ifdef GCC46 -GCC45=1 -endif - -ifdef GCC45 -GCC44=1 -endif - -ifdef GCC44 -GCC43=1 -endif - -ifdef GCC43 -GCC42=1 -endif - -ifdef GCC42 -GCC41=1 -endif - -ifdef GCC41 -GCC40=1 -VCHELP=1 -endif - -ifdef GCC295 -GCC29=1 -endif - -OLDWFLAGS:=$(WFLAGS) # -W -Wno-unused -WFLAGS=-Wall +WFLAGS:=-Wall ifndef GCC295 #WFLAGS+=-Wno-packed endif @@ -222,15 +30,13 @@ endif #WFLAGS+=-Wsystem-headers WFLAGS+=-Wfloat-equal #WFLAGS+=-Wtraditional -ifdef VCHELP - WFLAGS+=-Wdeclaration-after-statement - WFLAGS+=-Wno-error=declaration-after-statement -endif WFLAGS+=-Wundef ifndef GCC295 WFLAGS+=-Wendif-labels endif ifdef GCC41 + WFLAGS+=-Wdeclaration-after-statement + WFLAGS+=-Wno-error=declaration-after-statement WFLAGS+=-Wshadow endif #WFLAGS+=-Wlarger-than-%len% @@ -308,8 +114,6 @@ ifdef ERRORMODE WFLAGS+=-Werror endif -WFLAGS+=$(OLDWFLAGS) - ifdef GCC43 #WFLAGS+=-Wno-error=clobbered endif @@ -338,141 +142,36 @@ ifdef GCC81 WFLAGS+=-Wno-error=multistatement-macros endif - -#indicate platform and what interface use with -ifndef LINUX -ifndef FREEBSD -ifndef CYGWIN32 -ifndef MINGW -ifndef MINGW64 -ifndef SDL -ifndef DUMMY -$(error No interface or platform flag defined) -endif -endif -endif -endif -endif -endif -endif - -#determine the interface directory (where you put all i_*.c) -i_net_o=$(OBJDIR)/i_net.o -i_system_o=$(OBJDIR)/i_system.o -i_sound_o=$(OBJDIR)/i_sound.o -i_main_o=$(OBJDIR)/i_main.o -#set OBJDIR and BIN's starting place -OBJDIR=../objs -BIN=../bin -DEPDIR=../dep -#Nasm ASM and rm -ifdef YASM -NASM?=yasm +ifdef NONX86 + ifdef X86_64 # yeah that SEEMS contradictory + opts+=-march=nocona + endif else -NASM?=nasm -endif -REMOVE?=rm -f -MKDIR?=mkdir -p -GZIP?=gzip -GZIP_OPTS?=-9 -f -n -GZIP_OPT2=$(GZIP_OPTS) --rsyncable -UPX?=upx -UPX_OPTS?=--best --preserve-build-id -ifndef ECHO -UPX_OPTS+=-q + ifndef GCC29 + opts+=-msse3 -mfpmath=sse + else + opts+=-mpentium + endif endif -#Interface Setup -ifdef DUMMY - INTERFACE=dummy - OBJDIR:=$(OBJDIR)/dummy - BIN:=$(BIN)/dummy - DEPDIR:=$(DEPDIR)/dummy -else -ifdef LINUX - NASMFORMAT=elf -DLINUX - SDL=1 -ifdef LINUX64 - OBJDIR:=$(OBJDIR)/Linux64 - BIN:=$(BIN)/Linux64 - DEPDIR:=$(DEPDIR)/Linux64 -else - OBJDIR:=$(OBJDIR)/Linux - BIN:=$(BIN)/Linux - DEPDIR:=$(DEPDIR)/Linux -endif -else -ifdef FREEBSD - INTERFACE=sdl - NASMFORMAT=elf -DLINUX - SDL=1 - - OBJDIR:=$(OBJDIR)/FreeBSD - BIN:=$(BIN)/FreeBSD - DEPDIR:=$(DEPDIR)/Linux -else -ifdef SOLARIS - INTERFACE=sdl - NASMFORMAT=elf -DLINUX - SDL=1 - - OBJDIR:=$(OBJDIR)/Solaris - BIN:=$(BIN)/Solaris - DEPDIR:=$(DEPDIR)/Solaris -else -ifdef CYGWIN32 - INTERFACE=sdl - NASMFORMAT=win32 - SDL=1 - - OBJDIR:=$(OBJDIR)/cygwin - BIN:=$(BIN)/Cygwin - DEPDIR:=$(DEPDIR)/Cygwin -else -ifdef MINGW64 - #NASMFORMAT=win64 - SDL=1 - OBJDIR:=$(OBJDIR)/Mingw64 - BIN:=$(BIN)/Mingw64 - DEPDIR:=$(DEPDIR)/Mingw64 -else -ifdef MINGW - NASMFORMAT=win32 - SDL=1 - OBJDIR:=$(OBJDIR)/Mingw - BIN:=$(BIN)/Mingw - DEPDIR:=$(DEPDIR)/Mingw -endif -endif -endif -endif -endif -endif -endif - -ifdef ARCHNAME - OBJDIR:=$(OBJDIR)/$(ARCHNAME) - BIN:=$(BIN)/$(ARCHNAME) - DEPDIR:=$(DEPDIR)/$(ARCHNAME) -endif - -OBJDUMP_OPTS?=--wide --source --line-numbers -LD=$(CC) - -ifdef SDL - INTERFACE=sdl - OBJDIR:=$(OBJDIR)/SDL - DEPDIR:=$(DEPDIR)/SDL -endif - -ifndef DUMMY ifdef DEBUGMODE - OBJDIR:=$(OBJDIR)/Debug - BIN:=$(BIN)/Debug - DEPDIR:=$(DEPDIR)/Debug +ifdef GCC48 +opts+=-Og else - OBJDIR:=$(OBJDIR)/Release - BIN:=$(BIN)/Release - DEPDIR:=$(DEPDIR)/Release +opts+=O0 +endif +endif + +ifdef VALGRIND +ifdef GCC46 +WFLAGS+=-Wno-error=unused-but-set-variable +WFLAGS+=-Wno-unused-but-set-variable +endif +endif + +# Lua +ifdef GCC43 +ifndef GCC44 +WFLAGS+=-Wno-logical-op endif endif diff --git a/src/Makefile.d/win32.mk b/src/Makefile.d/win32.mk index 702ae3765..0c671b268 100644 --- a/src/Makefile.d/win32.mk +++ b/src/Makefile.d/win32.mk @@ -1,136 +1,99 @@ # -# win32/Makefile.cfg for SRB2/Minwgw +# Mingw, if you don't know, that's Win32/Win64 # -# -#Mingw, if you don't know, that's Win32/Win64 -# +ifndef MINGW64 +EXENAME?=srb2win.exe +else +EXENAME?=srb2win64.exe +endif + +sources+=win32/Srb2win.rc +opts+=-DSTDC_HEADERS +libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 + +nasm_format:=win32 + +SDL=1 + +ifndef NOHW +opts+=-DUSE_WGL_SWAP +endif ifdef MINGW64 - HAVE_LIBGME=1 - LIBGME_CFLAGS=-I../libs/gme/include - LIBGME_LDFLAGS=-L../libs/gme/win64 -lgme -ifdef HAVE_OPENMPT - LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc - LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86_64/mingw -lopenmpt -endif -ifndef NOMIXERX - HAVE_MIXERX=1 - SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDLMixerX/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows +libs+=-lws2_32 else - SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDL2_mixer/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -endif +ifdef NO_IPV6 +libs+=-lwsock32 else - HAVE_LIBGME=1 - LIBGME_CFLAGS=-I../libs/gme/include - LIBGME_LDFLAGS=-L../libs/gme/win32 -lgme -ifdef HAVE_OPENMPT - LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc - LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86/mingw -lopenmpt +libs+=-lws2_32 endif -ifndef NOMIXERX - HAVE_MIXERX=1 - SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDLMixerX/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -else - SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main - SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDL2_mixer/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -endif -endif - -ifndef NOASM - USEASM=1 endif ifndef NONET -ifndef MINGW64 #miniupnc is broken with MINGW64 - HAVE_MINIUPNPC=1 +ifndef MINGW64 # miniupnc is broken with MINGW64 +opts+=-I../libs -DSTATIC_MINIUPNPC +libs+=-L../libs/miniupnpc/mingw$(32) -lws2_32 -liphlpapi endif endif - OPTS=-DSTDC_HEADERS - -ifndef GCC44 - #OPTS+=-mms-bitfields -endif - - LIBS+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 -ifdef MINGW64 - LIBS+=-lws2_32 +ifndef MINGW64 +32=32 +x86=x86 +i686=i686 else -ifdef NO_IPV6 - LIBS+=-lwsock32 +32=64 +x86=x86_64 +i686=x86_64 +endif + +mingw:=$(i686)-w64-mingw32 + +define _set = +$(1)_CFLAGS?=$($(1)_opts) +$(1)_LDFLAGS?=$($(1)_libs) +endef + +lib:=../libs/gme +LIBGME_opts:=-I$(lib)/include +LIBGME_libs:=-L$(lib)/win$(32) -lgme +$(eval $(call _set,LIBGME)) + +lib:=../libs/libopenmpt +LIBOPENMPT_opts:=-I$(lib)/inc +LIBOPENMPT_libs:=-L$(lib)/lib/$(x86)/mingw -lopenmpt +$(eval $(call _set,LIBOPENMPT)) + +ifndef NOMIXERX +HAVE_MIXERX=1 +lib:=../libs/SDLMixerX/$(mingw) else - LIBS+=-lws2_32 -endif +lib:=../libs/SDL2_mixer/$(mingw) endif - # name of the exefile - EXENAME?=srb2win.exe +mixer_opts:=-I$(lib)/include/SDL2 +mixer_libs:=-L$(lib)/lib -ifdef SDL - i_system_o+=$(OBJDIR)/SRB2.res - #i_main_o+=$(OBJDIR)/win_dbg.o -ifndef NOHW - OPTS+=-DUSE_WGL_SWAP -endif -endif +lib:=../libs/SDL2/$(mingw) +SDL_opts:=-I$(lib)/include/SDL2\ + $(mixer_opts) -Dmain=SDL_main +SDL_libs:=-L$(lib)/lib $(mixer_libs)\ + -lmingw32 -lSDL2main -lSDL2 -mwindows +$(eval $(call _set,SDL)) +lib:=../libs/zlib +ZLIB_opts:=-I$(lib) +ZLIB_libs:=-L$(lib)/win32 -lz$(32) +$(eval $(call _set,ZLIB)) -ZLIB_CFLAGS?=-I../libs/zlib -ifdef MINGW64 -ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz64 -else -ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz32 -endif - -ifndef NOPNG ifndef PNG_CONFIG - PNG_CFLAGS?=-I../libs/libpng-src -ifdef MINGW64 - PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng64 -else - PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng32 -endif #MINGW64 -endif #PNG_CONFIG -endif #NOPNG - -ifdef GETTEXT -ifndef CCBS - MSGFMT?=../libs/gettext/bin32/msgfmt.exe -endif -ifdef MINGW64 - CPPFLAGS+=-I../libs/gettext/include64 - LDFLAGS+=-L../libs/gettext/lib64 - LIBS+=-lmingwex -else - CPPFLAGS+=-I../libs/gettext/include32 - LDFLAGS+=-L../libs/gettext/lib32 - STATIC_GETTEXT=1 -endif #MINGW64 -ifdef STATIC_GETTEXT - LIBS+=-lasprintf -lintl -else - LIBS+=-lintl.dll -endif #STATIC_GETTEXT -endif #GETTEXT - -ifdef HAVE_MINIUPNPC - CPPFLAGS+=-I../libs/ -DSTATIC_MINIUPNPC -ifdef MINGW64 - LDFLAGS+=-L../libs/miniupnpc/mingw64 -else - LDFLAGS+=-L../libs/miniupnpc/mingw32 -endif #MINGW64 +lib:=../libs/libpng-src +PNG_opts:=-I$(lib) +PNG_libs:=-L$(lib)/projects -lpng$(32) +$(eval $(call _set,PNG)) endif -ifndef NOCURL - CURL_CFLAGS+=-I../libs/curl/include -ifdef MINGW64 - CURL_LDFLAGS+=-L../libs/curl/lib64 -lcurl -else - CURL_LDFLAGS+=-L../libs/curl/lib32 -lcurl -endif #MINGW64 -endif +lib:=../libs/curl +CURL_opts:=-I$(lib)/include +CURL_libs:=-L$(lib)/lib$(32) -lcurl +$(eval $(call _set,CURL)) diff --git a/src/Sourcefile b/src/Sourcefile new file mode 100644 index 000000000..9f27f2810 --- /dev/null +++ b/src/Sourcefile @@ -0,0 +1,87 @@ +string.c +d_main.c +d_clisrv.c +d_net.c +d_netfil.c +d_netcmd.c +dehacked.c +z_zone.c +f_finale.c +f_wipe.c +g_demo.c +g_game.c +g_input.c +am_map.c +command.c +console.c +hu_stuff.c +y_inter.c +st_stuff.c +m_aatree.c +m_anigif.c +m_argv.c +m_bbox.c +m_cheat.c +m_cond.c +m_fixed.c +m_menu.c +m_misc.c +m_random.c +m_queue.c +info.c +p_ceilng.c +p_enemy.c +p_floor.c +p_inter.c +p_lights.c +p_map.c +p_maputl.c +p_mobj.c +p_polyobj.c +p_saveg.c +p_setup.c +p_sight.c +p_spec.c +p_telept.c +p_tick.c +p_user.c +p_slopes.c +tables.c +r_bsp.c +r_data.c +r_draw.c +r_main.c +r_plane.c +r_segs.c +r_skins.c +r_sky.c +r_splats.c +r_things.c +r_textures.c +r_picformats.c +r_portal.c +screen.c +v_video.c +s_sound.c +sounds.c +w_wad.c +filesrch.c +mserv.c +http-mserv.c +i_tcp.c +lzf.c +vid_copy.s +b_bot.c +lua_script.c +lua_baselib.c +lua_mathlib.c +lua_hooklib.c +lua_consolelib.c +lua_infolib.c +lua_mobjlib.c +lua_playerlib.c +lua_skinlib.c +lua_thinkerlib.c +lua_maplib.c +lua_blockmaplib.c +lua_hudlib.c diff --git a/src/blua/Sourcefile b/src/blua/Sourcefile new file mode 100644 index 000000000..f99c89c8d --- /dev/null +++ b/src/blua/Sourcefile @@ -0,0 +1,25 @@ +lapi.c +lbaselib.c +ldo.c +lfunc.c +linit.c +liolib.c +llex.c +lmem.c +lobject.c +lstate.c +lstrlib.c +ltablib.c +lundump.c +lzio.c +lauxlib.c +lcode.c +ldebug.c +ldump.c +lgc.c +lopcodes.c +lparser.c +lstring.c +ltable.c +ltm.c +lvm.c diff --git a/src/hardware/Sourcefile b/src/hardware/Sourcefile new file mode 100644 index 000000000..1c05de76c --- /dev/null +++ b/src/hardware/Sourcefile @@ -0,0 +1,13 @@ +hw_bsp.c +hw_draw.c +hw_light.c +hw_main.c +hw_clip.c +hw_md2.c +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/sdl/Sourcefile b/src/sdl/Sourcefile new file mode 100644 index 000000000..82d5ce073 --- /dev/null +++ b/src/sdl/Sourcefile @@ -0,0 +1,7 @@ +i_net.c +i_system.c +i_main.c +i_video.c +dosstr.c +endtxt.c +hwsym_sdl.c From 53d1cbe8264196e46911c86bc4be13d44aa35dfe Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 4 May 2021 16:50:50 -0700 Subject: [PATCH 131/241] Appveyor: update executable directory --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2acc2f712..d9cff5333 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -100,9 +100,9 @@ build_script: after_build: - if [%X86_64%] == [1] ( - set "BUILD_PATH=bin\Mingw64\Release" + set "BUILD_PATH=bin\64" ) else ( - set "BUILD_PATH=bin\Mingw\Release" + set "BUILD_PATH=bin" ) - if [%X86_64%] == [1] ( set "CONFIGURATION=%CONFIGURATION%64" ) - ccache -s From 888073d64d1885cae0ad8b5d54bfec31e9793e0a Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 4 May 2021 16:54:47 -0700 Subject: [PATCH 132/241] Fix make clean printing header --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index dafec3645..8c31b212d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -285,7 +285,7 @@ ifndef SILENT # makefile will 'restart' when it finishes including the # dependencies. ifndef MAKE_RESTARTS -ifndef destrutive +ifndef destructive $(shell $(CC) -v) define flags = From 8840bef2cb7c1913599d4c17b5027988638b50c8 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 4 May 2021 17:05:17 -0700 Subject: [PATCH 133/241] Appveyor: update to correct executable directory this time --- appveyor.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d9cff5333..8a20986cf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -99,16 +99,11 @@ build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% ERRORMODE=1 -k after_build: -- if [%X86_64%] == [1] ( - set "BUILD_PATH=bin\64" - ) else ( - set "BUILD_PATH=bin" - ) - if [%X86_64%] == [1] ( set "CONFIGURATION=%CONFIGURATION%64" ) - ccache -s - set BUILD_ARCHIVE=%REPO%-%GITSHORT%-%CONFIGURATION%.7z - set BUILDSARCHIVE=%REPO%-%CONFIGURATION%.7z -- cmd: 7z a %BUILD_ARCHIVE% %BUILD_PATH% -xr!.gitignore +- cmd: 7z a %BUILD_ARCHIVE% bin -xr!.gitignore - appveyor PushArtifact %BUILD_ARCHIVE% #- cmd: copy %BUILD_ARCHIVE% %BUILDSARCHIVE% #- appveyor PushArtifact %BUILDSARCHIVE% From 3d7205d4942d1e1b2627fdf5acf9d9c82437a97b Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 4 May 2021 22:34:20 -0700 Subject: [PATCH 134/241] Fix minor errors with Windows ECHO, DEL, MD - Quotes were not removed by ECHO. - DEL would print an error on nonexistent file. - MD would do this plus return a nonzero exit code. --- src/Makefile | 10 ++++++---- src/Makefile.d/platform.mk | 8 ++++---- src/Makefile.d/util.mk | 5 ++++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Makefile b/src/Makefile index 8c31b212d..0c44afe55 100644 --- a/src/Makefile +++ b/src/Makefile @@ -315,7 +315,7 @@ WINDRES:=$(WINDRES) $(WINDRESFLAGS)\ $(debug_opts) --include-dir=win32 -O coff %/ : - $(.)$(mkdir) $@ + $(.)$(mkdir) $(call Windows_path,$@) # this is needed so the target can be referenced in the # prerequisites @@ -385,14 +385,16 @@ $(eval $(call _recipe,o,nas,$(NASM) -o $$@ $$<)) $(eval $(call _recipe,o,s,$(CC) $(ASFLAGS) -c -o $$@ $$<)) $(eval $(call _recipe,res,rc,$(WINDRES) -i $$< -o $$@)) +_rm=$(.)$(rmrf) $(call Windows_path,$(1)) + cleandep : - $(.)$(rmrf) $(depends) comptime.h + $(call _rm,$(depends) comptime.h) clean : - $(.)$(rmrf) $(exe) $(dbg) $(dbg).txt $(objects) + $(call _rm,$(exe) $(dbg) $(dbg).txt $(objects)) distclean : - $(.)$(rmrf) ../bin ../objs ../deps comptime.h + $(call _rm,../bin ../objs ../deps comptime.h) info: ifdef WINDOWSHELL diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk index ca00806d9..4f110594e 100644 --- a/src/Makefile.d/platform.mk +++ b/src/Makefile.d/platform.mk @@ -5,11 +5,11 @@ PKG_CONFIG?=pkg-config ifdef WINDOWSHELL -rmrf?=DEL /S /Q -mkdir?=MD +rmrf=2>NUL DEL /S /Q +mkdir=-2>NUL MD else -rmrf?=rm -rf -mkdir?=mkdir -p +rmrf=rm -rf +mkdir=mkdir -p endif ifdef LINUX64 diff --git a/src/Makefile.d/util.mk b/src/Makefile.d/util.mk index 88f141bee..e76e32422 100644 --- a/src/Makefile.d/util.mk +++ b/src/Makefile.d/util.mk @@ -12,6 +12,9 @@ Wildvar=$(foreach v,$(filter $(1),$(.VARIABLES)),$($(v))) # directory of the file. List=$(addprefix $(dir $(1)),$(file < $(1))) +# Convert path separators to backslash on Windows. +Windows_path=$(if $(WINDOWSHELL),$(subst /,\,$(1)),$(1)) + define Propogate_flags = opts+=$$($(1)_CFLAGS) libs+=$$($(1)_LDFLAGS) @@ -73,7 +76,7 @@ Echo_name= Print= ifndef SILENT -Echo=@echo "$(1)" +Echo=@echo $(1) ifndef ECHO ifndef NOECHOFILENAMES Echo_name=$(call Echo,-- $(1) ...) From f9813844e7f0dfa6229062b1ebd83e4e8150c120 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 5 May 2021 03:56:57 -0700 Subject: [PATCH 135/241] Update CMakeLists.txt to use Sourcefiles This establishes (near) parity of source code file lists between the Makefile and CMakeLists.txt To make that change I messed around CMakeLists.txt a bit. It now uses target_sources and target_compile_definitions. I also removed some MSVC stuff since we don't actually care about MSVC--it made things easier. CMake minimum version 3.0 -> 3.13 for target_sources. --- CMakeLists.txt | 17 +- src/CMakeLists.txt | 383 ++---------------------------------- src/blua/CMakeLists.txt | 1 + src/hardware/CMakeLists.txt | 1 + src/sdl/CMakeLists.txt | 136 ++----------- 5 files changed, 47 insertions(+), 491 deletions(-) create mode 100644 src/blua/CMakeLists.txt create mode 100644 src/hardware/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 148f17ef0..bc764fc87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.13) # Enable CCache early set(SRB2_USE_CCACHE OFF CACHE BOOL "Use CCache") @@ -34,12 +34,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") ### Useful functions -# Prepend sources with current source directory -function(prepend_sources SOURCE_FILES) - foreach(SOURCE_FILE ${${SOURCE_FILES}}) - set(MODIFIED ${MODIFIED} ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}) - endforeach() - set(${SOURCE_FILES} ${MODIFIED} PARENT_SCOPE) +# Add sources from Sourcefile +function(target_sourcefile type) + file(STRINGS Sourcefile list + REGEX "[-0-9A-Za-z_]+\.${type}") + target_sources(SRB2SDL2 PRIVATE ${list}) endfunction() # Macro to add OSX framework @@ -118,8 +117,10 @@ set(SRB2_SDL2_EXE_NAME srb2 CACHE STRING "Executable binary output name") include_directories(${CMAKE_CURRENT_BINARY_DIR}/src) +add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32) + add_subdirectory(src) -#add_subdirectory(assets) +add_subdirectory(assets) ## config.h generation diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 47a790194..0148d605f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,224 +1,12 @@ # SRB2 Core # Core sources -set(SRB2_CORE_SOURCES - am_map.c - b_bot.c - command.c - comptime.c - console.c - d_clisrv.c - d_main.c - d_net.c - d_netcmd.c - d_netfil.c - dehacked.c - f_finale.c - f_wipe.c - filesrch.c - g_demo.c - g_game.c - g_input.c - hu_stuff.c - i_tcp.c - info.c - lzf.c - m_aatree.c - m_anigif.c - m_argv.c - m_bbox.c - m_cheat.c - m_cond.c - m_fixed.c - m_menu.c - m_misc.c - m_queue.c - m_random.c - md5.c - mserv.c - http-mserv.c - s_sound.c - screen.c - sounds.c - st_stuff.c - #string.c - tables.c - v_video.c - w_wad.c - y_inter.c - z_zone.c -) +target_sourcefile(c) +target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h) -set(SRB2_CORE_HEADERS - am_map.h - b_bot.h - byteptr.h - command.h - console.h - d_clisrv.h - d_event.h - d_main.h - d_net.h - d_netcmd.h - d_netfil.h - d_player.h - d_think.h - d_ticcmd.h - dehacked.h - doomdata.h - doomdef.h - doomstat.h - doomtype.h - endian.h - f_finale.h - fastcmp.h - filesrch.h - g_demo.h - g_game.h - g_input.h - g_state.h - hu_stuff.h - i_joy.h - i_net.h - i_sound.h - i_system.h - i_tcp.h - i_video.h - info.h - keys.h - lzf.h - m_aatree.h - m_anigif.h - m_argv.h - m_bbox.h - m_cheat.h - m_cond.h - m_dllist.h - m_fixed.h - m_menu.h - m_misc.h - m_queue.h - m_random.h - m_swap.h - md5.h - mserv.h - p5prof.h - s_sound.h - screen.h - sounds.h - st_stuff.h - tables.h - v_video.h - w_wad.h - y_inter.h - z_zone.h - - config.h.in -) - -set(SRB2_CORE_RENDER_SOURCES - r_bsp.c - r_data.c - r_draw.c - r_main.c - r_plane.c - r_segs.c - r_skins.c - r_sky.c - r_splats.c - r_things.c - r_textures.c - r_picformats.c - r_portal.c - - r_bsp.h - r_data.h - r_defs.h - r_draw.h - r_local.h - r_main.h - r_plane.h - r_segs.h - r_skins.h - r_sky.h - r_splats.h - r_state.h - r_things.h - r_textures.h - r_picformats.h - r_portal.h -) - -set(SRB2_CORE_GAME_SOURCES - p_ceilng.c - p_enemy.c - p_floor.c - p_inter.c - p_lights.c - p_map.c - p_maputl.c - p_mobj.c - p_polyobj.c - p_saveg.c - p_setup.c - p_sight.c - p_slopes.c - p_spec.c - p_telept.c - p_tick.c - p_user.c - - p_local.h - p_maputl.h - p_mobj.h - p_polyobj.h - p_pspr.h - p_saveg.h - p_setup.h - p_slopes.h - p_spec.h - p_tick.h -) - -if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) - set(SRB2_CORE_SOURCES ${SRB2_CORE_SOURCES} string.c) -endif() - -prepend_sources(SRB2_CORE_SOURCES) -prepend_sources(SRB2_CORE_HEADERS) -prepend_sources(SRB2_CORE_RENDER_SOURCES) -prepend_sources(SRB2_CORE_GAME_SOURCES) - -set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/config.h) -source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS}) -source_group("Renderer" FILES ${SRB2_CORE_RENDER_SOURCES}) -source_group("Game" FILES ${SRB2_CORE_GAME_SOURCES}) - - -set(SRB2_ASM_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/vid_copy.s -) - -set(SRB2_NASM_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/tmap_mmx.nas - ${CMAKE_CURRENT_SOURCE_DIR}/tmap.nas -) - -if(MSVC) - list(APPEND SRB2_NASM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tmap_vc.nas) -endif() - -set(SRB2_NASM_OBJECTS - ${CMAKE_CURRENT_BINARY_DIR}/tmap_mmx.obj - ${CMAKE_CURRENT_BINARY_DIR}/tmap.obj -) - -if(MSVC) - list(APPEND SRB2_NASM_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/tmap_vc.obj) -endif() - -source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES}) +set(SRB2_ASM_SOURCES vid_copy.s) +set(SRB2_NASM_SOURCES tmap_mmx.nas tmap.nas) ### Configuration set(SRB2_CONFIG_HAVE_PNG ON CACHE BOOL @@ -254,90 +42,7 @@ if(${CMAKE_SYSTEM} MATCHES "Windows") ###set on Windows only "Use SRB2's internal copies of required dependencies (SDL2, PNG, zlib, GME, OpenMPT).") endif() -set(SRB2_LUA_SOURCES - lua_baselib.c - lua_blockmaplib.c - lua_consolelib.c - lua_hooklib.c - lua_hudlib.c - lua_infolib.c - lua_maplib.c - lua_mathlib.c - lua_mobjlib.c - lua_playerlib.c - lua_script.c - lua_skinlib.c - lua_thinkerlib.c -) -set(SRB2_LUA_HEADERS - lua_hook.h - lua_hud.h - lua_libs.h - lua_script.h -) - -prepend_sources(SRB2_LUA_SOURCES) -prepend_sources(SRB2_LUA_HEADERS) - -source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS}) - -set(SRB2_BLUA_SOURCES - blua/lapi.c - blua/lauxlib.c - blua/lbaselib.c - blua/lcode.c - blua/ldebug.c - blua/ldo.c - blua/ldump.c - blua/lfunc.c - blua/lgc.c - blua/linit.c - blua/liolib.c - blua/llex.c - blua/lmem.c - blua/lobject.c - blua/lopcodes.c - blua/lparser.c - blua/lstate.c - blua/lstring.c - blua/lstrlib.c - blua/ltable.c - blua/ltablib.c - blua/ltm.c - blua/lundump.c - blua/lvm.c - blua/lzio.c -) -set(SRB2_BLUA_HEADERS - blua/lapi.h - blua/lauxlib.h - blua/lcode.h - blua/ldebug.h - blua/ldo.h - blua/lfunc.h - blua/lgc.h - blua/llex.h - blua/llimits.h - blua/lmem.h - blua/lobject.h - blua/lopcodes.h - blua/lparser.h - blua/lstate.h - blua/lstring.h - blua/ltable.h - blua/ltm.h - blua/lua.h - blua/luaconf.h - blua/lualib.h - blua/lundump.h - blua/lvm.h - blua/lzio.h -) - -prepend_sources(SRB2_BLUA_SOURCES) -prepend_sources(SRB2_BLUA_HEADERS) - -source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS}) +add_subdirectory(blua) if(${SRB2_CONFIG_HAVE_GME}) if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) @@ -353,7 +58,7 @@ if(${SRB2_CONFIG_HAVE_GME}) endif() if(${GME_FOUND}) set(SRB2_HAVE_GME ON) - add_definitions(-DHAVE_LIBGME) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_LIBGME) else() message(WARNING "You have specified that GME is available but it was not found.") endif() @@ -373,7 +78,7 @@ if(${SRB2_CONFIG_HAVE_OPENMPT}) endif() if(${OPENMPT_FOUND}) set(SRB2_HAVE_OPENMPT ON) - add_definitions(-DHAVE_OPENMPT) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_OPENMPT) else() message(WARNING "You have specified that OpenMPT is available but it was not found.") endif() @@ -396,8 +101,7 @@ if(${SRB2_CONFIG_HAVE_MIXERX}) endif() if(${MIXERX_FOUND}) set(SRB2_HAVE_MIXERX ON) - set(SRB2_SDL2_SOUNDIMPL mixer_sound.c) - add_definitions(-DHAVE_MIXERX) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXERX) else() message(WARNING "You have specified that SDL Mixer X is available but it was not found.") endif() @@ -417,7 +121,7 @@ if(${SRB2_CONFIG_HAVE_ZLIB}) endif() if(${ZLIB_FOUND}) set(SRB2_HAVE_ZLIB ON) - add_definitions(-DHAVE_ZLIB) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_ZLIB) else() message(WARNING "You have specified that ZLIB is available but it was not found. SRB2 may not compile correctly.") endif() @@ -438,14 +142,9 @@ if(${SRB2_CONFIG_HAVE_PNG} AND ${SRB2_CONFIG_HAVE_ZLIB}) endif() if(${PNG_FOUND}) set(SRB2_HAVE_PNG ON) - add_definitions(-DHAVE_PNG) - add_definitions(-D_LARGEFILE64_SOURCE) - set(SRB2_PNG_SOURCES apng.c) - set(SRB2_PNG_HEADERS apng.h) - prepend_sources(SRB2_PNG_SOURCES) - prepend_sources(SRB2_PNG_HEADERS) - source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS} - ${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS}) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_PNG) + target_compile_definitions(SRB2SDL2 PRIVATE -D_LARGEFILE64_SOURCE) + target_sources(SRB2SDL2 PRIVATE apng.c) else() message(WARNING "You have specified that PNG is available but it was not found. SRB2 may not compile correctly.") endif() @@ -466,7 +165,7 @@ if(${SRB2_CONFIG_HAVE_CURL}) endif() if(${CURL_FOUND}) set(SRB2_HAVE_CURL ON) - add_definitions(-DHAVE_CURL) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_CURL) else() message(WARNING "You have specified that CURL is available but it was not found. SRB2 may not compile correctly.") endif() @@ -474,59 +173,19 @@ endif() if(${SRB2_CONFIG_HAVE_THREADS}) set(SRB2_HAVE_THREADS ON) - set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/i_threads.h) - add_definitions(-DHAVE_THREADS) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_THREADS) endif() if(${SRB2_CONFIG_HWRENDER}) - add_definitions(-DHWRENDER) - set(SRB2_HWRENDER_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.c - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.c - ) - - set (SRB2_HWRENDER_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_drv.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_glob.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2load.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md3load.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_model.h - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/u_list.h - ) - - set(SRB2_R_OPENGL_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.c - ) - - set(SRB2_R_OPENGL_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.h - ) - + target_compile_definitions(SRB2SDL2 PRIVATE -DHWRENDER) + add_subdirectory(hardware) endif() if(${SRB2_CONFIG_HWRENDER} AND ${SRB2_CONFIG_STATIC_OPENGL}) find_package(OpenGL) if(${OPENGL_FOUND}) - add_definitions(-DHWRENDER) - add_definitions(-DSTATIC_OPENGL) + target_compile_definitions(SRB2SDL2 PRIVATE -DHWRENDER) + target_compile_definitions(SRB2SDL2 PRIVATE -DSTATIC_OPENGL) else() message(WARNING "You have specified static opengl but opengl was not found. Not setting HWRENDER.") endif() @@ -548,11 +207,11 @@ if(${SRB2_CONFIG_USEASM}) enable_language(ASM_NASM) endif() set(SRB2_USEASM ON) - add_definitions(-DUSEASM) + target_compile_definitions(SRB2SDL2 PRIVATE -DUSEASM) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse") else() set(SRB2_USEASM OFF) - add_definitions(-DNONX86 -DNORUSEASM) + target_compile_definitions(SRB2SDL2 PRIVATE -DNONX86 -DNORUSEASM) endif() # Targets @@ -588,7 +247,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -Wno-absolute-value) endif() -add_definitions(-DCMAKECONFIG) +target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG) #add_library(SRB2Core STATIC # ${SRB2_CORE_SOURCES} diff --git a/src/blua/CMakeLists.txt b/src/blua/CMakeLists.txt new file mode 100644 index 000000000..4e9c67d2f --- /dev/null +++ b/src/blua/CMakeLists.txt @@ -0,0 +1 @@ +target_sourcefile(c) diff --git a/src/hardware/CMakeLists.txt b/src/hardware/CMakeLists.txt new file mode 100644 index 000000000..4e9c67d2f --- /dev/null +++ b/src/hardware/CMakeLists.txt @@ -0,0 +1 @@ +target_sourcefile(c) diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index a7f015c86..a1d55ad4d 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -21,46 +21,25 @@ if(${SRB2_CONFIG_SDL2_USEMIXER}) endif() if(${SDL2_MIXER_FOUND}) set(SRB2_HAVE_MIXER ON) - set(SRB2_SDL2_SOUNDIMPL mixer_sound.c) + target_sources(SRB2SDL2 PRIVATE mixer_sound.c) else() message(WARNING "You specified that SDL2_mixer is available, but it was not found. Falling back to sdl sound.") - set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) + target_sources(SRB2SDL2 PRIVATE sdl_sound.c) endif() elseif(${MIXERX_FOUND}) - set(SRB2_SDL2_SOUNDIMPL mixer_sound.c) + target_sources(SRB2SDL2 PRIVATE mixer_sound.c) else() - set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) + target_sources(SRB2SDL2 PRIVATE sdl_sound.c) endif() -set(SRB2_SDL2_SOURCES - dosstr.c - endtxt.c - hwsym_sdl.c - i_main.c - i_net.c - i_system.c - i_ttf.c - i_video.c - #IMG_xpm.c - ogl_sdl.c +target_sourcefile(c) - ${SRB2_SDL2_SOUNDIMPL} -) - -set(SRB2_SDL2_HEADERS - endtxt.h - hwsym_sdl.h - i_ttf.h - ogl_sdl.h - sdlmain.h -) +target_sources(SRB2SDL2 PRIVATE ogl_sdl.c) if(${SRB2_CONFIG_HAVE_THREADS}) - set(SRB2_SDL2_SOURCES ${SRB2_SDL2_SOURCES} i_threads.c) + target_sources(SRB2SDL2 PRIVATE i_threads.c) endif() -source_group("Interface Code" FILES ${SRB2_SDL2_SOURCES} ${SRB2_SDL2_HEADERS}) - # Dependency if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) set(SDL2_FOUND ON) @@ -76,79 +55,31 @@ else() endif() if(${SDL2_FOUND}) - set(SRB2_SDL2_TOTAL_SOURCES - ${SRB2_CORE_SOURCES} - ${SRB2_CORE_HEADERS} - ${SRB2_PNG_SOURCES} - ${SRB2_PNG_HEADERS} - ${SRB2_CORE_RENDER_SOURCES} - ${SRB2_CORE_GAME_SOURCES} - ${SRB2_LUA_SOURCES} - ${SRB2_LUA_HEADERS} - ${SRB2_BLUA_SOURCES} - ${SRB2_BLUA_HEADERS} - ${SRB2_SDL2_SOURCES} - ${SRB2_SDL2_HEADERS} - ) - - source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS} - ${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS}) - source_group("Renderer" FILES ${SRB2_CORE_RENDER_SOURCES}) - source_group("Game" FILES ${SRB2_CORE_GAME_SOURCES}) - source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES}) - source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS}) - source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS}) - - if(${SRB2_CONFIG_HWRENDER}) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${SRB2_HWRENDER_SOURCES} - ${SRB2_HWRENDER_HEADERS} - ${SRB2_R_OPENGL_SOURCES} - ${SRB2_R_OPENGL_HEADERS} - ) - - source_group("Hardware" FILES ${SRB2_HWRENDER_SOURCES} ${SRB2_HWRENDER_HEADERS}) - source_group("Hardware\\OpenGL Renderer" FILES ${SRB2_R_OPENGL_SOURCES} ${SRB2_R_OPENGL_HEADERS}) - endif() - if(${SRB2_USEASM}) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${SRB2_NASM_SOURCES} - ) - if(MSVC) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${SRB2_NASM_OBJECTS} - ) - set_source_files_properties(${SRB2_NASM_OBJECTS} PROPERTIES GENERATED ON) - else() - list(APPEND SRB2_SDL2_TOTAL_SOURCES ${SRB2_ASM_SOURCES}) - set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES LANGUAGE C) - set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") - endif() + target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES} + ${SRB2_NASM_SOURCES}) + set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES LANGUAGE C) + set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") endif() if(${CMAKE_SYSTEM} MATCHES Windows) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} - ${CMAKE_SOURCE_DIR}/src/win32/win_dbg.c - ${CMAKE_SOURCE_DIR}/src/win32/Srb2win.rc - ) + target_sources(SRB2SDL2 PRIVATE + ../win32/win_dbg.c + ../win32/Srb2win.rc) endif() if(${CMAKE_SYSTEM} MATCHES Darwin) set(MACOSX_BUNDLE_ICON_FILE Srb2mac.icns) set_source_files_properties(macosx/Srb2mac.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") - set(SRB2_SDL2_MAC_SOURCES + target_sources(SRB2SDL2 PRIVATE macosx/mac_alert.c macosx/mac_alert.h macosx/mac_resources.c macosx/mac_resources.h macosx/Srb2mac.icns ) - source_group("Interface Code\\OSX Compatibility" FILES ${SRB2_SDL2_MAC_SOURCES}) - set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} ${SRB2_SDL2_MAC_SOURCES}) endif() - add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 ${SRB2_SDL2_TOTAL_SOURCES}) if(${CMAKE_SYSTEM} MATCHES Windows) set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2win) elseif(${CMAKE_SYSTEM} MATCHES Linux) @@ -205,18 +136,6 @@ if(${SDL2_FOUND}) set(ASM_ASSEMBLER_OBJFORMAT ${CMAKE_ASM_NASM_OBJECT_FORMAT}) set_source_files_properties(${SRB2_NASM_SOURCES} LANGUAGE ASM_NASM) endif() - - if(MSVC) - # using assembler with msvc doesn't work, must do it manually - foreach(ASMFILE ${SRB2_NASM_SOURCES}) - get_filename_component(ASMFILE_NAME ${ASMFILE} NAME_WE) - set(ASMFILE_NAME ${ASMFILE_NAME}.obj) - add_custom_command(TARGET SRB2SDL2 PRE_LINK - COMMAND ${ASM_ASSEMBLER_TEMP} ARGS -f ${ASM_ASSEMBLER_OBJFORMAT} -o ${CMAKE_CURRENT_BINARY_DIR}/${ASMFILE_NAME} ${ASMFILE} - COMMENT "assemble ${ASMFILE_NAME}." - ) - endforeach() - endif() endif() set_target_properties(SRB2SDL2 PROPERTIES VERSION ${SRB2_VERSION}) @@ -230,31 +149,6 @@ if(${SDL2_FOUND}) ) endif() - if(MSVC) - if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) - set(SDL2_MAIN_FOUND ON) - if(${SRB2_SYSTEM_BITS} EQUAL 64) - set(SDL2_MAIN_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/include/SDL2) - set(SDL2_MAIN_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/lib -lSDL2main") - else() # 32-bit - set(SDL2_MAIN_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/include/SDL2) - set(SDL2_MAIN_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/lib -lSDL2main") - endif() - else() - find_package(SDL2_MAIN REQUIRED) - endif() - target_link_libraries(SRB2SDL2 PRIVATE - ${SDL2_MAIN_LIBRARIES} - ) - target_compile_options(SRB2SDL2 PRIVATE - /Umain - /D_CRT_SECURE_NO_WARNINGS # something about string functions. - /D_CRT_NONSTDC_NO_DEPRECATE - /DSDLMAIN - /D_WINSOCK_DEPRECATED_NO_WARNINGS # Don't care - ) - endif() - target_include_directories(SRB2SDL2 PRIVATE ${SDL2_INCLUDE_DIRS} ${SDL2_MIXER_INCLUDE_DIRS} From ec8b63d6759f0c124693ea6d5a521e8d82efd566 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 5 May 2021 21:21:55 -0700 Subject: [PATCH 136/241] Makefile: remove last of unused flags --- src/Makefile.d/nix.mk | 2 +- src/Makefile.d/platform.mk | 4 ++-- src/Makefile.d/sdl.mk | 23 ++--------------------- 3 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk index fdcd40d4d..f1645e1e4 100644 --- a/src/Makefile.d/nix.mk +++ b/src/Makefile.d/nix.mk @@ -30,7 +30,7 @@ opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD libs+=-L/usr/X11R6/lib -lipx -lkvm endif -# FIXME +# FIXME: UNTESTED #ifdef SOLARIS #NOIPX=1 #NOASM=1 diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk index 4f110594e..be8d35830 100644 --- a/src/Makefile.d/platform.mk +++ b/src/Makefile.d/platform.mk @@ -33,10 +33,10 @@ endif else ifdef FREEBSD UNIX=1 platform=freebsd -else ifdef SOLARIS # FIXME +else ifdef SOLARIS # FIXME: UNTESTED UNIX=1 platform=solaris -else ifdef CYGWIN32 # FIXME +else ifdef CYGWIN32 # FIXME: UNTESTED nasm_format=win32 platform=cygwin else ifdef MINGW diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index 43a2ffced..99ca624e6 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -13,12 +13,12 @@ makedir:=$(makedir)/SDL sources+=$(call List,sdl/Sourcefile) opts+=-DDIRECTFULLSCREEN -DHAVE_SDL -# FIXME +# FIXME: UNTESTED #ifdef PANDORA #include sdl/SRB2Pandora/Makefile.cfg #endif #ifdef PANDORA -# FIXME +# FIXME: UNTESTED #ifdef CYGWIN32 #include sdl/MakeCYG.cfg #endif #ifdef CYGWIN32 @@ -63,25 +63,6 @@ USEASM=1 endif endif -# FIXME -#ifdef SDL_TTF -# OPTS+=-DHAVE_TTF -# SDL_LDFLAGS+=-lSDL2_ttf -lfreetype -lz -# OBJS+=$(OBJDIR)/i_ttf.o -#endif - -# FIXME -#ifdef SDL_IMAGE -# OPTS+=-DHAVE_IMAGE -# SDL_LDFLAGS+=-lSDL2_image -#endif - -# FIXME -#ifdef SDL_NET -# OPTS+=-DHAVE_SDLNET -# SDL_LDFLAGS+=-lSDL2_net -#endif - ifdef MINGW ifndef NOSDLMAIN SDLMAIN=1 From d325c7e6d314562f79f1890f7d0c5bf5e1496c93 Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 7 May 2021 17:45:56 +0200 Subject: [PATCH 137/241] The year is 2021 --- src/am_map.c | 2 +- src/am_map.h | 2 +- src/apng.c | 2 +- src/apng.h | 2 +- src/asm_defs.inc | 2 +- src/b_bot.c | 2 +- src/b_bot.h | 2 +- src/byteptr.h | 2 +- src/command.c | 2 +- src/command.h | 2 +- src/console.c | 2 +- src/console.h | 2 +- src/d_clisrv.c | 2 +- src/d_clisrv.h | 2 +- src/d_event.h | 2 +- src/d_main.c | 2 +- src/d_main.h | 2 +- src/d_net.c | 2 +- src/d_net.h | 2 +- src/d_netcmd.c | 2 +- src/d_netcmd.h | 2 +- src/d_netfil.c | 2 +- src/d_netfil.h | 2 +- src/d_player.h | 2 +- src/d_think.h | 2 +- src/d_ticcmd.h | 2 +- src/deh_lua.c | 2 +- src/deh_lua.h | 2 +- src/deh_soc.c | 2 +- src/deh_soc.h | 2 +- src/deh_tables.c | 2 +- src/deh_tables.h | 2 +- src/dehacked.c | 2 +- src/dehacked.h | 2 +- src/doomdata.h | 2 +- src/doomdef.h | 2 +- src/doomstat.h | 2 +- src/doomtype.h | 2 +- src/endian.h | 2 +- src/f_finale.c | 2 +- src/f_finale.h | 2 +- src/f_wipe.c | 2 +- src/g_demo.c | 2 +- src/g_demo.h | 2 +- src/g_game.c | 2 +- src/g_game.h | 2 +- src/g_input.c | 2 +- src/g_input.h | 2 +- src/g_state.h | 2 +- src/hardware/hw_batching.c | 2 +- src/hardware/hw_batching.h | 2 +- src/hardware/hw_cache.c | 2 +- src/hardware/hw_data.h | 2 +- src/hardware/hw_draw.c | 2 +- src/hardware/hw_drv.h | 2 +- src/hardware/hw_glob.h | 2 +- src/hardware/hw_light.h | 2 +- src/hardware/hw_main.h | 2 +- src/hardware/hw_md2.c | 2 +- src/hardware/hw_md2.h | 2 +- src/hardware/r_opengl/r_opengl.c | 2 +- src/http-mserv.c | 2 +- src/hu_stuff.c | 2 +- src/hu_stuff.h | 2 +- src/i_addrinfo.c | 2 +- src/i_addrinfo.h | 2 +- src/i_joy.h | 2 +- src/i_net.h | 2 +- src/i_sound.h | 2 +- src/i_system.h | 2 +- src/i_tcp.c | 2 +- src/i_tcp.h | 2 +- src/i_threads.h | 2 +- src/i_video.h | 2 +- src/info.c | 2 +- src/info.h | 2 +- src/keys.h | 2 +- src/lua_baselib.c | 2 +- src/lua_blockmaplib.c | 4 ++-- src/lua_consolelib.c | 2 +- src/lua_hook.h | 2 +- src/lua_hooklib.c | 2 +- src/lua_hud.h | 2 +- src/lua_hudlib.c | 2 +- src/lua_infolib.c | 2 +- src/lua_libs.h | 2 +- src/lua_maplib.c | 2 +- src/lua_mathlib.c | 2 +- src/lua_mobjlib.c | 2 +- src/lua_playerlib.c | 2 +- src/lua_polyobjlib.c | 4 ++-- src/lua_script.c | 2 +- src/lua_script.h | 2 +- src/lua_skinlib.c | 2 +- src/lua_taglib.c | 4 ++-- src/lua_thinkerlib.c | 2 +- src/m_aatree.c | 2 +- src/m_aatree.h | 2 +- src/m_anigif.c | 2 +- src/m_anigif.h | 2 +- src/m_argv.c | 2 +- src/m_argv.h | 2 +- src/m_bbox.c | 2 +- src/m_bbox.h | 2 +- src/m_cheat.c | 2 +- src/m_cheat.h | 2 +- src/m_cond.c | 2 +- src/m_cond.h | 2 +- src/m_dllist.h | 2 +- src/m_fixed.c | 2 +- src/m_fixed.h | 2 +- src/m_menu.c | 2 +- src/m_menu.h | 2 +- src/m_misc.c | 2 +- src/m_misc.h | 2 +- src/m_perfstats.c | 2 +- src/m_perfstats.h | 2 +- src/m_queue.c | 2 +- src/m_queue.h | 2 +- src/m_random.c | 2 +- src/m_random.h | 2 +- src/m_swap.h | 2 +- src/mserv.c | 4 ++-- src/mserv.h | 4 ++-- src/p_ceilng.c | 2 +- src/p_enemy.c | 2 +- src/p_floor.c | 2 +- src/p_inter.c | 2 +- src/p_lights.c | 2 +- src/p_local.h | 2 +- src/p_map.c | 2 +- src/p_maputl.c | 2 +- src/p_maputl.h | 2 +- src/p_mobj.c | 2 +- src/p_mobj.h | 2 +- src/p_polyobj.c | 2 +- src/p_polyobj.h | 2 +- src/p_pspr.h | 2 +- src/p_saveg.c | 2 +- src/p_saveg.h | 2 +- src/p_setup.c | 2 +- src/p_setup.h | 2 +- src/p_sight.c | 2 +- src/p_slopes.c | 2 +- src/p_slopes.h | 2 +- src/p_spec.c | 2 +- src/p_spec.h | 2 +- src/p_telept.c | 2 +- src/p_tick.c | 2 +- src/p_tick.h | 2 +- src/p_user.c | 2 +- src/r_bsp.c | 2 +- src/r_bsp.h | 2 +- src/r_data.h | 2 +- src/r_defs.h | 2 +- src/r_draw16.c | 2 +- src/r_draw8_npo2.c | 2 +- src/r_local.h | 2 +- src/r_main.c | 2 +- src/r_main.h | 2 +- src/r_patch.c | 2 +- src/r_patch.h | 2 +- src/r_patchrotation.c | 2 +- src/r_patchrotation.h | 2 +- src/r_picformats.c | 4 ++-- src/r_picformats.h | 4 ++-- src/r_plane.h | 2 +- src/r_portal.c | 2 +- src/r_portal.h | 2 +- src/r_segs.c | 2 +- src/r_segs.h | 2 +- src/r_skins.c | 2 +- src/r_skins.h | 2 +- src/r_sky.c | 2 +- src/r_sky.h | 2 +- src/r_splats.h | 2 +- src/r_state.h | 2 +- src/r_textures.h | 2 +- src/r_things.h | 2 +- src/s_sound.c | 2 +- src/s_sound.h | 2 +- src/screen.c | 2 +- src/screen.h | 2 +- src/sdl/i_system.c | 2 +- src/sdl/i_threads.c | 2 +- src/sdl/i_video.c | 2 +- src/sdl/mixer_sound.c | 4 ++-- src/sdl/ogl_sdl.c | 2 +- src/sdl/ogl_sdl.h | 2 +- src/sdl/sdl_sound.c | 2 +- src/sdl/sdlmain.h | 2 +- src/sounds.c | 2 +- src/sounds.h | 2 +- src/st_stuff.c | 2 +- src/st_stuff.h | 2 +- src/strcasestr.c | 2 +- src/string.c | 2 +- src/tables.c | 2 +- src/tables.h | 2 +- src/taglist.c | 4 ++-- src/taglist.h | 4 ++-- src/tmap.nas | 2 +- src/tmap.s | 2 +- src/tmap_asm.s | 2 +- src/tmap_mmx.nas | 2 +- src/tmap_vc.nas | 2 +- src/v_video.c | 2 +- src/v_video.h | 2 +- src/vid_copy.s | 2 +- src/w_wad.c | 2 +- src/w_wad.h | 2 +- src/win32/Srb2win.rc | 2 +- src/y_inter.c | 2 +- src/y_inter.h | 2 +- src/z_zone.c | 2 +- src/z_zone.h | 2 +- 216 files changed, 226 insertions(+), 226 deletions(-) diff --git a/src/am_map.c b/src/am_map.c index 53a7480a5..ef0ebb88c 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/am_map.h b/src/am_map.h index 1c8fa70e4..022a7208b 100644 --- a/src/am_map.h +++ b/src/am_map.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/apng.c b/src/apng.c index 0abbe541d..36b205c60 100644 --- a/src/apng.c +++ b/src/apng.c @@ -1,5 +1,5 @@ /* -Copyright 2019-2020, James R. +Copyright 2019-2021, James R. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/apng.h b/src/apng.h index a8b5c8f24..893b523cb 100644 --- a/src/apng.h +++ b/src/apng.h @@ -1,5 +1,5 @@ /* -Copyright 2019-2020, James R. +Copyright 2019-2021, James R. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/asm_defs.inc b/src/asm_defs.inc index ec286b0bd..9074f20f8 100644 --- a/src/asm_defs.inc +++ b/src/asm_defs.inc @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/b_bot.c b/src/b_bot.c index d3635f32c..5b4124627 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2011-2020 by Sonic Team Junior. +// Copyright (C) 2011-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/b_bot.h b/src/b_bot.h index 2806bd68f..9f55637d1 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/byteptr.h b/src/byteptr.h index 01a6293b4..4c8414fae 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/command.c b/src/command.c index d73cde5c2..95b1fd67d 100644 --- a/src/command.c +++ b/src/command.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/command.h b/src/command.h index d4033e6ef..34fd15963 100644 --- a/src/command.h +++ b/src/command.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/console.c b/src/console.c index 1560220f6..8c3703dd8 100644 --- a/src/console.c +++ b/src/console.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/console.h b/src/console.h index 0296f4f6e..28f40d308 100644 --- a/src/console.h +++ b/src/console.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 911a91355..4176b8a11 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 3d67525da..f3eb52423 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_event.h b/src/d_event.h index 3cce8fad1..1fd2e3824 100644 --- a/src/d_event.h +++ b/src/d_event.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_main.c b/src/d_main.c index 61510d590..2a608cfc8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_main.h b/src/d_main.h index 81de0634d..943da8418 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_net.c b/src/d_net.c index d534b1b08..9e5abe24a 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_net.h b/src/d_net.h index ea6b5d4d9..dbc6d8ba5 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 09f9d4651..97a2921a2 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netcmd.h b/src/d_netcmd.h index ac39626a4..fcdd1d4bb 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netfil.c b/src/d_netfil.c index 50dc2ba60..9618c8073 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_netfil.h b/src/d_netfil.h index 158149477..ddcbcfec3 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_player.h b/src/d_player.h index 2e7afed88..54ab34288 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_think.h b/src/d_think.h index 4bdac4627..c3f91edc4 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 2a5ef0981..374585edf 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_lua.c b/src/deh_lua.c index e6a436421..3af97999c 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_lua.h b/src/deh_lua.h index cd927b9fd..9df4028bd 100644 --- a/src/deh_lua.h +++ b/src/deh_lua.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_soc.c b/src/deh_soc.c index 5b12ea1b0..fc764b411 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_soc.h b/src/deh_soc.h index 2bcb52e70..4064deb3f 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_tables.c b/src/deh_tables.c index dd6d7d69f..23faf0092 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/deh_tables.h b/src/deh_tables.h index d094bcbad..1f265cc99 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/dehacked.c b/src/dehacked.c index c2ea28d27..7d8629567 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/dehacked.h b/src/dehacked.h index 1620314ca..1b200e246 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomdata.h b/src/doomdata.h index b3f7f5c4d..e317fec1b 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomdef.h b/src/doomdef.h index 52abc9597..9dc44d3bb 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomstat.h b/src/doomstat.h index 2d28b81af..843202395 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/doomtype.h b/src/doomtype.h index 950f50856..a094cbb08 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/endian.h b/src/endian.h index 24d8e35cd..e78204e72 100644 --- a/src/endian.h +++ b/src/endian.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_finale.c b/src/f_finale.c index fdcfad279..bfba7cf96 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_finale.h b/src/f_finale.h index b3abf1778..4aa2c3f05 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_wipe.c b/src/f_wipe.c index 6afb8a6a7..7526aeca3 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_demo.c b/src/g_demo.c index 593fd7723..ea71c9bd4 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_demo.h b/src/g_demo.h index df25042c4..73cf27358 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_game.c b/src/g_game.c index 399c4f2bd..9911baab6 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_game.h b/src/g_game.h index 744d6755a..98336ad44 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_input.c b/src/g_input.c index d3c21e774..357081e1d 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_input.h b/src/g_input.h index ce38f6ba9..609141825 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_state.h b/src/g_state.h index e364c5a35..589dc6361 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index b13ad03ea..3a8eef55e 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index 42291a0df..d886dcf2a 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 83a4e2e03..317efd320 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index 7e56a14d0..5aba6a2a9 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ba4923d10..e83aff0d7 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 8cae144ff..d4a586d41 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 2aba62248..37d77b467 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_light.h b/src/hardware/hw_light.h index fed7db47f..244cc921f 100644 --- a/src/hardware/hw_light.h +++ b/src/hardware/hw_light.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 4ad09aa3d..ba6532c38 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 5caf344f7..9c3aa9e58 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 0f4d2c7bc..9249c034c 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index af06a198f..645a3bbae 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1998-2020 by Sonic Team Junior. +// Copyright (C) 1998-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/http-mserv.c b/src/http-mserv.c index 7c7d04495..0b9eb2f92 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. +// Copyright (C) 2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7c4f1acf1..0c073866e 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 63d85f1b8..9b7cee2d3 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_addrinfo.c b/src/i_addrinfo.c index e77774549..79709899e 100644 --- a/src/i_addrinfo.c +++ b/src/i_addrinfo.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2020 by Sonic Team Junior. +// Copyright (C) 2011-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_addrinfo.h b/src/i_addrinfo.h index 7ae006719..397a1969d 100644 --- a/src/i_addrinfo.h +++ b/src/i_addrinfo.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2020 by Sonic Team Junior. +// Copyright (C) 2011-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_joy.h b/src/i_joy.h index 2a2797fc4..0c7c8dd3f 100644 --- a/src/i_joy.h +++ b/src/i_joy.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_net.h b/src/i_net.h index 5d93f191e..dbc82db65 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_sound.h b/src/i_sound.h index d45c0b323..e38a17626 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_system.h b/src/i_system.h index 12f0d751d..b88ea3177 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_tcp.c b/src/i_tcp.c index ab8a69a9f..679553039 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_tcp.h b/src/i_tcp.h index 738b8b4d1..785734415 100644 --- a/src/i_tcp.h +++ b/src/i_tcp.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_threads.h b/src/i_threads.h index ecb9fce67..924d283c4 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. +// Copyright (C) 2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_video.h b/src/i_video.h index ab48881d4..2d07fcf10 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/info.c b/src/info.c index ee836a372..bb1279b6b 100644 --- a/src/info.c +++ b/src/info.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/info.h b/src/info.h index 60e970246..031a08b43 100644 --- a/src/info.h +++ b/src/info.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/keys.h b/src/keys.h index 6cdd7956c..b19259320 100644 --- a/src/keys.h +++ b/src/keys.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_baselib.c b/src/lua_baselib.c index a265465da..a0c99411b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 1949d56bb..9089d19b6 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2016-2020 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2016-2020 by Sonic Team Junior. +// Copyright (C) 2016-2021 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index a8ef6b7c0..414d9692a 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hook.h b/src/lua_hook.h index 0d631aa4e..c22309eaa 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index a3f4a95d2..3715aae04 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hud.h b/src/lua_hud.h index 1e9dca00b..a7b1a4cf5 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 8d451e99c..b0548c321 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 6e86f47b7..af2d99a0c 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_libs.h b/src/lua_libs.h index fbe8d4878..05061f118 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 016141796..9031c99f1 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index b6046ab53..a1dca9e15 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 65adceb15..5d5f0e85b 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0eb54808f..687cee2eb 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index 2a5bcfbf1..cfd6b67d4 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2021 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_script.c b/src/lua_script.c index 9f8432832..aa1db3aeb 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_script.h b/src/lua_script.h index 89ba7b6ee..a9c8762ad 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 7e7480be3..3370f8f72 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_taglib.c b/src/lua_taglib.c index c9f320fe8..55abb09cd 100644 --- a/src/lua_taglib.c +++ b/src/lua_taglib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2021 by James R. +// Copyright (C) 2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index 82baa6469..65bf8c313 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_aatree.c b/src/m_aatree.c index c0bb739f8..b228ed63d 100644 --- a/src/m_aatree.c +++ b/src/m_aatree.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_aatree.h b/src/m_aatree.h index b784eb17a..5a240394f 100644 --- a/src/m_aatree.h +++ b/src/m_aatree.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.c b/src/m_anigif.c index 41f99254e..fe04a5cb4 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. // Copyright (C) 2013 by "Ninji". -// Copyright (C) 2013-2020 by Sonic Team Junior. +// Copyright (C) 2013-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.h b/src/m_anigif.h index abe05dd96..ca7563b1e 100644 --- a/src/m_anigif.h +++ b/src/m_anigif.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2013-2020 by Sonic Team Junior. +// Copyright (C) 2013-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_argv.c b/src/m_argv.c index 7d43d96bc..453d6e45c 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_argv.h b/src/m_argv.h index 92770f4e9..f39db513f 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_bbox.c b/src/m_bbox.c index 02d534164..e0505fd95 100644 --- a/src/m_bbox.c +++ b/src/m_bbox.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_bbox.h b/src/m_bbox.h index 9b63c61b6..c56bd22c0 100644 --- a/src/m_bbox.h +++ b/src/m_bbox.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cheat.c b/src/m_cheat.c index 6e0fb8c5c..c958bb4a4 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cheat.h b/src/m_cheat.h index ac2540408..ee4ba5f55 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cond.c b/src/m_cond.c index 36fcd7cf2..a54238ab2 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cond.h b/src/m_cond.h index 9bb162ff3..690b6fb26 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_dllist.h b/src/m_dllist.h index 680c2cd80..65303b4a3 100644 --- a/src/m_dllist.h +++ b/src/m_dllist.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2005 by James Haley -// Copyright (C) 2005-2020 by Sonic Team Junior. +// Copyright (C) 2005-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.c b/src/m_fixed.c index eb10fd5f8..d40ccd98e 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.h b/src/m_fixed.h index 289ca442a..73adf52f6 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_menu.c b/src/m_menu.c index 13531f1b8..496ce6b4c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_menu.h b/src/m_menu.h index 0465128ef..ba9c326a0 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_misc.c b/src/m_misc.c index 17a398b83..999ee0961 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_misc.h b/src/m_misc.h index c5ef9f9f2..fc5430f01 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.c b/src/m_perfstats.c index b58599b6d..c4b2044b3 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.h b/src/m_perfstats.h index 1ca71957f..8f87146f2 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Sonic Team Junior. +// Copyright (C) 2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_queue.c b/src/m_queue.c index 8603ab202..a337ca4ce 100644 --- a/src/m_queue.c +++ b/src/m_queue.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2020 by Sonic Team Junior. +// Copyright (C) 2003-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_queue.h b/src/m_queue.h index 3e9579e11..cc64b8dd7 100644 --- a/src/m_queue.h +++ b/src/m_queue.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2020 by Sonic Team Junior. +// Copyright (C) 2003-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_random.c b/src/m_random.c index 481fdb72b..6b281fc24 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -3,7 +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) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_random.h b/src/m_random.h index 01190e046..df10b4bb3 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -3,7 +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) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_swap.h b/src/m_swap.h index b44d6de8c..6aa347d97 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.c b/src/mserv.c index dfb417415..f46a3d444 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by James R. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.h b/src/mserv.h index d0d5e49df..ff12fa1f8 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by James R. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_ceilng.c b/src/p_ceilng.c index f12499d5c..ac93e8e2e 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_enemy.c b/src/p_enemy.c index 51f18f596..ca88b7831 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_floor.c b/src/p_floor.c index 7c26065b5..d7e417f5c 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_inter.c b/src/p_inter.c index e9a16a3dd..380040bc8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_lights.c b/src/p_lights.c index d396e92d3..937808ef1 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_local.h b/src/p_local.h index 8568dd4f8..1fcd3050d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_map.c b/src/p_map.c index bf668ba3e..19b999c43 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_maputl.c b/src/p_maputl.c index 90718a41c..efcebe736 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_maputl.h b/src/p_maputl.h index 08b606833..cec344d03 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_mobj.c b/src/p_mobj.c index 49db6daee..690842270 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_mobj.h b/src/p_mobj.h index 5bb7c908e..82cd056a8 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 874edbd50..6431e4624 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 8c2946965..7c814e0bf 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_pspr.h b/src/p_pspr.h index 231262beb..4525ba14c 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_saveg.c b/src/p_saveg.c index 03229e740..ba4d8a32e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_saveg.h b/src/p_saveg.h index be98953eb..ed9297a4d 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_setup.c b/src/p_setup.c index 40dd1a284..5a8248a28 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_setup.h b/src/p_setup.h index 5d13ae7d4..9fa70d516 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_sight.c b/src/p_sight.c index 2e1e49997..e4a37a718 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_slopes.c b/src/p_slopes.c index aa46a8402..05955c5d6 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2020 by Sonic Team Junior. +// Copyright (C) 2015-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_slopes.h b/src/p_slopes.h index 46e8dc1e7..ae040ae56 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2020 by Sonic Team Junior. +// Copyright (C) 2015-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_spec.c b/src/p_spec.c index 226e58d15..0bb12cf58 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_spec.h b/src/p_spec.h index bba7c4a40..3b8abfcf8 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_telept.c b/src/p_telept.c index f6feddf4b..6bac5ad20 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_tick.c b/src/p_tick.c index c0a1c5700..9f00ef8dc 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_tick.h b/src/p_tick.h index 1fb88f3f2..ae481c6a2 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_user.c b/src/p_user.c index 4413cc6cd..29770ccb5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_bsp.c b/src/r_bsp.c index 6f2a90d2d..5acd4e70c 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_bsp.h b/src/r_bsp.h index e2da8ebaf..40d24ffec 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_data.h b/src/r_data.h index aec52b54b..571fdc54f 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_defs.h b/src/r_defs.h index 9c649fbc4..1be3a1b8c 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw16.c b/src/r_draw16.c index 8b1d29e8d..1a2fed773 100644 --- a/src/r_draw16.c +++ b/src/r_draw16.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index a34a20e9a..6bb2880b2 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_local.h b/src/r_local.h index 4ccb766cf..ba78ea87d 100644 --- a/src/r_local.h +++ b/src/r_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_main.c b/src/r_main.c index 04bdebc58..be9bbd7d0 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_main.h b/src/r_main.h index 2ac6abf5a..f81447c45 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.c b/src/r_patch.c index 1a08d1892..ef41aa574 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.h b/src/r_patch.h index 32bcb3909..d4ca8e6ee 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 123c4eef2..a6c2b41ce 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.h b/src/r_patchrotation.h index 2744f71d2..c64a08366 100644 --- a/src/r_patchrotation.h +++ b/src/r_patchrotation.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_picformats.c b/src/r_picformats.c index f87362c76..3bbbf82ec 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2020 by Sonic Team Junior. +// Copyright (C) 2018-2021 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_picformats.h b/src/r_picformats.h index 8d3999013..b1bb35edd 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2020 by Sonic Team Junior. +// Copyright (C) 2018-2021 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_plane.h b/src/r_plane.h index 0d11c5b72..748a7f007 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_portal.c b/src/r_portal.c index 1aca145ec..3026f4e4c 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_portal.h b/src/r_portal.h index e665a26e6..0effd07b5 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_segs.c b/src/r_segs.c index a6772f964..c9f9bbfe6 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_segs.h b/src/r_segs.h index ace5711d4..da7d44ad4 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_skins.c b/src/r_skins.c index 6f150f234..7b6c4517b 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_skins.h b/src/r_skins.h index fbbb38743..3f67bfdab 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_sky.c b/src/r_sky.c index 7cdcfa44d..041cccfc5 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_sky.h b/src/r_sky.h index 55d866b86..f4356dcfa 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_splats.h b/src/r_splats.h index 05d8b66b0..cab3d63b6 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_state.h b/src/r_state.h index 25aa69702..5a606ed8c 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_textures.h b/src/r_textures.h index 74a94a9ed..dd286b6ac 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_things.h b/src/r_things.h index 95b4215af..9315b36e9 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/s_sound.c b/src/s_sound.c index 392a5b453..ea1479cae 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/s_sound.h b/src/s_sound.h index 4ac3c70bf..f736833f9 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/screen.c b/src/screen.c index d37724390..770f1c802 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/screen.h b/src/screen.h index e4944775d..67880e2b9 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index a0dd6e1da..df29e348b 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -5,7 +5,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index 3b1c20b9a..bf9668584 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020 by James R. +// Copyright (C) 2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 0ed10463f..5f18720f8 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -4,7 +4,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 412a21ea0..2f1a87266 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1301,7 +1301,7 @@ boolean I_PlaySong(boolean looping) #if defined (GME_VERSION) && GME_VERSION >= 0x000603 if (looping) gme_set_autoload_playback_limit(gme, 0); -#endif +#endif gme_set_equalizer(gme, &eq); gme_start_track(gme, 0); current_track = 0; diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index 52727c056..c426e6792 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 748e30bae..8f87f688e 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 86e294fb5..058b601c3 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2014-2020 by Sonic Team Junior. +// Copyright (C) 2014-2021 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index e35506114..a9676b5c2 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/src/sounds.c b/src/sounds.c index 092bda21f..4c5b11ee9 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sounds.h b/src/sounds.h index e49dd2f3e..2dd37953c 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/st_stuff.c b/src/st_stuff.c index a1fbbec03..a0457ba53 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/st_stuff.h b/src/st_stuff.h index 4ea307d2b..b1ea2942d 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/strcasestr.c b/src/strcasestr.c index b266278ed..1cbee286a 100644 --- a/src/strcasestr.c +++ b/src/strcasestr.c @@ -2,7 +2,7 @@ strcasestr -- case insensitive substring searching function. */ /* -Copyright 2019-2020 James R. +Copyright 2019-2021 James R. All rights reserved. Redistribution and use in source forms, with or without modification, is diff --git a/src/string.c b/src/string.c index e430c5cc3..f32025612 100644 --- a/src/string.c +++ b/src/string.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tables.c b/src/tables.c index 70a1ecd0a..9263f42d3 100644 --- a/src/tables.c +++ b/src/tables.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tables.h b/src/tables.h index 953d891ce..baa3adf36 100644 --- a/src/tables.h +++ b/src/tables.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/taglist.c b/src/taglist.c index a759f4d02..1b4a64ecd 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by Nev3r. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2021 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/taglist.h b/src/taglist.h index a0529ab6b..80100f80a 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. -// Copyright (C) 2020 by Nev3r. +// Copyright (C) 1999-2021 by Sonic Team Junior. +// Copyright (C) 2021 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap.nas b/src/tmap.nas index 69282d0b4..5bf28359e 100644 --- a/src/tmap.nas +++ b/src/tmap.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2020 by Sonic Team Junior. +;; Copyright (C) 1999-2021 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap.s b/src/tmap.s index 3a4cf2e1a..62dcf85dc 100644 --- a/src/tmap.s +++ b/src/tmap.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap_asm.s b/src/tmap_asm.s index 3cd0f87cc..b5a0a51e9 100644 --- a/src/tmap_asm.s +++ b/src/tmap_asm.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap_mmx.nas b/src/tmap_mmx.nas index 15b97499d..8b6ef91a6 100644 --- a/src/tmap_mmx.nas +++ b/src/tmap_mmx.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DOSDOOM. -;; Copyright (C) 2010-2020 by Sonic Team Junior. +;; Copyright (C) 2010-2021 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap_vc.nas b/src/tmap_vc.nas index 49eb21a6d..b6ee26e6b 100644 --- a/src/tmap_vc.nas +++ b/src/tmap_vc.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2020 by Sonic Team Junior. +;; Copyright (C) 1999-2021 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/v_video.c b/src/v_video.c index 4713db0d8..9cbf6d792 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/v_video.h b/src/v_video.h index 8a18f82ad..7184e799e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/vid_copy.s b/src/vid_copy.s index eae435ea4..6a3788356 100644 --- a/src/vid_copy.s +++ b/src/vid_copy.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/w_wad.c b/src/w_wad.c index 6149aec6e..cbff5c67b 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/w_wad.h b/src/w_wad.h index d0a86bcb4..130967712 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index b0eb2532e..0a280448b 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -97,7 +97,7 @@ BEGIN VALUE "FileDescription", "Sonic Robo Blast 2\0" VALUE "FileVersion", VERSIONSTRING_RC VALUE "InternalName", "srb2\0" - VALUE "LegalCopyright", "Copyright 1998-2020 by Sonic Team Junior\0" + VALUE "LegalCopyright", "Copyright 1998-2021 by Sonic Team Junior\0" VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" VALUE "OriginalFilename", "srb2win.exe\0" VALUE "PrivateBuild", "\0" diff --git a/src/y_inter.c b/src/y_inter.c index 4354a1677..dc78a1983 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2020 by Sonic Team Junior. +// Copyright (C) 2004-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/y_inter.h b/src/y_inter.h index 7268b1a47..871142858 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2020 by Sonic Team Junior. +// Copyright (C) 2004-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/z_zone.c b/src/z_zone.c index d7da17e51..34ff3d37e 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2020 by Sonic Team Junior. +// Copyright (C) 2006-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/z_zone.h b/src/z_zone.h index 7b58be8f3..be55bf994 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2020 by Sonic Team Junior. +// Copyright (C) 1999-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. From 07e69c5eb30d83f229e42db460dd180c3188f9dd Mon Sep 17 00:00:00 2001 From: LJ Sonic Date: Fri, 7 May 2021 18:04:30 +0200 Subject: [PATCH 138/241] Add copyright date ranges for files created in 2020 --- src/hardware/hw_batching.c | 2 +- src/hardware/hw_batching.h | 2 +- src/http-mserv.c | 2 +- src/i_threads.h | 2 +- src/lua_polyobjlib.c | 4 ++-- src/lua_taglib.c | 4 ++-- src/m_perfstats.c | 2 +- src/m_perfstats.h | 2 +- src/mserv.c | 2 +- src/mserv.h | 2 +- src/r_patch.c | 2 +- src/r_patch.h | 2 +- src/r_patchrotation.c | 2 +- src/r_patchrotation.h | 2 +- src/sdl/i_threads.c | 2 +- src/taglist.c | 2 +- src/taglist.h | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index 3a8eef55e..0ac33d136 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index d886dcf2a..9ccc7de3d 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/http-mserv.c b/src/http-mserv.c index 0b9eb2f92..f9134ba50 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_threads.h b/src/i_threads.h index 924d283c4..bc752181f 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index cfd6b67d4..5d76a912d 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/lua_taglib.c b/src/lua_taglib.c index 55abb09cd..d0cf385a9 100644 --- a/src/lua_taglib.c +++ b/src/lua_taglib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by James R. -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by James R. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.c b/src/m_perfstats.c index c4b2044b3..8a99312e6 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.h b/src/m_perfstats.h index 8f87146f2..71208fbc1 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Sonic Team Junior. +// Copyright (C) 2020-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.c b/src/mserv.c index f46a3d444..f64c7bea9 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2021 by Sonic Team Junior. -// Copyright (C) 2021 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/mserv.h b/src/mserv.h index ff12fa1f8..7a3b3d8ec 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2021 by Sonic Team Junior. -// Copyright (C) 2021 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.c b/src/r_patch.c index ef41aa574..6827cd12c 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.h b/src/r_patch.h index d4ca8e6ee..96fbb0e28 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index a6c2b41ce..a9b4a2b8f 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.h b/src/r_patchrotation.h index c64a08366..689b7d411 100644 --- a/src/r_patchrotation.h +++ b/src/r_patchrotation.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2021 by Jaime "Lactozilla" Passos. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index bf9668584..f73d00bcf 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021 by James R. +// Copyright (C) 2020-2021 by James R. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/taglist.c b/src/taglist.c index 1b4a64ecd..28fa48c25 100644 --- a/src/taglist.c +++ b/src/taglist.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2021 by Sonic Team Junior. -// Copyright (C) 2021 by Nev3r. +// Copyright (C) 2020-2021 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/taglist.h b/src/taglist.h index 80100f80a..146d76131 100644 --- a/src/taglist.h +++ b/src/taglist.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2021 by Sonic Team Junior. -// Copyright (C) 2021 by Nev3r. +// Copyright (C) 2020-2021 by Nev3r. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. From 8e8881b534e5844e45a06f9bdbfb3f6728a8f9cd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 7 May 2021 14:14:31 -0400 Subject: [PATCH 139/241] Fix custom title card text not looping properly --- 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 a1fbbec03..5f7307b58 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1367,7 +1367,7 @@ void ST_drawTitleCard(void) zzticker = lt_ticker; V_DrawMappedPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap); V_DrawMappedPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap); - V_DrawMappedPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); + V_DrawMappedPatch(FixedInt(lt_zigzag), (-zztext->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); V_DrawMappedPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); } From 44782654001339da3ec60e3b31772b198cd11d03 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 7 May 2021 14:15:37 -0400 Subject: [PATCH 140/241] Fix title card patches not actually having enough room for an entire lump name --- src/doomstat.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 2d28b81af..ee6756759 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -337,9 +337,9 @@ typedef struct fixed_t gravity; ///< Map-wide gravity. // Title card. - char ltzzpatch[8]; ///< Zig zag patch. - char ltzztext[8]; ///< Zig zag text. - char ltactdiamond[8]; ///< Act diamond. + char ltzzpatch[9]; ///< Zig zag patch. + char ltzztext[9]; ///< Zig zag text. + char ltactdiamond[9]; ///< Act diamond. // Freed animals stuff. UINT8 numFlickies; ///< Internal. For freed flicky support. From c06817d0085ee77b0027917bca91a24e60c7deba Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 7 May 2021 15:30:46 -0700 Subject: [PATCH 141/241] Makefile: fix mingw/64 swapped with 32-bit --- src/Makefile.d/platform.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk index be8d35830..f13488823 100644 --- a/src/Makefile.d/platform.mk +++ b/src/Makefile.d/platform.mk @@ -47,9 +47,9 @@ NOASM=1 # but we make that assumption elsewhere # Once that changes, remove this X86_64=1 -platform=mingw -else platform=mingw/64 +else +platform=mingw endif include Makefile.d/win32.mk endif From 9e7d80c2c44199126fa451c59fca0f98d23ad14d Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 7 May 2021 16:08:24 -0700 Subject: [PATCH 142/241] Makefile: suppress DEL error --- src/Makefile.d/platform.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk index f13488823..531d073e9 100644 --- a/src/Makefile.d/platform.mk +++ b/src/Makefile.d/platform.mk @@ -5,7 +5,7 @@ PKG_CONFIG?=pkg-config ifdef WINDOWSHELL -rmrf=2>NUL DEL /S /Q +rmrf=-2>NUL DEL /S /Q mkdir=-2>NUL MD else rmrf=rm -rf From dc6851dabc376a939673fadac8bacc903e74127e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 6 May 2021 17:41:43 -0400 Subject: [PATCH 143/241] Save skin name instead of skin number into save files Allows you to save a game as any character, and you don't have to load the files in a specific order to access the save file. --- src/g_game.c | 25 +++++++++++- src/m_menu.c | 105 ++++++++++++++++++++++++++++++++++++++------------ src/p_saveg.c | 49 ++++++++++++++++++++--- src/p_saveg.h | 2 + 4 files changed, 150 insertions(+), 31 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 399c4f2bd..08d07dbbb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4619,6 +4619,9 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) UINT8 *end_p = savebuffer + length; UINT8 *lives_p; SINT8 pllives; +#ifdef NEWSKINSAVES + INT16 backwardsCompat = 0; +#endif save_p = savebuffer; // Version check @@ -4637,9 +4640,29 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) // P_UnArchivePlayer() CHECKPOS - (void)READUINT16(save_p); +#ifdef NEWSKINSAVES + backwardsCompat = READUINT16(save_p); CHECKPOS + if (backwardsCompat == NEWSKINSAVES) // New save, read skin names +#endif + { + boolean haveBot = false; + char ourSkinName[SKINNAMESIZE+1]; + + READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); + CHECKPOS + haveBot = (boolean)READUINT8(save_p); + CHECKPOS + + if (haveBot == true) + { + char botSkinName[SKINNAMESIZE+1]; + READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + CHECKPOS + } + } + WRITEUINT8(save_p, numgameovers); CHECKPOS diff --git a/src/m_menu.c b/src/m_menu.c index 40215090c..03487e2fa 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -62,6 +62,8 @@ #include "i_joy.h" // for joystick menu controls +#include "p_saveg.h" // Only for NEWSKINSAVES + // Condition Sets #include "m_cond.h" @@ -8580,7 +8582,7 @@ static void M_LoadSelect(INT32 choice) #define VERSIONSIZE 16 #define BADSAVE { savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; } -#define CHECKPOS if (save_p >= end_p) BADSAVE +#define CHECKPOS if (sav_p >= end_p) BADSAVE // Reads the save file to list lives, level, player, etc. // Tails 05-29-2003 static void M_ReadSavegameInfo(UINT32 slot) @@ -8589,10 +8591,13 @@ static void M_ReadSavegameInfo(UINT32 slot) char savename[255]; UINT8 *savebuffer; UINT8 *end_p; // buffer end point, don't read past here - UINT8 *save_p; + UINT8 *sav_p; INT32 fake; // Dummy variable char temp[sizeof(timeattackfolder)]; char vcheck[VERSIONSIZE]; +#ifdef NEWSKINSAVES + INT16 backwardsCompat = 0; +#endif sprintf(savename, savegamename, slot); @@ -8608,19 +8613,19 @@ static void M_ReadSavegameInfo(UINT32 slot) end_p = savebuffer + length; // skip the description field - save_p = savebuffer; + sav_p = savebuffer; // Version check memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, "version %d", VERSION); - if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE - save_p += VERSIONSIZE; + if (strcmp((const char *)sav_p, (const char *)vcheck)) BADSAVE + sav_p += VERSIONSIZE; // dearchive all the modifications // P_UnArchiveMisc() CHECKPOS - fake = READINT16(save_p); + fake = READINT16(sav_p); if (((fake-1) & 8191) >= NUMMAPS) BADSAVE @@ -8637,54 +8642,104 @@ static void M_ReadSavegameInfo(UINT32 slot) savegameinfo[slot].gamemap = fake; CHECKPOS - savegameinfo[slot].numemeralds = READUINT16(save_p)-357; // emeralds + savegameinfo[slot].numemeralds = READUINT16(sav_p)-357; // emeralds CHECKPOS - READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to + READSTRINGN(sav_p, temp, sizeof(temp)); // mod it belongs to if (strcmp(temp, timeattackfolder)) BADSAVE // P_UnArchivePlayer() +#ifdef NEWSKINSAVES CHECKPOS - fake = READUINT16(save_p); - savegameinfo[slot].skinnum = fake & ((1<<5) - 1); - if (savegameinfo[slot].skinnum >= numskins - || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) - BADSAVE - savegameinfo[slot].botskin = fake >> 5; - if (savegameinfo[slot].botskin-1 >= numskins - || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) - BADSAVE + backwardsCompat = READUINT16(sav_p); + + if (backwardsCompat != NEWSKINSAVES) + { + CONS_Printf("Old behavior for %d\n", slot); + + // Backwards compat + savegameinfo[slot].skinnum = backwardsCompat & ((1<<5) - 1); + + if (savegameinfo[slot].skinnum >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) + BADSAVE + + CONS_Printf("Read skinnum successfully\n"); + + savegameinfo[slot].botskin = backwardsCompat >> 5; + if (savegameinfo[slot].botskin-1 >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) + BADSAVE + + CONS_Printf("Read botskin successfully\n"); + } + else +#endif + { + boolean haveBot = false; + char ourSkinName[SKINNAMESIZE+1]; + + CONS_Printf("New behavior for %d\n", slot); + + CHECKPOS + READSTRINGN(sav_p, ourSkinName, SKINNAMESIZE); + savegameinfo[slot].skinnum = R_SkinAvailable(ourSkinName); + + if (savegameinfo[slot].skinnum >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) + BADSAVE + + CONS_Printf("Read skinnum successfully\n"); + + CHECKPOS + haveBot = (boolean)READUINT8(sav_p); + + if (haveBot == true) + { + char botSkinName[SKINNAMESIZE+1]; + + CHECKPOS + READSTRINGN(sav_p, botSkinName, SKINNAMESIZE); + savegameinfo[slot].botskin = (R_SkinAvailable(botSkinName) + 1); + + if (savegameinfo[slot].botskin-1 >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) + BADSAVE + } + + CONS_Printf("Read botskin successfully\n"); + } CHECKPOS - savegameinfo[slot].numgameovers = READUINT8(save_p); // numgameovers + savegameinfo[slot].numgameovers = READUINT8(sav_p); // numgameovers CHECKPOS - savegameinfo[slot].lives = READSINT8(save_p); // lives + savegameinfo[slot].lives = READSINT8(sav_p); // lives CHECKPOS - savegameinfo[slot].continuescore = READINT32(save_p); // score + savegameinfo[slot].continuescore = READINT32(sav_p); // score CHECKPOS - fake = READINT32(save_p); // continues + fake = READINT32(sav_p); // continues if (useContinues) savegameinfo[slot].continuescore = fake; // File end marker check CHECKPOS - switch (READUINT8(save_p)) + switch (READUINT8(sav_p)) { case 0xb7: { UINT8 i, banksinuse; CHECKPOS - banksinuse = READUINT8(save_p); + banksinuse = READUINT8(sav_p); CHECKPOS if (banksinuse > NUM_LUABANKS) BADSAVE for (i = 0; i < banksinuse; i++) { - (void)READINT32(save_p); + (void)READINT32(sav_p); CHECKPOS } - if (READUINT8(save_p) != 0x1d) + if (READUINT8(sav_p) != 0x1d) BADSAVE } case 0x1d: diff --git a/src/p_saveg.c b/src/p_saveg.c index 818596cac..cd9235e05 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -64,12 +64,26 @@ typedef enum static inline void P_ArchivePlayer(void) { const player_t *player = &players[consoleplayer]; - INT16 skininfo = player->skin + (botskin<<5); SINT8 pllives = player->lives; if (pllives < startinglivesbalance[numgameovers]) // Bump up to 3 lives if the player pllives = startinglivesbalance[numgameovers]; // has less than that. - WRITEUINT16(save_p, skininfo); +#ifdef NEWSKINSAVES + WRITEUINT16(save_p, NEWSKINSAVES); +#endif + + WRITESTRINGN(save_p, skins[player->skin].name, SKINNAMESIZE); + + if (botskin != 0) + { + WRITEUINT8(save_p, 1); + WRITESTRINGN(save_p, skins[botskin-1].name, SKINNAMESIZE); + } + else + { + WRITEUINT8(save_p, 0); + } + WRITEUINT8(save_p, numgameovers); WRITESINT8(save_p, pllives); WRITEUINT32(save_p, player->score); @@ -78,9 +92,34 @@ static inline void P_ArchivePlayer(void) static inline void P_UnArchivePlayer(void) { - INT16 skininfo = READUINT16(save_p); - savedata.skin = skininfo & ((1<<5) - 1); - savedata.botskin = skininfo >> 5; +#ifdef NEWSKINSAVES + INT16 backwardsCompat = READUINT16(save_p); + + if (backwardsCompat != NEWSKINSAVES) + { + // Backwards compat + savedata.skin = backwardsCompat & ((1<<5) - 1); + savedata.botskin = backwardsCompat >> 5; + } + else +#endif + { + boolean haveBot = false; + char ourSkinName[SKINNAMESIZE+1]; + + READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); + savedata.skin = R_SkinAvailable(ourSkinName); + + haveBot = (boolean)READUINT8(save_p); + + if (haveBot == true) + { + char botSkinName[SKINNAMESIZE+1]; + + READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + savedata.botskin = R_SkinAvailable(botSkinName) + 1; + } + } savedata.numgameovers = READUINT8(save_p); savedata.lives = READSINT8(save_p); diff --git a/src/p_saveg.h b/src/p_saveg.h index be98953eb..1649d32d7 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -18,6 +18,8 @@ #pragma interface #endif +#define NEWSKINSAVES (INT16_MAX) // Purely for backwards compatibility, remove this for 2.3 + // Persistent storage/archiving. // These are the load / save game routines. From a5830270062f6a2e34c041eed2ba096546dafc33 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 7 May 2021 19:52:29 -0400 Subject: [PATCH 144/241] Remove prints --- src/m_menu.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 03487e2fa..b72ba0be4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8656,8 +8656,6 @@ static void M_ReadSavegameInfo(UINT32 slot) if (backwardsCompat != NEWSKINSAVES) { - CONS_Printf("Old behavior for %d\n", slot); - // Backwards compat savegameinfo[slot].skinnum = backwardsCompat & ((1<<5) - 1); @@ -8665,14 +8663,10 @@ static void M_ReadSavegameInfo(UINT32 slot) || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) BADSAVE - CONS_Printf("Read skinnum successfully\n"); - savegameinfo[slot].botskin = backwardsCompat >> 5; if (savegameinfo[slot].botskin-1 >= numskins || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) BADSAVE - - CONS_Printf("Read botskin successfully\n"); } else #endif @@ -8680,8 +8674,6 @@ static void M_ReadSavegameInfo(UINT32 slot) boolean haveBot = false; char ourSkinName[SKINNAMESIZE+1]; - CONS_Printf("New behavior for %d\n", slot); - CHECKPOS READSTRINGN(sav_p, ourSkinName, SKINNAMESIZE); savegameinfo[slot].skinnum = R_SkinAvailable(ourSkinName); @@ -8690,8 +8682,6 @@ static void M_ReadSavegameInfo(UINT32 slot) || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) BADSAVE - CONS_Printf("Read skinnum successfully\n"); - CHECKPOS haveBot = (boolean)READUINT8(sav_p); @@ -8707,8 +8697,6 @@ static void M_ReadSavegameInfo(UINT32 slot) || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) BADSAVE } - - CONS_Printf("Read botskin successfully\n"); } CHECKPOS From d136c60a3fa9f73a7ae0f26d0552f67b4d5f0d8e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 7 May 2021 20:13:16 -0400 Subject: [PATCH 145/241] Add some comments, write an empty string instead of a boolean determining if the bot skin exists or not. I was a little scared of doing this at first, but after a bit of thought & some testing that it'll be fine. --- src/g_game.c | 12 +++--------- src/m_menu.c | 20 ++++++-------------- src/p_saveg.c | 22 +++++++++------------- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 08d07dbbb..ad60fe47a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4647,20 +4647,14 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) if (backwardsCompat == NEWSKINSAVES) // New save, read skin names #endif { - boolean haveBot = false; char ourSkinName[SKINNAMESIZE+1]; + char botSkinName[SKINNAMESIZE+1]; READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); CHECKPOS - haveBot = (boolean)READUINT8(save_p); - CHECKPOS - if (haveBot == true) - { - char botSkinName[SKINNAMESIZE+1]; - READSTRINGN(save_p, botSkinName, SKINNAMESIZE); - CHECKPOS - } + READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + CHECKPOS } WRITEUINT8(save_p, numgameovers); diff --git a/src/m_menu.c b/src/m_menu.c index b72ba0be4..2cbbe400f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8671,8 +8671,8 @@ static void M_ReadSavegameInfo(UINT32 slot) else #endif { - boolean haveBot = false; char ourSkinName[SKINNAMESIZE+1]; + char botSkinName[SKINNAMESIZE+1]; CHECKPOS READSTRINGN(sav_p, ourSkinName, SKINNAMESIZE); @@ -8683,20 +8683,12 @@ static void M_ReadSavegameInfo(UINT32 slot) BADSAVE CHECKPOS - haveBot = (boolean)READUINT8(sav_p); + READSTRINGN(sav_p, botSkinName, SKINNAMESIZE); + savegameinfo[slot].botskin = (R_SkinAvailable(botSkinName) + 1); - if (haveBot == true) - { - char botSkinName[SKINNAMESIZE+1]; - - CHECKPOS - READSTRINGN(sav_p, botSkinName, SKINNAMESIZE); - savegameinfo[slot].botskin = (R_SkinAvailable(botSkinName) + 1); - - if (savegameinfo[slot].botskin-1 >= numskins - || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) - BADSAVE - } + if (savegameinfo[slot].botskin-1 >= numskins + || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) + BADSAVE } CHECKPOS diff --git a/src/p_saveg.c b/src/p_saveg.c index cd9235e05..abfd4b905 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -69,19 +69,22 @@ static inline void P_ArchivePlayer(void) pllives = startinglivesbalance[numgameovers]; // has less than that. #ifdef NEWSKINSAVES + // Write a specific value into the old skininfo location. + // If we read something other than this, it's an older save file that used skin numbers. WRITEUINT16(save_p, NEWSKINSAVES); #endif + // Write skin names, so that loading skins in different orders + // doesn't change who the save file is for! WRITESTRINGN(save_p, skins[player->skin].name, SKINNAMESIZE); if (botskin != 0) { - WRITEUINT8(save_p, 1); WRITESTRINGN(save_p, skins[botskin-1].name, SKINNAMESIZE); } else { - WRITEUINT8(save_p, 0); + WRITESTRINGN(save_p, "\0", SKINNAMESIZE); } WRITEUINT8(save_p, numgameovers); @@ -97,28 +100,21 @@ static inline void P_UnArchivePlayer(void) if (backwardsCompat != NEWSKINSAVES) { - // Backwards compat + // This is an older save file, which used direct skin numbers. savedata.skin = backwardsCompat & ((1<<5) - 1); savedata.botskin = backwardsCompat >> 5; } else #endif { - boolean haveBot = false; char ourSkinName[SKINNAMESIZE+1]; + char botSkinName[SKINNAMESIZE+1]; READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); savedata.skin = R_SkinAvailable(ourSkinName); - haveBot = (boolean)READUINT8(save_p); - - if (haveBot == true) - { - char botSkinName[SKINNAMESIZE+1]; - - READSTRINGN(save_p, botSkinName, SKINNAMESIZE); - savedata.botskin = R_SkinAvailable(botSkinName) + 1; - } + READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + savedata.botskin = R_SkinAvailable(botSkinName) + 1; } savedata.numgameovers = READUINT8(save_p); From 87afa7655a71539c7cbc7db12df18c4253187fbc Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 7 May 2021 18:57:46 -0700 Subject: [PATCH 146/241] CMake: fix ASM compile - target_sources from correct directory - enable_language must be used in add_executable directory --- CMakeLists.txt | 2 -- src/CMakeLists.txt | 6 ++++++ src/sdl/CMakeLists.txt | 2 -- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc764fc87..6f901d3d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,8 +117,6 @@ set(SRB2_SDL2_EXE_NAME srb2 CACHE STRING "Executable binary output name") include_directories(${CMAKE_CURRENT_BINARY_DIR}/src) -add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32) - add_subdirectory(src) add_subdirectory(assets) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0148d605f..3b690a20a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,7 @@ # SRB2 Core +add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32) + # Core sources target_sourcefile(c) target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h) @@ -206,9 +208,13 @@ if(${SRB2_CONFIG_USEASM}) set(CMAKE_ASM_NASM_FLAGS "${SRB2_ASM_FLAGS}" CACHE STRING "Flags used by the assembler during all build types.") enable_language(ASM_NASM) endif() + set(SRB2_USEASM ON) target_compile_definitions(SRB2SDL2 PRIVATE -DUSEASM) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse") + + target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES} + ${SRB2_NASM_SOURCES}) else() set(SRB2_USEASM OFF) target_compile_definitions(SRB2SDL2 PRIVATE -DNONX86 -DNORUSEASM) diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index a1d55ad4d..4f19d93df 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -56,8 +56,6 @@ endif() if(${SDL2_FOUND}) if(${SRB2_USEASM}) - target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES} - ${SRB2_NASM_SOURCES}) set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES LANGUAGE C) set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") endif() From 3880263f1fb9e206f94a5b170a6c3775efbe5313 Mon Sep 17 00:00:00 2001 From: lachablock Date: Sat, 8 May 2021 12:27:29 +1000 Subject: [PATCH 147/241] Add machine dashmode as a condition for gap passage. (Also remove the sprite2 check, we don't need to be that stingy since PlayerHeight hooks allow greater control over that now!) --- src/p_user.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_user.c b/src/p_user.c index 4dbbcc04f..dc7209763 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -12972,6 +12972,8 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player) return ((player->pflags & (PF_SPINNING|PF_GLIDING)) // players who are spinning or gliding || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) // players who are landing from a glide + || ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE) + && player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH) // machine players in dashmode || JUMPCURLED(player)); // players who are jumpcurled, but only if they would normally jump that way } From d2db204058a6f7dac39a68704c93a11e63a1d0de Mon Sep 17 00:00:00 2001 From: lachablock Date: Sat, 8 May 2021 18:34:32 +1000 Subject: [PATCH 148/241] Fix rollout rock controls in 2D mode --- src/p_user.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index b3bfb763c..57cb056fd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -12727,7 +12727,10 @@ void P_PlayerAfterThink(player_t *player) if (player->cmd.forwardmove || player->cmd.sidemove) { rock->flags2 |= MF2_STRONGBOX; // signifies the rock should not slow to a halt - rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); + if (twodlevel || (mo->flags2 & MF2_TWOD)) + rock->movedir = mo->angle; + else + rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); P_Thrust(rock, rock->movedir, rock->scale >> 1); } else From ec8e884a310fe7978bba4d720ce1259d918a5c8b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 8 May 2021 12:56:33 -0400 Subject: [PATCH 149/241] Removed this function --- src/r_skins.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/r_skins.h b/src/r_skins.h index 675eac5cc..70e9b49c0 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -90,7 +90,6 @@ extern skin_t skins[MAXSKINS]; void R_InitSkins(void); INT32 GetPlayerDefaultSkin(INT32 playernum); -void SetPlayerDefaultSkin(INT32 playernum); void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 boolean R_SkinUsable(INT32 playernum, INT32 skinnum); From 210c9419e4bddd1fe8e9be7cb66de31119fa0d68 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 8 May 2021 16:48:40 -0700 Subject: [PATCH 150/241] Ignore -Wtrigraphs --- src/CMakeLists.txt | 2 ++ src/Makefile.cfg | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 87a0499b6..88ab1cdcb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -604,6 +604,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -Wno-absolute-value) endif() +set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -Wno-trigraphs) + add_definitions(-DCMAKECONFIG) #add_library(SRB2Core STATIC diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 075cd2d3a..79d332f85 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -209,7 +209,7 @@ endif OLDWFLAGS:=$(WFLAGS) # -W -Wno-unused -WFLAGS=-Wall +WFLAGS=-Wall -Wno-trigraphs ifndef GCC295 #WFLAGS+=-Wno-packed endif From 35244fa736cd2b5d1a35b471ef75cfaaba6a3a2a Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 8 May 2021 16:49:23 -0700 Subject: [PATCH 151/241] Clang: fix -Wimplicit-const-int-float-conversion Some of these integers exceed the precision of float. In that case the number is rounded. The rounding shouldn't matter too much anyway, so just shut the compiler up. --- src/hardware/hw_main.c | 2 +- src/m_random.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e94c637e4..dd633d6fc 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5715,7 +5715,7 @@ static void HWR_DrawSkyBackground(player_t *player) dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); - v[0].s = v[3].s = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[0].s = v[3].s = (-1.0f * angle) / (((float)ANGLE_90-1.0f)*dimensionmultiply); // left v[2].s = v[1].s = v[0].s + (1.0f/dimensionmultiply); // right (or left + 1.0f) // use +angle and -1.0f above instead if you wanted old backwards behavior diff --git a/src/m_random.c b/src/m_random.c index 481fdb72b..b00eff60f 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -60,7 +60,7 @@ UINT8 M_RandomByte(void) */ INT32 M_RandomKey(INT32 a) { - return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*a); + return (INT32)((rand()/((float)RAND_MAX+1.0f))*a); } /** Provides a random integer in a given range. @@ -73,7 +73,7 @@ INT32 M_RandomKey(INT32 a) */ INT32 M_RandomRange(INT32 a, INT32 b) { - return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*(b-a+1))+a; + return (INT32)((rand()/((float)RAND_MAX+1.0f))*(b-a+1))+a; } From 69647eb78d36c0b2f5febecd2c4e55f622325217 Mon Sep 17 00:00:00 2001 From: RJPFonseca Date: Sun, 9 May 2021 19:10:53 +0100 Subject: [PATCH 152/241] Used spaces instead of tabs in Makefile.cfg --- src/Makefile.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 075cd2d3a..e6821a4c9 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -61,10 +61,10 @@ ifeq (,$(filter GCC% CLEANONLY,$(.VARIABLES))) # If this version is not in the list, default to the latest supported ifeq (,$(filter $(v),$(SUPPORTED_GCC_VERSIONS))) - define line = + define line = Your compiler version, GCC $(version), is not supported by the Makefile. The Makefile will assume GCC $(LATEST_GCC_VERSION).)) - endef + endef $(call print,$(line)) GCC$(subst .,,$(LATEST_GCC_VERSION))=1 else From 0edbca5e02dfc0ffa23696e4c1d86cd12f8e516b Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 10 May 2021 16:51:18 -0700 Subject: [PATCH 153/241] Actually report server version mismatches Incompatible servers get dropped from the server list. It turns out the server list is also used when connecting directly to a server. This meant that if you tried connecting to a server that was incompatible, you'd just get an infinite connection screen, as if the server was completely unreachable. Now it won't drop the server if you are directly connecting to it. I also copied some incompatibility messages from HandleConnect. --- src/d_clisrv.c | 113 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 25 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7fa6d8d59..8b80e58f5 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1667,20 +1667,24 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) if (serverlistcount >= MAXSERVERLIST) return; // list full - if (info->_255 != 255) - return;/* old packet format */ + /* check it later if connecting to this one */ + if (node != servernode) + { + if (info->_255 != 255) + return;/* old packet format */ - if (info->packetversion != PACKETVERSION) - return;/* old new packet format */ + if (info->packetversion != PACKETVERSION) + return;/* old new packet format */ - if (info->version != VERSION) - return; // Not same version. + if (info->version != VERSION) + return; // Not same version. - if (info->subversion != SUBVERSION) - return; // Close, but no cigar. + if (info->subversion != SUBVERSION) + return; // Close, but no cigar. - if (strcmp(info->application, SRB2APPLICATION)) - return;/* that's a different mod */ + if (strcmp(info->application, SRB2APPLICATION)) + return;/* that's a different mod */ + } i = serverlistcount++; } @@ -1829,6 +1833,65 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif // ifndef NONET +static const char * InvalidServerReason (INT32 i) +{ +#define EOT "\nPress ESC\n" + + serverinfo_pak *info = &serverlist[i].info; + + /* magic number for new packet format */ + if (info->_255 != 255) + { + return + "Outdated server (version unknown).\n" EOT; + } + + if (strncmp(info->application, SRB2APPLICATION, sizeof + info->application)) + { + return va( + "%s cannot connect\n" + "to %s servers.\n" EOT, + SRB2APPLICATION, + info->application); + } + + if ( + info->packetversion != PACKETVERSION || + info->version != VERSION || + info->subversion != SUBVERSION + ){ + return va( + "Incompatible %s versions.\n" + "(server version %d.%d.%d)\n" EOT, + SRB2APPLICATION, + info->version / 100, + info->version % 100, + info->subversion); + } + + if (info->refusereason) + { + if (serverlist[i].info.refusereason == 1) + return + "The server is not accepting\n" + "joins for the moment.\n" EOT; + else if (serverlist[i].info.refusereason == 2) + return va( + "Maximum players reached: %d\n" EOT, + info->maxplayer); + else + return + "You can't join.\n" + "I don't know why,\n" + "but you can't join.\n" EOT; + } + + return NULL; + +#undef EOT +} + /** Called by CL_ServerConnectionTicker * * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit. @@ -1859,23 +1922,23 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent) return true; } - // Quit here rather than downloading files and being refused later. - if (serverlist[i].info.refusereason) - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - if (serverlist[i].info.refusereason == 1) - M_StartMessage(M_GetText("The server is not accepting\njoins for the moment.\n\nPress ESC\n"), NULL, MM_NOTHING); - else if (serverlist[i].info.refusereason == 2) - M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING); - else - M_StartMessage(M_GetText("You can't join.\nI don't know why,\nbut you can't join.\n\nPress ESC\n"), NULL, MM_NOTHING); - return false; - } - if (client) { + const char *reason = InvalidServerReason(i); + + // Quit here rather than downloading files + // and being refused later. + if (reason) + { + char *message = Z_StrDup(reason); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(message, NULL, MM_NOTHING); + Z_Free(message); + return false; + } + D_ParseFileneeded(serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded); CONS_Printf(M_GetText("Checking files...\n")); From 22bfc2db78e2c0afbe839681310a7470b17a9325 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 10 May 2021 17:50:01 -0700 Subject: [PATCH 154/241] Refactor HandleConnect refusals Also removed some version fields from serverconfig_pak and clientconfig_pak. Client version will be checked with SRB2APPLICATION and MODVERSION. Not updating PACKETVERSION because those packets shouldn't have been packetversion'd in the first place. --- src/d_clisrv.c | 115 +++++++++++++++++++++++++++++++++++-------------- src/d_clisrv.h | 8 +--- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 8b80e58f5..27e104596 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1150,15 +1150,14 @@ static boolean CL_SendJoin(void) CONS_Printf(M_GetText("Sending join request...\n")); netbuffer->packettype = PT_CLIENTJOIN; + netbuffer->u.clientcfg.modversion = MODVERSION; + strncpy(netbuffer->u.clientcfg.application, + SRB2APPLICATION, + sizeof netbuffer->u.clientcfg.application); + if (splitscreen || botingame) localplayers++; netbuffer->u.clientcfg.localplayers = localplayers; - netbuffer->u.clientcfg._255 = 255; - netbuffer->u.clientcfg.packetversion = PACKETVERSION; - netbuffer->u.clientcfg.version = VERSION; - netbuffer->u.clientcfg.subversion = SUBVERSION; - strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, - sizeof netbuffer->u.clientcfg.application); CleanupPlayerName(consoleplayer, cv_playername.zstring); if (splitscreen) @@ -1344,9 +1343,6 @@ static boolean SV_SendServerConfig(INT32 node) netbuffer->packettype = PT_SERVERCFG; - netbuffer->u.servercfg.version = VERSION; - netbuffer->u.servercfg.subversion = SUBVERSION; - netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer; netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots); netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic); @@ -3683,6 +3679,78 @@ static size_t TotalTextCmdPerTic(tic_t tic) return total; } +static const char * +ConnectionRefused (SINT8 node, INT32 rejoinernum) +{ + clientconfig_pak *cc = &netbuffer->u.clientcfg; + + boolean rejoining = (rejoinernum != -1); + + if (!node)/* server connecting to itself */ + return NULL; + + if ( + cc->modversion != MODVERSION || + strncmp(cc->application, SRB2APPLICATION, + sizeof cc->application) + ){ + return/* this is probably client's fault */ + "Incompatible."; + } + else if (bannednode && bannednode[node]) + { + return + "You have been banned\n" + "from the server."; + } + else if (cc->localplayers != 1) + { + return + "Wrong player count."; + } + + if (!rejoining) + { + if (!cv_allownewplayer.value) + { + return + "The server is not accepting\n" + "joins for the moment."; + } + else if (D_NumPlayers() >= cv_maxplayers.value) + { + return va( + "Maximum players reached: %d", + cv_maxplayers.value); + } + } + + if (luafiletransfers) + { + return + "The serveris broadcasting a file\n" + "requested by a Lua script.\n" + "Please wait a bit and then\n" + "try rejoining."; + } + + if (netgame) + { + const tic_t th = 2 * cv_joindelay.value * TICRATE; + + if (joindelay > th) + { + return va( + "Too many people are connecting.\n" + "Please wait %d seconds and then\n" + "try rejoining.", + (joindelay - th) / TICRATE); + } + } + + return NULL; +} + /** Called when a PT_CLIENTJOIN packet is received * * \param node The packet sender @@ -3693,33 +3761,14 @@ static void HandleConnect(SINT8 node) char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; INT32 rejoinernum; INT32 i; + const char *refuse; rejoinernum = FindRejoinerNum(node); - if (bannednode && bannednode[node]) - SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server.")); - else if (netbuffer->u.clientcfg._255 != 255 || - netbuffer->u.clientcfg.packetversion != PACKETVERSION) - SV_SendRefuse(node, "Incompatible packet formats."); - else if (strncmp(netbuffer->u.clientcfg.application, SRB2APPLICATION, - sizeof netbuffer->u.clientcfg.application)) - SV_SendRefuse(node, "Different SRB2 modifications\nare not compatible."); - else if (netbuffer->u.clientcfg.version != VERSION - || netbuffer->u.clientcfg.subversion != SUBVERSION) - SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION)); - else if (!cv_allownewplayer.value && node && rejoinernum == -1) - SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment.")); - else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1) - SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value)); - else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client? - SV_SendRefuse(node, M_GetText("Too many players from\nthis node.")); - else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join? - SV_SendRefuse(node, M_GetText("No players from\nthis node.")); - else if (luafiletransfers) - SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining.")); - else if (netgame && joindelay > 2 * (tic_t)cv_joindelay.value * TICRATE) - SV_SendRefuse(node, va(M_GetText("Too many people are connecting.\nPlease wait %d seconds and then\ntry rejoining."), - (joindelay - 2 * cv_joindelay.value * TICRATE) / TICRATE)); + refuse = ConnectionRefused(node, rejoinernum); + + if (refuse) + SV_SendRefuse(node, refuse); else { #ifndef NONET diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 3d67525da..9b690da84 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -141,9 +141,6 @@ typedef struct typedef struct { - UINT8 version; // Different versions don't work - UINT8 subversion; // Contains build version - // Server launch stuffs UINT8 serverplayer; UINT8 totalslotnum; // "Slots": highest player number in use plus one. @@ -190,11 +187,8 @@ typedef struct typedef struct { - UINT8 _255;/* see serverinfo_pak */ - UINT8 packetversion; + UINT8 modversion; char application[MAXAPPLICATION]; - UINT8 version; // Different versions don't work - UINT8 subversion; // Contains build version UINT8 localplayers; UINT8 mode; char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; From 8486a9386d84293375465420fa80cfeed9859cd1 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 10 May 2021 18:10:16 -0700 Subject: [PATCH 155/241] serverinfo: enumerate refusereason --- src/d_clisrv.c | 41 +++++++++++++++++++++++++---------------- src/d_clisrv.h | 7 ++++++- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 27e104596..a06a935a7 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1200,6 +1200,19 @@ static INT32 FindRejoinerNum(SINT8 node) return -1; } +static UINT8 +GetRefuseReason (INT32 node) +{ + if (!node || FindRejoinerNum(node) != -1) + return 0; + else if (!cv_allownewplayer.value) + return REFUSE_JOINS_DISABLED; + else if (D_NumPlayers() >= cv_maxplayers.value) + return REFUSE_SLOTS_FULL; + else + return 0; +} + static void SV_SendServerInfo(INT32 node, tic_t servertime) { UINT8 *p; @@ -1218,14 +1231,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers(); netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value; - if (!node || FindRejoinerNum(node) != -1) - netbuffer->u.serverinfo.refusereason = 0; - else if (!cv_allownewplayer.value) - netbuffer->u.serverinfo.refusereason = 1; - else if (D_NumPlayers() >= cv_maxplayers.value) - netbuffer->u.serverinfo.refusereason = 2; - else - netbuffer->u.serverinfo.refusereason = 0; + netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], sizeof netbuffer->u.serverinfo.gametypename); @@ -1866,21 +1872,24 @@ static const char * InvalidServerReason (INT32 i) info->subversion); } - if (info->refusereason) + switch (info->refusereason) { - if (serverlist[i].info.refusereason == 1) + case REFUSE_JOINS_DISABLED: return "The server is not accepting\n" "joins for the moment.\n" EOT; - else if (serverlist[i].info.refusereason == 2) + case REFUSE_SLOTS_FULL: return va( "Maximum players reached: %d\n" EOT, info->maxplayer); - else - return - "You can't join.\n" - "I don't know why,\n" - "but you can't join.\n" EOT; + default: + if (info->refusereason) + { + return + "You can't join.\n" + "I don't know why,\n" + "but you can't join.\n" EOT; + } } return NULL; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 9b690da84..0e8e4c2b8 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -194,6 +194,11 @@ typedef struct char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; } ATTRPACK clientconfig_pak; +enum { + REFUSE_JOINS_DISABLED = 1, + REFUSE_SLOTS_FULL, +}; + #define MAXSERVERNAME 32 #define MAXFILENEEDED 915 // This packet is too large @@ -211,7 +216,7 @@ typedef struct UINT8 subversion; UINT8 numberofplayer; UINT8 maxplayer; - UINT8 refusereason; // 0: joinable, 1: joins disabled, 2: full + UINT8 refusereason; // 0: joinable, REFUSE enum char gametypename[24]; UINT8 modifiedgame; UINT8 cheatsenabled; From c13e1a74ddb5fba981d801d1137c11537d4505f7 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 10 May 2021 18:10:53 -0700 Subject: [PATCH 156/241] Reject banned players with refusereason --- src/d_clisrv.c | 6 ++++++ src/d_clisrv.h | 13 +++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index a06a935a7..e87edf43d 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1205,6 +1205,8 @@ GetRefuseReason (INT32 node) { if (!node || FindRejoinerNum(node) != -1) return 0; + else if (bannednode && bannednode[node]) + return REFUSE_BANNED; else if (!cv_allownewplayer.value) return REFUSE_JOINS_DISABLED; else if (D_NumPlayers() >= cv_maxplayers.value) @@ -1874,6 +1876,10 @@ static const char * InvalidServerReason (INT32 i) switch (info->refusereason) { + case REFUSE_BANNED: + return + "You have been banned\n" + "from the server.\n" EOT; case REFUSE_JOINS_DISABLED: return "The server is not accepting\n" diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 0e8e4c2b8..99274b5de 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -22,11 +22,15 @@ #include "mserv.h" /* -The 'packet version' is used to distinguish packet formats. -This version is independent of VERSION and SUBVERSION. Different -applications may follow different packet versions. +The 'packet version' is used to distinguish packet +formats. This version is independent of VERSION and +SUBVERSION. Different applications may follow different +packet versions. + +If you change the struct or the meaning of a field +therein, increment this number. */ -#define PACKETVERSION 3 +#define PACKETVERSION 4 // Network play related stuff. // There is a data struct that stores network @@ -197,6 +201,7 @@ typedef struct enum { REFUSE_JOINS_DISABLED = 1, REFUSE_SLOTS_FULL, + REFUSE_BANNED, }; #define MAXSERVERNAME 32 From f55a5b3b0b964ccf77279bab9136ee7ce883a2e1 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 11 May 2021 20:02:12 -0400 Subject: [PATCH 157/241] Add badge to readme showing latest stable release --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8a5ca1a1f..49a3cc36d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Sonic Robo Blast 2 +[![latest release](https://badgen.net/github/release/STJr/SRB2/stable)](https://github.com/STJr/SRB2/releases/latest) [![Build status](https://ci.appveyor.com/api/projects/status/399d4hcw9yy7hg2y?svg=true)](https://ci.appveyor.com/project/STJr/srb2) [![Build status](https://travis-ci.org/STJr/SRB2.svg?branch=master)](https://travis-ci.org/STJr/SRB2) From 5b86b8991c7408ba7ebb78d0d6ff4438d447936e Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Sun, 16 May 2021 21:43:52 -0300 Subject: [PATCH 158/241] Use floating point trigonometry --- src/r_plane.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index d26c124ef..4c757d8ca 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -368,11 +368,11 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, if (plangle != 0) { // Add the view offset, rotated by the plane angle. - fixed_t cosinecomponent = FINECOSINE(plangle>>ANGLETOFINESHIFT); - fixed_t sinecomponent = FINESINE(plangle>>ANGLETOFINESHIFT); - fixed_t oldxoff = xoff; - xoff = FixedMul(xoff,cosinecomponent)+FixedMul(yoff,sinecomponent); - yoff = -FixedMul(oldxoff,sinecomponent)+FixedMul(yoff,cosinecomponent); + float ang = ANG2RAD(plangle); + float x = FixedToFloat(xoff); + float y = FixedToFloat(yoff); + xoff = FloatToFixed(x * cos(ang) + y * sin(ang)); + yoff = FloatToFixed(-x * sin(ang) + y * cos(ang)); } } From 4e5c3566c95cd9526d42629837f779c041fe0a92 Mon Sep 17 00:00:00 2001 From: lachablock Date: Sat, 22 May 2021 16:52:01 +1000 Subject: [PATCH 159/241] Respect mobj->color while enemies & bosses flash --- src/r_draw.c | 4 ++++ src/r_things.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/r_draw.c b/src/r_draw.c index 9a835ee58..c7bf36e64 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -481,8 +481,12 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U // White! if (skinnum == TC_BOSS) { + UINT8 *originalColormap = R_GetTranslationColormap(TC_DEFAULT, (skincolornum_t)color, GTC_CACHE); for (i = 0; i < 16; i++) + { + dest_colormap[DEFAULT_STARTTRANSCOLOR + i] = originalColormap[DEFAULT_STARTTRANSCOLOR + i]; dest_colormap[31-i] = i; + } } else if (skinnum == TC_METALSONIC) { diff --git a/src/r_things.c b/src/r_things.c index 5c0e5fda9..bbae345db 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -753,7 +753,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) else if (vis->mobj->type == MT_METALSONIC_BATTLE) return R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); else - return R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + return R_GetTranslationColormap(TC_BOSS, vis->mobj->color, GTC_CACHE); } else if (vis->mobj->color) { From 99ad18826332cb95798d17b658ccb4fa9c83b3f6 Mon Sep 17 00:00:00 2001 From: lachablock Date: Sat, 22 May 2021 18:17:48 +1000 Subject: [PATCH 160/241] Fix models interpolating to frame 0 from a same-sprite2 FF_SPR2ENDSTATE state --- src/hardware/hw_md2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 9c3aa9e58..e3b612678 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1533,7 +1533,12 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) { nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; if (nextFrame >= mod) - nextFrame = 0; + { + if (spr->mobj->state->frame & FF_SPR2ENDSTATE) + nextFrame--; + else + nextFrame = 0; + } if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; else From 750bdd9d607f1a078d16b88a87d59b12bf0992a7 Mon Sep 17 00:00:00 2001 From: lachablock Date: Sat, 22 May 2021 23:25:36 +1000 Subject: [PATCH 161/241] Respect mobj->color while enemies & bosses flash, but in OpenGL --- src/hardware/hw_main.c | 2 +- src/hardware/hw_md2.c | 28 ++++++++++------------------ 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index dd633d6fc..cec55e601 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5327,7 +5327,7 @@ static void HWR_ProjectSprite(mobj_t *thing) else if (vis->mobj->type == MT_METALSONIC_BATTLE) vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); else - vis->colormap = R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + vis->colormap = R_GetTranslationColormap(TC_BOSS, vis->mobj->color, GTC_CACHE); } else if (thing->color) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 9c3aa9e58..fd7b67aad 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -777,24 +777,7 @@ static void HWR_CreateBlendedTexture(patch_t *gpatch, patch_t *blendgpatch, GLMi while (size--) { - if (skinnum == TC_BOSS) - { - // Turn everything below a certain threshold white - if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue < 127) - { - // Lactozilla: Invert the colors - cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue); - } - else - { - cur->s.red = image->s.red; - cur->s.green = image->s.green; - cur->s.blue = image->s.blue; - } - - cur->s.alpha = image->s.alpha; - } - else if (skinnum == TC_ALLWHITE) + if (skinnum == TC_ALLWHITE) { // Turn everything white cur->s.red = cur->s.green = cur->s.blue = 255; @@ -1065,6 +1048,15 @@ skippixel: cur->s.alpha = image->s.alpha; } + else if (skinnum == TC_BOSS) + { + // Turn everything below a certain threshold white + if ((image->s.red == image->s.green) && (image->s.green == image->s.blue) && image->s.blue < 127) + { + // Lactozilla: Invert the colors + cur->s.red = cur->s.green = cur->s.blue = (255 - image->s.blue); + } + } } } From a1553c46232f6a4df12b71af9ff7f29bf36b9607 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Sat, 22 May 2021 20:08:11 -0300 Subject: [PATCH 162/241] Update r_opengl.c --- src/hardware/r_opengl/r_opengl.c | 75 ++++++++++---------------------- 1 file changed, 22 insertions(+), 53 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 003a1b3ca..de0e8c6a6 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -62,6 +62,9 @@ static FBITFIELD CurrentPolyFlags; static FTextureInfo *TexCacheTail = NULL; static FTextureInfo *TexCacheHead = NULL; +static RGBA_t *textureBuffer = NULL; +static size_t textureBufferSize = 0; + RGBA_t myPaletteData[256]; GLint screen_width = 0; // used by Draw2DLine() GLint screen_height = 0; @@ -202,32 +205,6 @@ static void GL_MSG_Error(const char *format, ...) #endif } -// ----------------------+ -// GetTextureFormatName : Returns the corresponding texture format string from the texture format enumeration. -// ----------------------+ -static const char *GetTextureFormatName(INT32 format) -{ - static char num[12]; - - switch (format) - { - case GL_TEXFMT_P_8: return "GL_TEXFMT_P_8"; - case GL_TEXFMT_AP_88: return "GL_TEXFMT_AP_88"; - case GL_TEXFMT_RGBA: return "GL_TEXFMT_RGBA"; - case GL_TEXFMT_ALPHA_8: return "GL_TEXFMT_ALPHA_8"; - case GL_TEXFMT_INTENSITY_8: return "GL_TEXFMT_INTENSITY_8"; - case GL_TEXFMT_ALPHA_INTENSITY_88: return "GL_TEXFMT_ALPHA_INTENSITY_88"; - default: break; - } - - // If the texture format is not known (due to it being invalid), - // return a string containing the format index instead. - format = INT32_MIN; - snprintf(num, sizeof(num), "%d", format); - - return num; -} - #ifdef STATIC_OPENGL /* 1.0 functions */ /* Miscellaneous */ @@ -1366,6 +1343,10 @@ void Flush(void) TexCacheTail = TexCacheHead = NULL; //Hurdler: well, TexCacheHead is already NULL tex_downloaded = 0; + + free(textureBuffer); + textureBuffer = NULL; + textureBufferSize = 0; } @@ -1758,28 +1739,16 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) CurrentPolyFlags = PolyFlags; } -// -------------------+ -// AllocTextureBuffer : Allocates memory for converting a non-RGBA texture into an RGBA texture. -// -------------------+ -static RGBA_t *AllocTextureBuffer(GLMipmap_t *pTexInfo) +static void AllocTextureBuffer(GLMipmap_t *pTexInfo) { - size_t len = (pTexInfo->width * pTexInfo->height); - RGBA_t *tex = calloc(len, sizeof(RGBA_t)); - - if (tex == NULL) - I_Error("AllocTextureBuffer: out of memory allocating %s bytes for texture %d, format %s", - sizeu1(len * sizeof(RGBA_t)), pTexInfo->downloaded, GetTextureFormatName(pTexInfo->format)); - - return tex; -} - -// ------------------+ -// FreeTextureBuffer : Frees memory allocated by AllocTextureBuffer. -// ------------------+ -static void FreeTextureBuffer(RGBA_t *tex) -{ - if (tex) - free(tex); + size_t size = pTexInfo->width * pTexInfo->height; + if (size > textureBufferSize) + { + textureBuffer = realloc(textureBuffer, size * sizeof(RGBA_t)); + if (textureBuffer == NULL) + I_Error("AllocTextureBuffer: out of memory allocating %s bytes", sizeu1(size * sizeof(RGBA_t))); + textureBufferSize = size; + } } // -----------------+ @@ -1810,7 +1779,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) if ((pTexInfo->format == GL_TEXFMT_P_8) || (pTexInfo->format == GL_TEXFMT_AP_88)) { - ptex = tex = AllocTextureBuffer(pTexInfo); + AllocTextureBuffer(pTexInfo); + ptex = tex = textureBuffer; for (j = 0; j < h; j++) { @@ -1851,7 +1821,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88) { - ptex = tex = AllocTextureBuffer(pTexInfo); + AllocTextureBuffer(pTexInfo); + ptex = tex = textureBuffer; for (j = 0; j < h; j++) { @@ -1868,7 +1839,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks { - ptex = tex = AllocTextureBuffer(pTexInfo); + AllocTextureBuffer(pTexInfo); + ptex = tex = textureBuffer; for (j = 0; j < h; j++) { @@ -1963,9 +1935,6 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } } - // Free the texture buffer - FreeTextureBuffer(tex); - if (pTexInfo->flags & TF_WRAPX) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); else From 75397c347db01720f32547ca02c8c7b9486a727c Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Sat, 22 May 2021 21:09:06 -0300 Subject: [PATCH 163/241] Remove FRACUNIT/2 --- src/r_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_main.c b/src/r_main.c index be9bbd7d0..17e124cb9 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -955,7 +955,7 @@ void R_ExecuteSetViewSize(void) j = viewheight*16; for (i = 0; i < j; i++) { - dy = ((i - viewheight*8)< Date: Mon, 24 May 2021 00:00:01 -0500 Subject: [PATCH 164/241] make a few messages more helpful --- src/d_clisrv.c | 6 +++--- src/locale/en.po | 6 +++--- src/locale/srb2.pot | 6 +++--- src/p_setup.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3a0e64c56..64efd3b60 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2952,7 +2952,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) { case KICK_MSG_GO_AWAY: if (!players[pnum].quittime) - HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false); + HU_AddChatText(va("\x82*%s has been kicked (No reason given)", player_names[pnum]), false); kickreason = KR_KICK; break; case KICK_MSG_PING_HIGH: @@ -2960,7 +2960,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) kickreason = KR_PINGLIMIT; break; case KICK_MSG_CON_FAIL: - HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false); + HU_AddChatText(va("\x82*%s left the game (Synch failure)", player_names[pnum]), false); kickreason = KR_SYNCH; if (M_CheckParm("-consisdump")) // Helps debugging some problems @@ -3006,7 +3006,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) kickreason = KR_LEAVE; break; case KICK_MSG_BANNED: - HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false); + HU_AddChatText(va("\x82*%s has been banned (No reason given)", player_names[pnum]), false); kickreason = KR_BAN; break; case KICK_MSG_CUSTOM_KICK: diff --git a/src/locale/en.po b/src/locale/en.po index 30ebe4368..8dd08173d 100644 --- a/src/locale/en.po +++ b/src/locale/en.po @@ -466,7 +466,7 @@ msgid "" msgstr "" #: d_clisrv.c:1764 -msgid "has been kicked (Go away)\n" +msgid "has been kicked (No reason given)\n" msgstr "" #: d_clisrv.c:1768 @@ -474,7 +474,7 @@ msgid "left the game (Broke ping limit)\n" msgstr "" #: d_clisrv.c:1772 -msgid "left the game (Consistency failure)\n" +msgid "left the game (Synch failure)\n" msgstr "" #: d_clisrv.c:1778 @@ -501,7 +501,7 @@ msgid "left the game\n" msgstr "" #: d_clisrv.c:1798 -msgid "has been banned (Don't come back)\n" +msgid "has been banned (No reason given)\n" msgstr "" #: d_clisrv.c:1802 diff --git a/src/locale/srb2.pot b/src/locale/srb2.pot index 960c36dbe..cd2db750d 100644 --- a/src/locale/srb2.pot +++ b/src/locale/srb2.pot @@ -459,7 +459,7 @@ msgid "" msgstr "" #: d_clisrv.c:1889 -msgid "has been kicked (Go away)\n" +msgid "has been kicked (No reason given)\n" msgstr "" #: d_clisrv.c:1893 @@ -467,7 +467,7 @@ msgid "left the game (Broke ping limit)\n" msgstr "" #: d_clisrv.c:1897 -msgid "left the game (Consistency failure)\n" +msgid "left the game (Synch failure)\n" msgstr "" #: d_clisrv.c:1903 @@ -494,7 +494,7 @@ msgid "left the game\n" msgstr "" #: d_clisrv.c:1923 -msgid "has been banned (Don't come back)\n" +msgid "has been banned (No reason given)\n" msgstr "" #: d_clisrv.c:1927 diff --git a/src/p_setup.c b/src/p_setup.c index 16c080248..231e5ed57 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2486,7 +2486,7 @@ static void P_LoadMapBSP(const virtres_t *virt) if (numsubsectors <= 0) I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); if (numnodes <= 0) - I_Error("Level has no nodes"); + I_Error("Level has no nodes (does your map have at least 2 sectors?)"); if (numsegs <= 0) I_Error("Level has no segs"); From a1235e144dfddd2151471071c8cdd713ae46d89b Mon Sep 17 00:00:00 2001 From: katsy Date: Wed, 26 May 2021 01:09:56 -0500 Subject: [PATCH 165/241] allow sliders passage through spin gaps --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 6ebee5afc..45867ee5b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -12971,7 +12971,7 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player) else if (canEnter == 2) return false; - return ((player->pflags & (PF_SPINNING|PF_GLIDING)) // players who are spinning or gliding + return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) // players who are spinning, sliding, or gliding || (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) // players who are landing from a glide || JUMPCURLED(player)); // players who are jumpcurled, but only if they would normally jump that way } From 6286fc8b05909e332dac676de5c7fe01d33266c0 Mon Sep 17 00:00:00 2001 From: katsy Date: Wed, 26 May 2021 02:37:46 -0400 Subject: [PATCH 166/241] add sliding flag to spinheight conditions --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 45867ee5b..9cb00967a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -12979,7 +12979,7 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player) // returns true if the player should use their skin's spinheight instead of their skin's height boolean P_PlayerShouldUseSpinHeight(player_t *player) { - return ((player->pflags & (PF_SPINNING|PF_GLIDING)) + return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) || (player->mo->state == &states[player->mo->info->painstate]) || (player->panim == PA_ROLL) || ((player->powers[pw_tailsfly] || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) From fd82357d4f72d2f8b7922551a98c3688bca77d5b Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Thu, 27 May 2021 18:35:15 -0400 Subject: [PATCH 167/241] Expose M_MapNumber to Lua --- src/lua_baselib.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index a0c99411b..2a8c62a37 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -28,6 +28,7 @@ #include "console.h" #include "d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff +#include "m_misc.h" // M_MapNumber #include "lua_script.h" #include "lua_libs.h" @@ -357,6 +358,23 @@ static int lib_pGetColorAfter(lua_State *L) return 1; } +// M_MISC +////////////// + +static int lib_mMapNumber(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + size_t len = strlen(arg); + if (len == 2 || len == 5) { + char first = arg[len-2]; + char second = arg[len-1]; + lua_pushinteger(L, M_MapNumber(first, second)); + } else { + lua_pushinteger(L, 0); + } + return 1; +} + // M_RANDOM ////////////// @@ -3778,6 +3796,9 @@ static luaL_Reg lib[] = { {"M_GetColorAfter",lib_pGetColorAfter}, {"M_GetColorBefore",lib_pGetColorBefore}, + // m_misc + {"M_MapNumber",lib_mMapNumber}, + // m_random {"P_RandomFixed",lib_pRandomFixed}, {"P_RandomByte",lib_pRandomByte}, From 07801a2a184b2120608759f80889a3a6113a02d3 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 28 May 2021 18:42:19 +0100 Subject: [PATCH 168/241] move P_MapEnd call in P_LoadLevel further down, so that the P_MapStart/End pair also encloses cached actions and the MapLoad Lua hook --- src/p_setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 16c080248..1abdccc21 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4223,7 +4223,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_ResetWaypoints(); - P_MapStart(); + P_MapStart(); // tmthing can be used starting from this point if (!P_LoadMapFromFile()) return false; @@ -4276,8 +4276,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // clear special respawning que iquehead = iquetail = 0; - P_MapEnd(); - // Remove the loading shit from the screen if (rendermode != render_none && !(titlemapinaction || reloadinggamestate)) F_WipeColorFill(levelfadecol); @@ -4323,6 +4321,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) LUAh_MapLoad(); } + P_MapEnd(); // tmthing is no longer needed from this point onwards + // No render mode or reloading gamestate, stop here. if (rendermode == render_none || reloadinggamestate) return true; From ada6ec07dbc76d0d6e732e3b761ef79819c38412 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 28 May 2021 18:47:09 +0100 Subject: [PATCH 169/241] Fix Lua versions of P_ZMovement and its clones as well as P_MovePlayer so tmthing changes don't linger afterwards --- src/lua_baselib.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index df370a431..daf1ee6b0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1044,48 +1044,56 @@ static int lib_pSceneryXYMovement(lua_State *L) static int lib_pZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_ZMovement(actor)); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 1; } static int lib_pRingZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_RingZMovement(actor); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 0; } static int lib_pSceneryZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SceneryZMovement(actor)); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 1; } static int lib_pPlayerZMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_PlayerZMovement(actor); P_CheckPosition(actor, actor->x, actor->y); + P_SetTarget(&tmthing, ptmthing); return 0; } @@ -1472,11 +1480,13 @@ static int lib_pSpawnSkidDust(lua_State *L) static int lib_pMovePlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *ptmthing = tmthing; NOHUD INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_MovePlayer(player); + P_SetTarget(&tmthing, ptmthing); return 0; } From 45b1223f3e356544ef8968c1d7054727e261cd1e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 28 May 2021 18:56:32 +0100 Subject: [PATCH 170/241] My mistake, `P_PreTicker` calls `P_MapStart` and `P_MapEnd` too, so rework my earlier fix a bit --- src/p_setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 1abdccc21..913dfe403 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4295,6 +4295,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) P_RunCachedActions(); + P_MapEnd(); // tmthing is no longer needed from this point onwards + // Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap... if (!titlemapinaction) { @@ -4318,11 +4320,11 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); } P_PreTicker(2); + P_MapStart(); // just in case MapLoad modifies tmthing LUAh_MapLoad(); + P_MapEnd(); // just in case MapLoad modifies tmthing } - P_MapEnd(); // tmthing is no longer needed from this point onwards - // No render mode or reloading gamestate, stop here. if (rendermode == render_none || reloadinggamestate) return true; From 8d8f62baefdcbb1b71d75d505b95e3cc4a675056 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Fri, 28 May 2021 23:59:39 -0400 Subject: [PATCH 171/241] Add additional multitagging functionality --- extras/conf/SRB2-22.cfg | 14 ++++++++++++++ src/p_setup.c | 33 +++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index d36c16b75..ad930a485 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -640,22 +640,36 @@ linedeftypes prefix = "(63)"; } + 96 + { + title = "Apply Tag to Tagged Sectors"; + prefix = "(96)"; + flags8192text = "[13] Use Front Side Offsets"; + flags32768text = "[15] Use Back Side Offsets"; + } + 97 { title = "Apply Tag to Front Sector"; prefix = "(97)"; + flags8192text = "[13] Use Front Side Offsets"; + flags32768text = "[15] Use Back Side Offsets"; } 98 { title = "Apply Tag to Back Sector"; prefix = "(98)"; + flags8192text = "[13] Use Front Side Offsets"; + flags32768text = "[15] Use Back Side Offsets"; } 99 { title = "Apply Tag to Front and Back Sectors"; prefix = "(99)"; + flags8192text = "[13] Use Front Side Offsets"; + flags32768text = "[15] Use Back Side Offsets"; } 540 diff --git a/src/p_setup.c b/src/p_setup.c index 16c080248..6375decac 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2952,19 +2952,44 @@ static void P_LinkMapData(void) // For maps in binary format, add multi-tags from linedef specials. This must be done // before any linedef specials have been processed. +static void P_AddBinaryMapTagsFromLine(sector_t *sector, line_t *line) +{ + Tag_Add(§or->tags, Tag_FGet(&line->tags)); + if (line->flags & ML_EFFECT6) { + if (sides[line->sidenum[0]].textureoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].textureoffset); + if (sides[line->sidenum[0]].rowoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].rowoffset); + } + if (line->flags & ML_TFERLINE) { + if (sides[line->sidenum[1]].textureoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].textureoffset); + if (sides[line->sidenum[1]].rowoffset) + Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].rowoffset); + } +} + static void P_AddBinaryMapTags(void) { size_t i; for (i = 0; i < numlines; i++) { + // 96: Apply Tag to Tagged Sectors // 97: Apply Tag to Front Sector // 98: Apply Tag to Back Sector // 99: Apply Tag to Front and Back Sectors - if (lines[i].special == 97 || lines[i].special == 99) - Tag_Add(&lines[i].frontsector->tags, Tag_FGet(&lines[i].tags)); - if (lines[i].special == 98 || lines[i].special == 99) - Tag_Add(&lines[i].backsector->tags, Tag_FGet(&lines[i].tags)); + if (lines[i].special == 96) { + mtag_t tag = Tag_FGet(&lines[i].frontsector->tags); + INT32 s; + TAG_ITER_DECLARECOUNTER(0); + TAG_ITER_SECTORS(0, tag, s) + P_AddBinaryMapTagsFromLine(§ors[s], &lines[i]); + } else if (lines[i].special == 97 || lines[i].special == 99) { + P_AddBinaryMapTagsFromLine(lines[i].frontsector, &lines[i]); + } else if (lines[i].special == 98 || lines[i].special == 99) { + P_AddBinaryMapTagsFromLine(lines[i].backsector, &lines[i]); + } } } From 7d71d534d47941faaa5dbe962a20b52ab850a8b8 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 29 May 2021 00:40:06 -0400 Subject: [PATCH 172/241] Add missing "/ FRACUNIT" to texture offset code --- src/p_setup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 6375decac..4bb47c943 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2957,15 +2957,15 @@ static void P_AddBinaryMapTagsFromLine(sector_t *sector, line_t *line) Tag_Add(§or->tags, Tag_FGet(&line->tags)); if (line->flags & ML_EFFECT6) { if (sides[line->sidenum[0]].textureoffset) - Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].textureoffset); + Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].textureoffset / FRACUNIT); if (sides[line->sidenum[0]].rowoffset) - Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].rowoffset); + Tag_Add(§or->tags, (INT32)sides[line->sidenum[0]].rowoffset / FRACUNIT); } if (line->flags & ML_TFERLINE) { if (sides[line->sidenum[1]].textureoffset) - Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].textureoffset); + Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].textureoffset / FRACUNIT); if (sides[line->sidenum[1]].rowoffset) - Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].rowoffset); + Tag_Add(§or->tags, (INT32)sides[line->sidenum[1]].rowoffset / FRACUNIT); } } From eee894581aecc4575baf0edb4cb46941806efbf8 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 29 May 2021 00:54:31 -0400 Subject: [PATCH 173/241] Make linedef 96 skip the control sector --- src/p_setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 4bb47c943..336cf9886 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2983,8 +2983,10 @@ static void P_AddBinaryMapTags(void) mtag_t tag = Tag_FGet(&lines[i].frontsector->tags); INT32 s; TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, s) - P_AddBinaryMapTagsFromLine(§ors[s], &lines[i]); + TAG_ITER_SECTORS(0, tag, s) { + if (s != lines[i].frontsector - sectors) // Skip the control sector + P_AddBinaryMapTagsFromLine(§ors[s], &lines[i]); + } } else if (lines[i].special == 97 || lines[i].special == 99) { P_AddBinaryMapTagsFromLine(lines[i].frontsector, &lines[i]); } else if (lines[i].special == 98 || lines[i].special == 99) { From 93de054786147c7f64360177cd271ed70eedb2fb Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 29 May 2021 11:08:46 -0400 Subject: [PATCH 174/241] Fix linedef type 96 (I had it all wrong) --- src/p_setup.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 336cf9886..0d061aaab 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2980,12 +2980,36 @@ static void P_AddBinaryMapTags(void) // 98: Apply Tag to Back Sector // 99: Apply Tag to Front and Back Sectors if (lines[i].special == 96) { + size_t j; mtag_t tag = Tag_FGet(&lines[i].frontsector->tags); - INT32 s; - TAG_ITER_DECLARECOUNTER(0); - TAG_ITER_SECTORS(0, tag, s) { - if (s != lines[i].frontsector - sectors) // Skip the control sector - P_AddBinaryMapTagsFromLine(§ors[s], &lines[i]); + mtag_t target_tags[5]; + target_tags[0] = Tag_FGet(&lines[i].tags); + if (lines[i].flags & ML_EFFECT6) { + target_tags[1] = (INT32)sides[lines[i].sidenum[0]].textureoffset / FRACUNIT; + target_tags[2] = (INT32)sides[lines[i].sidenum[0]].rowoffset / FRACUNIT; + } else { + target_tags[1] = target_tags[2] = 0; + } + if (lines[i].flags & ML_TFERLINE) { + target_tags[3] = (INT32)sides[lines[i].sidenum[1]].textureoffset / FRACUNIT; + target_tags[4] = (INT32)sides[lines[i].sidenum[1]].rowoffset / FRACUNIT; + } else { + target_tags[3] = target_tags[4] = 0; + } + + for (j = 0; j < numsectors; j++) { + CONS_Printf("Sector %zu (tag %d):\n", j, Tag_FGet(§ors[j].tags)); + size_t k; for (k = 0; k < 5; k++) { + if (k > 0 && !target_tags[k]) + continue; + if (Tag_Find(§ors[j].tags, target_tags[k])) { + Tag_Add(§ors[j].tags, tag); + CONS_Printf(" Tag %d found, added tag %d\n", target_tags[k], tag); + break; + } else { + CONS_Printf(" Tag %d not found\n", target_tags[k]); + } + } } } else if (lines[i].special == 97 || lines[i].special == 99) { P_AddBinaryMapTagsFromLine(lines[i].frontsector, &lines[i]); From 5090de58097eed382a58402af0f3217eb3493381 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 29 May 2021 12:09:30 -0400 Subject: [PATCH 175/241] Remove leftover debug printfs --- src/p_setup.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 0d061aaab..ea655f5f9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2998,16 +2998,13 @@ static void P_AddBinaryMapTags(void) } for (j = 0; j < numsectors; j++) { - CONS_Printf("Sector %zu (tag %d):\n", j, Tag_FGet(§ors[j].tags)); size_t k; for (k = 0; k < 5; k++) { if (k > 0 && !target_tags[k]) continue; if (Tag_Find(§ors[j].tags, target_tags[k])) { Tag_Add(§ors[j].tags, tag); - CONS_Printf(" Tag %d found, added tag %d\n", target_tags[k], tag); break; } else { - CONS_Printf(" Tag %d not found\n", target_tags[k]); } } } From 2d4411d077a0d36a78707e655863b94afd127ec4 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 29 May 2021 12:23:35 -0400 Subject: [PATCH 176/241] Remove empty 'else' block (also leftover) --- src/p_setup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index ea655f5f9..095524203 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3004,7 +3004,6 @@ static void P_AddBinaryMapTags(void) if (Tag_Find(§ors[j].tags, target_tags[k])) { Tag_Add(§ors[j].tags, tag); break; - } else { } } } From f8fe763df22285af086f51389186ebf8ab15b2b8 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sat, 29 May 2021 12:28:06 -0400 Subject: [PATCH 177/241] Fix linedef type 99 --- src/p_setup.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 095524203..f60af94ed 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3007,10 +3007,11 @@ static void P_AddBinaryMapTags(void) } } } - } else if (lines[i].special == 97 || lines[i].special == 99) { - P_AddBinaryMapTagsFromLine(lines[i].frontsector, &lines[i]); - } else if (lines[i].special == 98 || lines[i].special == 99) { - P_AddBinaryMapTagsFromLine(lines[i].backsector, &lines[i]); + } else { + if (lines[i].special == 97 || lines[i].special == 99) + P_AddBinaryMapTagsFromLine(lines[i].frontsector, &lines[i]); + if (lines[i].special == 98 || lines[i].special == 99) + P_AddBinaryMapTagsFromLine(lines[i].backsector, &lines[i]); } } } From d10cf4faf52734dc48b7fe7d4865610bce018e0a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 29 May 2021 22:54:58 +0100 Subject: [PATCH 178/241] A_Custom3DRotate: don't scale hspeed and vspeed - they are angular speeds, not linear! (I added the scaling to this action somewhere between 7-9 years ago, and somehow never knew I made this mistake until now, welp.) --- src/p_enemy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 3b13fe295..b90a87cc0 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -9899,8 +9899,8 @@ void A_Custom3DRotate(mobj_t *actor) const fixed_t radius = FixedMul(loc1lw*FRACUNIT, actor->scale); const fixed_t hOff = FixedMul(loc1up*FRACUNIT, actor->scale); - const fixed_t hspeed = FixedMul(loc2up*FRACUNIT/10, actor->scale); - const fixed_t vspeed = FixedMul(loc2lw*FRACUNIT/10, actor->scale); + const fixed_t hspeed = loc2up*FRACUNIT/10; // Monster's note (29/05/21): DO NOT SCALE, this is an angular speed! + const fixed_t vspeed = loc2lw*FRACUNIT/10; // ditto if (LUA_CallAction(A_CUSTOM3DROTATE, actor)) return; From 0b51b391f1a7e61f1e64992c92cd96e483b1ed08 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Sun, 30 May 2021 12:16:15 -0400 Subject: [PATCH 179/241] Make 96's flags consistent with 97-99 by default --- extras/conf/SRB2-22.cfg | 17 +++++++++-------- src/p_setup.c | 35 +++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index ad930a485..5a464eb5d 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -644,32 +644,33 @@ linedeftypes { title = "Apply Tag to Tagged Sectors"; prefix = "(96)"; - flags8192text = "[13] Use Front Side Offsets"; - flags32768text = "[15] Use Back Side Offsets"; + flags1024text = "[10] Offsets are target tags"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; } 97 { title = "Apply Tag to Front Sector"; prefix = "(97)"; - flags8192text = "[13] Use Front Side Offsets"; - flags32768text = "[15] Use Back Side Offsets"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; } 98 { title = "Apply Tag to Back Sector"; prefix = "(98)"; - flags8192text = "[13] Use Front Side Offsets"; - flags32768text = "[15] Use Back Side Offsets"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; } 99 { title = "Apply Tag to Front and Back Sectors"; prefix = "(99)"; - flags8192text = "[13] Use Front Side Offsets"; - flags32768text = "[15] Use Back Side Offsets"; + flags8192text = "[13] Use front side offsets"; + flags32768text = "[15] Use back side offsets"; } 540 diff --git a/src/p_setup.c b/src/p_setup.c index f60af94ed..7ecaf2ff4 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2982,28 +2982,31 @@ static void P_AddBinaryMapTags(void) if (lines[i].special == 96) { size_t j; mtag_t tag = Tag_FGet(&lines[i].frontsector->tags); - mtag_t target_tags[5]; - target_tags[0] = Tag_FGet(&lines[i].tags); + mtag_t target_tag = Tag_FGet(&lines[i].tags); + mtag_t offset_tags[4]; + memset(offset_tags, 0, sizeof(mtag_t)*4); if (lines[i].flags & ML_EFFECT6) { - target_tags[1] = (INT32)sides[lines[i].sidenum[0]].textureoffset / FRACUNIT; - target_tags[2] = (INT32)sides[lines[i].sidenum[0]].rowoffset / FRACUNIT; - } else { - target_tags[1] = target_tags[2] = 0; + offset_tags[1] = (INT32)sides[lines[i].sidenum[0]].textureoffset / FRACUNIT; + offset_tags[2] = (INT32)sides[lines[i].sidenum[0]].rowoffset / FRACUNIT; } if (lines[i].flags & ML_TFERLINE) { - target_tags[3] = (INT32)sides[lines[i].sidenum[1]].textureoffset / FRACUNIT; - target_tags[4] = (INT32)sides[lines[i].sidenum[1]].rowoffset / FRACUNIT; - } else { - target_tags[3] = target_tags[4] = 0; + offset_tags[3] = (INT32)sides[lines[i].sidenum[1]].textureoffset / FRACUNIT; + offset_tags[4] = (INT32)sides[lines[i].sidenum[1]].rowoffset / FRACUNIT; } for (j = 0; j < numsectors; j++) { - size_t k; for (k = 0; k < 5; k++) { - if (k > 0 && !target_tags[k]) - continue; - if (Tag_Find(§ors[j].tags, target_tags[k])) { - Tag_Add(§ors[j].tags, tag); - break; + boolean matches_target_tag = Tag_Find(§ors[j].tags, target_tag); + size_t k; for (k = 0; k < 4; k++) { + if (lines[i].flags & ML_EFFECT5) { + if (matches_target_tag || offset_tags[k] && Tag_Find(§ors[j].tags, offset_tags[k])) { + Tag_Add(§ors[j].tags, tag); + break; + } + } else if (matches_target_tag) { + if (k == 0) + Tag_Add(§ors[j].tags, tag); + if (offset_tags[k]) + Tag_Add(§ors[j].tags, offset_tags[k]); } } } From 92209bf246068c10b1ac318faecc85313dd85e8a Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Mon, 31 May 2021 15:09:54 -0400 Subject: [PATCH 180/241] Update p_user.c --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index c5f919c78..6b3a8f585 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2992,7 +2992,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) player->powers[pw_spacetime] = 0; // Underwater audio cues - if (P_IsLocalPlayer(player) && !player->bot) + if (P_IsLocalPlayer(player) && !player->bot && !(player->mo->eflags & MFE_COLDWATER)) { if ((player->powers[pw_underwater] == 25*TICRATE + 1) || (player->powers[pw_underwater] == 20*TICRATE + 1) From 3e91a8b2d4ce08cdcda59fd37db8b2c986397c6e Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Mon, 31 May 2021 19:23:37 +0000 Subject: [PATCH 181/241] Revert "Update p_user.c" This reverts commit 92209bf246068c10b1ac318faecc85313dd85e8a --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 6b3a8f585..c5f919c78 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2992,7 +2992,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) player->powers[pw_spacetime] = 0; // Underwater audio cues - if (P_IsLocalPlayer(player) && !player->bot && !(player->mo->eflags & MFE_COLDWATER)) + if (P_IsLocalPlayer(player) && !player->bot) { if ((player->powers[pw_underwater] == 25*TICRATE + 1) || (player->powers[pw_underwater] == 20*TICRATE + 1) From 172454f108ea17ee4c0b289df4924fc4dd8b1b02 Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Tue, 1 Jun 2021 10:09:57 -0400 Subject: [PATCH 182/241] Fix offset_tags array indices --- src/p_setup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 7ecaf2ff4..50b073a21 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2986,12 +2986,12 @@ static void P_AddBinaryMapTags(void) mtag_t offset_tags[4]; memset(offset_tags, 0, sizeof(mtag_t)*4); if (lines[i].flags & ML_EFFECT6) { - offset_tags[1] = (INT32)sides[lines[i].sidenum[0]].textureoffset / FRACUNIT; - offset_tags[2] = (INT32)sides[lines[i].sidenum[0]].rowoffset / FRACUNIT; + offset_tags[0] = (INT32)sides[lines[i].sidenum[0]].textureoffset / FRACUNIT; + offset_tags[1] = (INT32)sides[lines[i].sidenum[0]].rowoffset / FRACUNIT; } if (lines[i].flags & ML_TFERLINE) { - offset_tags[3] = (INT32)sides[lines[i].sidenum[1]].textureoffset / FRACUNIT; - offset_tags[4] = (INT32)sides[lines[i].sidenum[1]].rowoffset / FRACUNIT; + offset_tags[2] = (INT32)sides[lines[i].sidenum[1]].textureoffset / FRACUNIT; + offset_tags[3] = (INT32)sides[lines[i].sidenum[1]].rowoffset / FRACUNIT; } for (j = 0; j < numsectors; j++) { From 115254efc9e2b42c15c93d478611d0a64f4a27bd Mon Sep 17 00:00:00 2001 From: flarn2006 Date: Tue, 1 Jun 2021 17:10:29 -0400 Subject: [PATCH 183/241] Fix compiler warning related to precedence --- 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 50b073a21..61d1a5e46 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2998,7 +2998,7 @@ static void P_AddBinaryMapTags(void) boolean matches_target_tag = Tag_Find(§ors[j].tags, target_tag); size_t k; for (k = 0; k < 4; k++) { if (lines[i].flags & ML_EFFECT5) { - if (matches_target_tag || offset_tags[k] && Tag_Find(§ors[j].tags, offset_tags[k])) { + if (matches_target_tag || (offset_tags[k] && Tag_Find(§ors[j].tags, offset_tags[k]))) { Tag_Add(§ors[j].tags, tag); break; } From 476dcc861be0c82e4a99f9379970588c95cbcefa Mon Sep 17 00:00:00 2001 From: lachablock Date: Thu, 3 Jun 2021 14:36:29 +1000 Subject: [PATCH 184/241] Restore P_AproxDistance Lua parity --- src/lua_baselib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1a0b53920..594ac6af2 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -444,7 +444,7 @@ static int lib_pAproxDistance(lua_State *L) fixed_t dx = luaL_checkfixed(L, 1); fixed_t dy = luaL_checkfixed(L, 2); //HUDSAFE - lua_pushfixed(L, R_PointToDist2(0, 0, dx, dy)); + lua_pushfixed(L, P_AproxDistance(dx, dy)); return 1; } From 6ff212b79f4bc97b2f34edf2ebc62e79e64ca519 Mon Sep 17 00:00:00 2001 From: sphere Date: Thu, 3 Jun 2021 16:01:09 +0200 Subject: [PATCH 185/241] Use floating-point math for polyobject planes as well. --- src/r_plane.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/r_plane.c b/src/r_plane.c index 4c757d8ca..818770906 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -380,9 +380,11 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, { if (polyobj->angle != 0) { - angle_t fineshift = polyobj->angle >> ANGLETOFINESHIFT; - xoff -= FixedMul(FINECOSINE(fineshift), polyobj->centerPt.x)+FixedMul(FINESINE(fineshift), polyobj->centerPt.y); - yoff -= FixedMul(FINESINE(fineshift), polyobj->centerPt.x)-FixedMul(FINECOSINE(fineshift), polyobj->centerPt.y); + float ang = ANG2RAD(polyobj->angle); + float x = FixedToFloat(polyobj->centerPt.x); + float y = FixedToFloat(polyobj->centerPt.y); + xoff -= FloatToFixed(x * cos(ang) + y * sin(ang)); + yoff -= FloatToFixed(x * sin(ang) - y * cos(ang)); } else { From 409cba678dcabcc7cb2960cf3d444a45b064a47b Mon Sep 17 00:00:00 2001 From: GoldenTails Date: Sat, 5 Jun 2021 18:35:44 -0500 Subject: [PATCH 186/241] metalrecording --- src/lua_script.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 6b8613812..4e04c2ee0 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -184,6 +184,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"modeattacking")) { lua_pushboolean(L, modeattacking); return 1; + } else if (fastcmp(word,"metalrecording")) { + lua_pushboolean(L, metalrecording); + return 1; } else if (fastcmp(word,"splitscreen")) { lua_pushboolean(L, splitscreen); return 1; From 0f4eb4fab949976276c4a8e9426d45bbfc275eec Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 7 Jun 2021 18:13:22 -0700 Subject: [PATCH 187/241] Merge conflicts 4d22b9f17 --- src/lua_hook.h | 6 +++++- src/lua_hooklib.c | 45 ++++++++++++++++++++++++++++++++++++++++----- src/p_user.c | 46 +++++++++++++++++++++++----------------------- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index 0f8482794..b44233734 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -68,6 +68,8 @@ automatically. X (GameQuit),\ X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\ X (MusicChange),\ + X (PlayerHeight),/* override player height */\ + X (PlayerCanEnterSpinGaps),\ #define STRING_HOOK_LIST(X) \ X (BotAI),/* B_BuildTailsTiccmd by skin name */\ @@ -124,3 +126,5 @@ int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend); int LUA_HookShouldJingleContinue(player_t *, const char *musname); int LUA_HookPlayerCmd(player_t *, ticcmd_t *); int LUA_HookMusicChange(const char *oldname, struct MusicChange *); +fixed_t LUA_HookPlayerHeight(player_t *player); +int LUA_HookPlayerCanEnterSpinGaps(player_t *player); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 7f5e3dc96..9f4fa4c88 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2020 by Sonic Team Junior. +// Copyright (C) 2012-2021 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -231,7 +231,7 @@ typedef struct Hook_State Hook_State; typedef void (*Hook_Callback)(Hook_State *); struct Hook_State { - int status;/* return status to calling function */ + INT32 status;/* return status to calling function */ void * userdata; int hook_type; mobjtype_t mobj_type;/* >0 if mobj hook */ @@ -1005,13 +1005,13 @@ static void res_musicchange(Hook_State *hook) if (lua_isboolean(gL, -4)) *musicchange->looping = lua_toboolean(gL, -4); // output 4: position override - if (lua_isboolean(gL, -3)) + if (lua_isnumber(gL, -3)) *musicchange->position = lua_tonumber(gL, -3); // output 5: prefadems override - if (lua_isboolean(gL, -2)) + if (lua_isnumber(gL, -2)) *musicchange->prefadems = lua_tonumber(gL, -2); // output 6: fadeinms override - if (lua_isboolean(gL, -1)) + if (lua_isnumber(gL, -1)) *musicchange->fadeinms = lua_tonumber(gL, -1); } @@ -1052,3 +1052,38 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param) return hook.status; } + +static void res_playerheight(Hook_State *hook) +{ + if (!lua_isnil(gL, -1)) + { + fixed_t returnedheight = lua_tonumber(gL, -1); + // 0 height has... strange results, but it's not problematic like negative heights are. + // when an object's height is set to a negative number directly with lua, it's forced to 0 instead. + // here, I think it's better to ignore negatives so that they don't replace any results of previous hooks! + if (returnedheight >= 0) + hook->status = returnedheight; + } +} + +fixed_t LUA_HookPlayerHeight(player_t *player) +{ + Hook_State hook; + if (prepare_hook(&hook, -1, HOOK(PlayerHeight))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, 1, res_playerheight); + } + return hook.status; +} + +int LUA_HookPlayerCanEnterSpinGaps(player_t *player) +{ + Hook_State hook; + if (prepare_hook(&hook, 0, HOOK(PlayerCanEnterSpinGaps))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + call_hooks(&hook, 1, 1, res_force); + } + return hook.status; +} diff --git a/src/p_user.c b/src/p_user.c index 2b773c84a..c3184b52f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1111,7 +1111,7 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) return false; { - UINT8 shouldCollide = LUAh_PlayerCanDamage(player, thing); + UINT8 shouldCollide = LUA_HookPlayerCanDamage(player, thing); if (P_MobjWasRemoved(thing)) return false; // removed??? if (shouldCollide == 1) @@ -1594,7 +1594,7 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname) break; case JT_OTHER: // Other state - result = LUAh_ShouldJingleContinue(&players[i], musname); + result = LUA_HookShouldJingleContinue(&players[i], musname); break; case JT_NONE: // Null state @@ -1860,7 +1860,7 @@ void P_SpawnShieldOrb(player_t *player) I_Error("P_SpawnShieldOrb: player->mo is NULL!\n"); #endif - if (LUAh_ShieldSpawn(player)) + if (LUA_HookPlayer(player, HOOK(ShieldSpawn))) return; if (player->powers[pw_shield] & SH_FORCE) @@ -4583,7 +4583,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_SPIN) { - if (LUAh_SpinSpecial(player)) + if (LUA_HookPlayer(player, HOOK(SpinSpecial))) return; } @@ -5055,7 +5055,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUAh_ShieldSpecial(player))) // Spin button effects + if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5179,7 +5179,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) // and you don't have a shield, do it! P_DoSuperTransformation(player, false); } - else if (!LUAh_JumpSpinSpecial(player)) + else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) switch (player->charability) { case CA_THOK: @@ -5252,7 +5252,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_JUMP && !player->exiting && !P_PlayerInPain(player)) { - if (LUAh_JumpSpecial(player)) + if (LUA_HookPlayer(player, HOOK(JumpSpecial))) ; // all situations below this require jump button not to be pressed already else if (player->pflags & PF_JUMPDOWN) @@ -5287,7 +5287,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) }*/ else if (player->pflags & PF_JUMPED) { - if (!LUAh_AbilitySpecial(player)) + if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) switch (player->charability) { case CA_THOK: @@ -5480,7 +5480,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } else if (player->pflags & PF_THOKKED) { - if (!LUAh_AbilitySpecial(player)) + if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) switch (player->charability) { case CA_FLY: @@ -5503,7 +5503,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; } } - else if ((!(player->charflags & SF_NOSHIELDABILITY)) && ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super] && !LUAh_ShieldSpecial(player))) + else if ((!(player->charflags & SF_NOSHIELDABILITY)) && ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super] && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) P_DoJumpShield(player); } @@ -8653,7 +8653,7 @@ void P_MovePlayer(player_t *player) { boolean atspinheight = false; fixed_t oldheight = player->mo->height; - fixed_t luaheight = LUAh_PlayerHeight(player); + fixed_t luaheight = LUA_HookPlayerHeight(player); if (luaheight != -1) { @@ -10515,7 +10515,7 @@ boolean P_SpectatorJoinGame(player_t *player) else changeto = (P_RandomFixed() & 1) + 1; - if (!LUAh_TeamSwitch(player, changeto, true, false, false)) + if (!LUA_HookTeamSwitch(player, changeto, true, false, false)) return false; if (player->mo) @@ -10532,7 +10532,7 @@ boolean P_SpectatorJoinGame(player_t *player) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -10550,7 +10550,7 @@ boolean P_SpectatorJoinGame(player_t *player) // respawn in place and sit there for the rest of the round. if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE))) { - if (!LUAh_TeamSwitch(player, 3, true, false, false)) + if (!LUA_HookTeamSwitch(player, 3, true, false, false)) return false; if (player->mo) { @@ -10577,7 +10577,7 @@ boolean P_SpectatorJoinGame(player_t *player) { // Call ViewpointSwitch hooks here. // The viewpoint was forcibly changed. - LUAh_ViewpointSwitch(player, &players[consoleplayer], true); + LUA_HookViewpointSwitch(player, &players[consoleplayer], true); displayplayer = consoleplayer; } @@ -11503,7 +11503,7 @@ void P_PlayerThink(player_t *player) } if (player->playerstate == PST_REBORN) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -11605,7 +11605,7 @@ void P_PlayerThink(player_t *player) if (player->playerstate == PST_DEAD) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } } @@ -11726,7 +11726,7 @@ void P_PlayerThink(player_t *player) { player->mo->flags2 &= ~MF2_SHADOW; P_DeathThink(player); - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; } @@ -11768,7 +11768,7 @@ void P_PlayerThink(player_t *player) { if (P_SpectatorJoinGame(player)) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; // player->mo was removed. } } @@ -11873,7 +11873,7 @@ void P_PlayerThink(player_t *player) if (!player->mo) { - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); return; // P_MovePlayer removed player->mo. } @@ -12327,7 +12327,7 @@ void P_PlayerThink(player_t *player) } #undef dashmode - LUAh_PlayerThink(player); + LUA_HookPlayer(player, HOOK(PlayerThink)); /* // Colormap verification @@ -12896,7 +12896,7 @@ void P_PlayerAfterThink(player_t *player) if (player->followmobj) { - if (LUAh_FollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) + if (LUA_HookFollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) {;} else { @@ -12975,7 +12975,7 @@ boolean P_PlayerFullbright(player_t *player) // returns true if the player can enter a sector that they could not if standing at their skin's full height boolean P_PlayerCanEnterSpinGaps(player_t *player) { - UINT8 canEnter = LUAh_PlayerCanEnterSpinGaps(player); + UINT8 canEnter = LUA_HookPlayerCanEnterSpinGaps(player); if (canEnter == 1) return true; else if (canEnter == 2) From 52f9b47ce35008b8b4afce5bba2ccff73f5bfe17 Mon Sep 17 00:00:00 2001 From: sphere Date: Thu, 10 Jun 2021 17:49:33 +0200 Subject: [PATCH 188/241] Ignore a linedef tag of 0 when using linedef action 96. --- 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 51d2f474d..db44e4be0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2995,7 +2995,7 @@ static void P_AddBinaryMapTags(void) } for (j = 0; j < numsectors; j++) { - boolean matches_target_tag = Tag_Find(§ors[j].tags, target_tag); + boolean matches_target_tag = target_tag && Tag_Find(§ors[j].tags, target_tag); size_t k; for (k = 0; k < 4; k++) { if (lines[i].flags & ML_EFFECT5) { if (matches_target_tag || (offset_tags[k] && Tag_Find(§ors[j].tags, offset_tags[k]))) { From 4c9b83b6bdd8cd3e2626505940de75668e3db0c2 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 10 Jun 2021 21:20:42 +0100 Subject: [PATCH 189/241] Allow P_CheckSight to see through FF_FOG FOFs --- src/p_sight.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_sight.c b/src/p_sight.c index e4a37a718..706745f35 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -307,7 +307,7 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) for (rover = front->ffloors; rover; rover = rover->next) { if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT) + || !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG))) { continue; } @@ -323,7 +323,7 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) for (rover = back->ffloors; rover; rover = rover->next) { if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT) + || !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG))) { continue; } @@ -452,7 +452,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) /// \todo Improve by checking fog density/translucency /// and setting a sight limit. if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERPLANES) || rover->flags & FF_TRANSLUCENT) + || !(rover->flags & FF_RENDERPLANES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG))) { continue; } From c9417f26e59bffcf2b0f2f5452d8ce5e98e2da55 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 10 Jun 2021 17:47:03 -0700 Subject: [PATCH 190/241] Fix pop original table in lua net archive --- src/lua_hooklib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 9f4fa4c88..a8d49db7e 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -851,7 +851,7 @@ void LUA_HookNetArchive(lua_CFunction archFunc) init_hook_call(&hook, 1, 0, res_none); call_mapped(&hook, map); - lua_pop(gL, 2); // pop hook table and archFunc + lua_pop(gL, 1); // pop archFunc lua_remove(gL, EINDEX); // pop error handler // stack: tables } From 46ca9613c68422a26910cbb034a9f3e004a967c3 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 10 Jun 2021 18:09:39 -0700 Subject: [PATCH 191/241] Pop hook id fetched from table --- src/lua_hooklib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index a8d49db7e..63a1b111d 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -352,6 +352,7 @@ static void get_hook_from_table(Hook_State *hook, int n) { lua_rawgeti(gL, -1, n); hook->id = lua_tonumber(gL, -1); + lua_pop(gL, 1); lua_getref(gL, hookRefs[hook->id]); } From 8be7c1a03d8a4c011b777eb41d8e906e4539e7bc Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 11 Jun 2021 18:31:38 -0700 Subject: [PATCH 192/241] Fix double micros conv. blame e0a307da15 --- src/lua_hooklib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 63a1b111d..2ecd12589 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -624,7 +624,7 @@ void LUA_HookThinkFrame(void) if (cv_perfstats.value == 3) { lua_Debug ar; - time_taken = I_PreciseToMicros(I_GetPreciseTime() - time_taken); + time_taken = I_GetPreciseTime() - time_taken; lua_getinfo(gL, ">S", &ar); PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); hook_index++; From 781678389f8c591c5f201b2c789e5d92b90788c8 Mon Sep 17 00:00:00 2001 From: Radicalicious Date: Sat, 12 Jun 2021 20:36:57 -0400 Subject: [PATCH 193/241] Replace "II" with "2" for consistency --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 688cd4fc7..bfea57a60 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1063,7 +1063,7 @@ boolean F_IntroResponder(event_t *event) // CREDITS // ========= static const char *credits[] = { - "\1Sonic Robo Blast II", + "\1Sonic Robo Blast 2", "\1Credits", "", "\1Game Design", From df5c9933ec355b2924c0dc8d10cf6044ec7fd4fd Mon Sep 17 00:00:00 2001 From: sphere Date: Wed, 16 Jun 2021 16:12:38 +0200 Subject: [PATCH 194/241] Restore toggle for Robo-Hood to not jump away from nearby players. --- extras/conf/SRB2-22.cfg | 1 + src/p_enemy.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 5a464eb5d..f457fe972 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -3589,6 +3589,7 @@ thingtypes sprite = "ARCHA1"; width = 24; height = 32; + flags8text = "[8] Don't jump away"; } 118 { diff --git a/src/p_enemy.c b/src/p_enemy.c index 9a9edb5e3..def3a87f5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1709,7 +1709,7 @@ void A_HoodThink(mobj_t *actor) dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z); dm = P_AproxDistance(dx, dy); // Target dangerously close to robohood, retreat then. - if ((dm < 256<flags2 & MF2_AMBUSH)) { S_StartSound(actor, actor->info->attacksound); P_SetMobjState(actor, actor->info->raisestate); From 3a044e71cc7cf6c80d9836189511c1a58c108370 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 16 Jun 2021 15:34:58 -0700 Subject: [PATCH 195/241] Disable EXE disassembly and compression by default NOOBJDUMP=1 and NOUPX=1 have been removed. Make 'dump' target to disassemble. UPX=upx to compress executable. Setting UPX used to cause it to fail. That has been fixed. --- src/Makefile | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index 0c44afe55..6ec009044 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,6 +15,7 @@ # cleandep - remove dependency files for this build # distclean - remove entire executable, object and # dependency file directory structure. +# dump - disassemble executable # info - print settings # # This Makefile can automatically detect the host system @@ -83,8 +84,8 @@ # STATIC=1 - Use static linking. # DISTCC=1 # CCACHE=1 -# NOOBJDUMP=1 - Don't disassemble executable. -# NOUPX=1 - Don't compress executable. +# UPX= - UPX command to use for compressing final +# executable. # WINDOWSHELL=1 - Use Windows commands. # PREFIX= - Prefix to many commands, for cross compiling. # YASM=1 - Use Yasm instead of NASM assembler. @@ -165,7 +166,6 @@ ifdef WINDOWSHELL GZIP_OPTS+=--rsyncable endif -UPX?=upx UPX_OPTS?=--best --preserve-build-id ifndef ECHO UPX_OPTS+=-qq @@ -242,9 +242,7 @@ all : $(exe) $(call Echo,$(build_done)) ifndef VALGRIND -ifndef NOOBJDUMP -all : $(dbg).txt -endif +dump : $(dbg).txt endif ifdef STATIC @@ -310,7 +308,9 @@ LD:=$(CC) CC:=$(CC) $(CFLAGS) NASM:=$(NASM) $(NASMOPTS) -f $(nasm_format) GZIP:=$(GZIP) $(GZIP_OPTS) +ifdef UPX UPX:=$(UPX) $(UPX_OPTS) +endif WINDRES:=$(WINDRES) $(WINDRESFLAGS)\ $(debug_opts) --include-dir=win32 -O coff @@ -321,11 +321,14 @@ WINDRES:=$(WINDRES) $(WINDRESFLAGS)\ # prerequisites .SECONDEXPANSION : +# 'UPX' is also recognized in the enviornment by upx +unexport UPX + # executable stripped of debugging symbols $(exe) : $(dbg) | $$(@D)/ $(.)$(OBJCOPY) --strip-debug $< $@ $(.)-$(OBJCOPY) --add-gnu-debuglink=$< $@ -ifndef NOUPX +ifdef UPX $(call Echo,Compressing final executable...) $(.)-$(UPX) $@ endif From c142b3241ddb8f1ea9b5090d20dffa43a17129ab Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 16 Jun 2021 15:48:16 -0700 Subject: [PATCH 196/241] Makefile: alert full path of final executable With added textual contrast. --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 6ec009044..6d2d68477 100644 --- a/src/Makefile +++ b/src/Makefile @@ -236,7 +236,8 @@ DBGNAME?=$(EXENAME).debug exe:=$(bin)/$(EXENAME) dbg:=$(bin)/$(DBGNAME) -build_done=Build is done, please look for $( Date: Wed, 16 Jun 2021 15:57:08 -0700 Subject: [PATCH 197/241] Add a proxy Makefile at top level --- Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..7ee12d837 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +ifdef SILENT +MAKEFLAGS+=--no-print-directory +endif + +all : + +% :: + @$(MAKE) -C src $(MAKECMDGOALS) From b04c79d8a7ba4ae8f888ab94d394b6714699e107 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 16 Jun 2021 16:58:47 -0700 Subject: [PATCH 198/241] Say 'at' --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 6d2d68477..18ab524b8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -237,7 +237,7 @@ exe:=$(bin)/$(EXENAME) dbg:=$(bin)/$(DBGNAME) build_done==== Build is done, look for \ - $( Date: Sat, 19 Jun 2021 18:32:56 -0700 Subject: [PATCH 199/241] Fix basic warnings --- src/lua_inputlib.c | 2 +- src/sdl/i_video.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c index 217202222..71eb1033f 100644 --- a/src/lua_inputlib.c +++ b/src/lua_inputlib.c @@ -117,7 +117,7 @@ static int lib_setMouseGrab(lua_State *L) return 0; } -static boolean lib_getCursorPosition(lua_State *L) +static int lib_getCursorPosition(lua_State *L) { int x, y; I_GetCursorPosition(&x, &y); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index c387e5a18..234585cf3 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -407,7 +407,7 @@ void I_UpdateMouseGrab(void) boolean I_GetMouseGrab(void) { - return SDL_GetWindowGrab(window); + return (boolean)SDL_GetWindowGrab(window); } void I_SetMouseGrab(boolean grab) From 2d7a8c3c571bcc5335437e9db074c75af00408ce Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 21 Jun 2021 14:47:42 -0700 Subject: [PATCH 200/241] Makefile: use shell commands to read in Sourcefile File function is not supported < Make 4.2. --- src/Makefile | 11 ++++++----- src/Makefile.d/platform.mk | 2 ++ src/Makefile.d/util.mk | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Makefile b/src/Makefile index 18ab524b8..7104a91cf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -176,11 +176,7 @@ include Makefile.d/detect.mk # make would try to remove the implicitly made directories .PRECIOUS : %/ comptime.c -# very sophisticated dependency -sources:=\ - $(call List,Sourcefile)\ - $(call List,blua/Sourcefile)\ - +sources:= makedir:=../make # -DCOMPVERSION: flag to use comptime.h @@ -204,6 +200,11 @@ endif depdir:=$(makedir)/deps objdir:=$(makedir)/objs +# very sophisticated dependency +sources+=\ + $(call List,Sourcefile)\ + $(call List,blua/Sourcefile)\ + depends:=$(basename $(filter %.c %.s,$(sources))) objects:=$(basename $(filter %.c %.s %.nas,$(sources))) diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk index 531d073e9..fad4be191 100644 --- a/src/Makefile.d/platform.mk +++ b/src/Makefile.d/platform.mk @@ -7,9 +7,11 @@ PKG_CONFIG?=pkg-config ifdef WINDOWSHELL rmrf=-2>NUL DEL /S /Q mkdir=-2>NUL MD +cat=TYPE else rmrf=rm -rf mkdir=mkdir -p +cat=cat endif ifdef LINUX64 diff --git a/src/Makefile.d/util.mk b/src/Makefile.d/util.mk index e76e32422..bda68df13 100644 --- a/src/Makefile.d/util.mk +++ b/src/Makefile.d/util.mk @@ -10,7 +10,8 @@ Wildvar=$(foreach v,$(filter $(1),$(.VARIABLES)),$($(v))) # Read a list of words from file and prepend each with the # directory of the file. -List=$(addprefix $(dir $(1)),$(file < $(1))) +_cat=$(shell $(cat) $(call Windows_path,$(1))) +List=$(addprefix $(dir $(1)),$(call _cat,$(1))) # Convert path separators to backslash on Windows. Windows_path=$(if $(WINDOWSHELL),$(subst /,\,$(1)),$(1)) From d5146945a69ebf30e6fc1fbb64558e456e0b7459 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 21 Jun 2021 16:10:13 -0700 Subject: [PATCH 201/241] Makefile: don't automatically set WINDOWSHELL unless PATH matches Windows norms This is for MSYS2, which requires unix shell commands. --- src/Makefile.d/detect.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk index f576bcf78..89c193a32 100644 --- a/src/Makefile.d/detect.mk +++ b/src/Makefile.d/detect.mk @@ -29,7 +29,10 @@ $(call Print,$(_m)) # go for a 32-bit sdl mingw exe by default MINGW:=1 +# cmd.exe uses native Windows semicolon delimited PATH +ifneq (,$(findstring ;,$(PATH))) WINDOWSHELL:=1 +endif else # if you on the *nix From 5f4d7e3c5b013afe03ae2a441c82ad79bae7c66c Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 22 Jun 2021 15:14:42 -0700 Subject: [PATCH 202/241] Makefile: fail if old build directories exist After a checkout from before revision, old directories such as bin/Linux64 only remain if untracked files exist within. This may be confusing to the user. They may even use an outdated executable if it is one of those untracked files. --- src/Makefile | 6 +++++- src/Makefile.d/old.mk | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/Makefile.d/old.mk diff --git a/src/Makefile b/src/Makefile index 7104a91cf..61a4c5e34 100644 --- a/src/Makefile +++ b/src/Makefile @@ -132,6 +132,10 @@ goals:=$(or $(MAKECMDGOALS),all) cleanonly:=$(filter $(clean_targets),$(goals)) destructive:=$(filter-out info,$(cleanonly)) +ifndef cleanonly +include Makefile.d/old.mk +endif + include Makefile.d/util.mk ifdef PREFIX @@ -399,7 +403,7 @@ clean : $(call _rm,$(exe) $(dbg) $(dbg).txt $(objects)) distclean : - $(call _rm,../bin ../objs ../deps comptime.h) + $(call _rm,../bin ../objs ../deps ../make comptime.h) info: ifdef WINDOWSHELL diff --git a/src/Makefile.d/old.mk b/src/Makefile.d/old.mk new file mode 100644 index 000000000..e5890eedd --- /dev/null +++ b/src/Makefile.d/old.mk @@ -0,0 +1,16 @@ +# +# Warn about old build directories and offer to purge. +# + +_old:=$(wildcard $(addprefix ../bin/,FreeBSD Linux \ + Linux64 Mingw Mingw64 SDL dummy) ../objs ../deps) + +ifdef _old +$(foreach v,$(_old),$(info $(abspath $(v)))) +$(info ) +$(info These directories are no longer\ + required and should be removed.) +$(info You may remove them manually or\ + by using 'make distclean') +$(error ) +endif From c3ad5de912fccfdd64c510f5684883afceaa7d36 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 22 Jun 2021 15:47:48 -0700 Subject: [PATCH 203/241] Makefile: let variables be defined on Make line If a variable is defined as in 'make CC=gcc-10', then that definition overrides anything other definition in the Makefile. --- src/Makefile | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/Makefile b/src/Makefile index 61a4c5e34..90776b812 100644 --- a/src/Makefile +++ b/src/Makefile @@ -145,7 +145,7 @@ endif OBJDUMP_OPTS?=--wide --source --line-numbers OBJCOPY:=$(call Prefix,objcopy) -OBJDUMP:=$(call Prefix,objdump) $(OBJDUMP_OPTS) +OBJDUMP:=$(call Prefix,objdump) WINDRES:=$(call Prefix,windres) ifdef YASM @@ -273,16 +273,18 @@ opts+=$(debug_opts) opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v))) -CFLAGS:=$(opts) $(WFLAGS) $(CPPFLAGS) $(CFLAGS) -LDFLAGS:=$(libs) $(LDFLAGS) -ASFLAGS+=-x assembler-with-cpp +opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS) +libs+=$(LDFLAGS) +asflags:=$(ASFLAGS) -x assembler-with-cpp + +cc=$(CC) ifdef DISTCC -CC:=distcc $(CC) +cc=distcc $(CC) endif ifdef CCACHE -CC:=ccache $(CC) +cc=ccache $(CC) endif ifndef SILENT @@ -293,11 +295,11 @@ ifndef destructive $(shell $(CC) -v) define flags = -CC ........ $(CC) +CC ........ $(cc) -CFLAGS .... $(CFLAGS) +CFLAGS .... $(opts) -LDFLAGS ... $(LDFLAGS) +LDFLAGS ... $(libs) endef $(info $(flags)) @@ -311,13 +313,12 @@ endif endif LD:=$(CC) -CC:=$(CC) $(CFLAGS) -NASM:=$(NASM) $(NASMOPTS) -f $(nasm_format) -GZIP:=$(GZIP) $(GZIP_OPTS) +cc:=$(cc) $(opts) +nasm=$(NASM) $(NASMOPTS) -f $(nasm_format) ifdef UPX -UPX:=$(UPX) $(UPX_OPTS) +upx=$(UPX) $(UPX_OPTS) endif -WINDRES:=$(WINDRES) $(WINDRESFLAGS)\ +windres=$(WINDRES) $(WINDRESFLAGS)\ $(debug_opts) --include-dir=win32 -O coff %/ : @@ -327,7 +328,7 @@ WINDRES:=$(WINDRES) $(WINDRESFLAGS)\ # prerequisites .SECONDEXPANSION : -# 'UPX' is also recognized in the enviornment by upx +# 'UPX' is also recognized in the environment by upx unexport UPX # executable stripped of debugging symbols @@ -336,19 +337,19 @@ $(exe) : $(dbg) | $$(@D)/ $(.)-$(OBJCOPY) --add-gnu-debuglink=$< $@ ifdef UPX $(call Echo,Compressing final executable...) - $(.)-$(UPX) $@ + $(.)-$(upx) $@ endif # original executable with debugging symbols $(dbg) : $(objects) | $$(@D)/ $(call Echo,Linking $(@F)...) - $(.)$(LD) -o $@ $^ $(LDFLAGS) + $(.)$(LD) -o $@ $^ $(libs) # disassembly of executable $(dbg).txt : $(dbg) $(call Echo,Dumping debugging info...) - $(.)$(OBJDUMP) $< > $@ - $(.)$(GZIP) $@ + $(.)$(OBJDUMP) $(OBJDUMP_OPTS) $< > $@ + $(.)$(GZIP) $(GZIP_OPTS) $@ # '::' means run unconditionally # this really updates comptime.h @@ -373,11 +374,11 @@ ifdef Echo_name @printf '%-20.20s\r' $$< endif endif - $(.)$(CC) -MM -MF $$@ -MT $(objdir)/$$(*F).o $(2) $$< + $(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$(*F).o $(2) $$< endef $(eval $(call _recipe,c)) -$(eval $(call _recipe,s,$(ASFLAGS))) +$(eval $(call _recipe,s,$(asflags))) # compiling recipe template # 1: target file suffix @@ -389,10 +390,10 @@ $(objdir)/%.$(1) : %.$(2) | $$$$(@D)/ $(.)$(3) endef -$(eval $(call _recipe,o,c,$(CC) -c -o $$@ $$<)) -$(eval $(call _recipe,o,nas,$(NASM) -o $$@ $$<)) -$(eval $(call _recipe,o,s,$(CC) $(ASFLAGS) -c -o $$@ $$<)) -$(eval $(call _recipe,res,rc,$(WINDRES) -i $$< -o $$@)) +$(eval $(call _recipe,o,c,$(cc) -c -o $$@ $$<)) +$(eval $(call _recipe,o,nas,$(nasm) -o $$@ $$<)) +$(eval $(call _recipe,o,s,$(cc) $(asflags) -c -o $$@ $$<)) +$(eval $(call _recipe,res,rc,$(windres) -i $$< -o $$@)) _rm=$(.)$(rmrf) $(call Windows_path,$(1)) From ed85e994a46ace07cf022b38a9abac1698a8667e Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 22 Jun 2021 15:49:59 -0700 Subject: [PATCH 204/241] Remove misplaced parentheses --- src/Makefile.d/detect.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk index 89c193a32..3edf0dad4 100644 --- a/src/Makefile.d/detect.mk +++ b/src/Makefile.d/detect.mk @@ -94,7 +94,7 @@ ifeq (,$(filter $(v),$(gcc_versions))) define line = Your compiler version, GCC $(version), \ is not supported by the Makefile. -The Makefile will assume GCC $(latest_gcc_version).)) +The Makefile will assume GCC $(latest_gcc_version). endef $(call Print,$(line)) GCC$(subst .,,$(latest_gcc_version)):=1 From 90763d42e1352efb03a81fee3c53de7fcd9d0d3e Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 01:49:09 -0700 Subject: [PATCH 205/241] Shuffle LUA_HookKey --- src/lua_hook.h | 2 +- src/lua_hooklib.c | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lua_hook.h b/src/lua_hook.h index e3af951f5..223b83c61 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -107,6 +107,7 @@ void LUA_HookInt(INT32 integer, int hook); void LUA_HookBool(boolean value, int hook); int LUA_HookPlayer(player_t *, int hook); int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook); +int LUA_HookKey(INT32 keycode, int hook); // Hooks for key events void LUA_HookThinkFrame(void); int LUA_HookMobjLineCollide(mobj_t *, line_t *); @@ -130,4 +131,3 @@ int LUA_HookPlayerCmd(player_t *, ticcmd_t *); int LUA_HookMusicChange(const char *oldname, struct MusicChange *); fixed_t LUA_HookPlayerHeight(player_t *player); int LUA_HookPlayerCanEnterSpinGaps(player_t *player); -int LUA_HookKey(INT32 keycode, int hooktype); // Hooks for key events diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 39aa5ea18..6c709bf48 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -588,6 +588,17 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type) return hook.status; } +int LUA_HookKey(INT32 keycode, int hook_type) +{ + Hook_State hook; + if (prepare_hook(&hook, false, hook_type)) + { + lua_pushinteger(gL, keycode); + call_hooks(&hook, 1, 0, res_true); + } + return hook.status; +} + /* ========================================================================= SPECIALIZED HOOKS ========================================================================= */ @@ -1088,14 +1099,3 @@ int LUA_HookPlayerCanEnterSpinGaps(player_t *player) } return hook.status; } - -int LUA_HookKey(INT32 keycode, int hooktype) -{ - Hook_State hook; - if (prepare_hook(&hook, 0, hooktype)) - { - lua_pushinteger(gL, keycode); - call_hooks(&hook, 1, 0, res_true); - } - return hook.status; -} From 7d01bd38d8dc7fc6744d20c3376e38ccdf480d9a Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 01:49:53 -0700 Subject: [PATCH 206/241] Fix return value of Lua key hooks not being used --- src/lua_hooklib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 6c709bf48..d1b0d3bdd 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -594,7 +594,7 @@ int LUA_HookKey(INT32 keycode, int hook_type) if (prepare_hook(&hook, false, hook_type)) { lua_pushinteger(gL, keycode); - call_hooks(&hook, 1, 0, res_true); + call_hooks(&hook, 1, 1, res_true); } return hook.status; } From c1ecfa306f6a0b168d4f6cbc3224ebebd4deec51 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 13:58:38 -0700 Subject: [PATCH 207/241] Makefile: 'dep' not 'deps' --- src/Makefile.d/old.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.d/old.mk b/src/Makefile.d/old.mk index e5890eedd..ec9b6d776 100644 --- a/src/Makefile.d/old.mk +++ b/src/Makefile.d/old.mk @@ -3,7 +3,7 @@ # _old:=$(wildcard $(addprefix ../bin/,FreeBSD Linux \ - Linux64 Mingw Mingw64 SDL dummy) ../objs ../deps) + Linux64 Mingw Mingw64 SDL dummy) ../objs ../dep) ifdef _old $(foreach v,$(_old),$(info $(abspath $(v)))) From c3fa9bea0fd6a426e448d4ecb8240a75593ecd50 Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Tue, 29 Jun 2021 13:30:10 -0700 Subject: [PATCH 208/241] ri# mified: src/tazx# mofied: src/tazx# modified: src/tazx# modified: src/tazxc --- src/g_game.c | 5 +---- src/r_skins.c | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 83531bb35..9f2d05ff0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2317,16 +2317,13 @@ void G_Ticker(boolean run) P_ForceLocalAngle(&players[i], players[i].angleturn << 16); else players[i].cmd.angleturn = players[i].angleturn; - players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn; - players[i].oldrelangleturn = players[i].cmd.angleturn; if (P_ControlStyle(&players[i]) == CS_LMAOGALOG) P_ForceLocalAngle(&players[i], players[i].angleturn << 16); else players[i].cmd.angleturn = players[i].angleturn; players[i].cmd.angleturn &= ~TICCMD_RECEIVED; - - // Use the leveltime sent in the player's ticcmd to determine control lag + // Use the leveltime sent in the player's ticcmd to determine control lag players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1); } else // Less work is required if we're building a bot ticcmd. diff --git a/src/r_skins.c b/src/r_skins.c index f67f2afd4..c734b6001 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -286,7 +286,6 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) // We want to check our global unlockables. return (unlockables[unlockID].unlocked); } ->>>>>>> src/r_skins.c } // returns true if the skin name is found (loaded from pwad) From 6c03f9b5b3590e01773f05bc1c31cc67a2d88fc2 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 14:42:40 -0700 Subject: [PATCH 209/241] fuck --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 90776b812..8bb7b54ef 100644 --- a/src/Makefile +++ b/src/Makefile @@ -404,7 +404,7 @@ clean : $(call _rm,$(exe) $(dbg) $(dbg).txt $(objects)) distclean : - $(call _rm,../bin ../objs ../deps ../make comptime.h) + $(call _rm,../bin ../objs ../dep ../make comptime.h) info: ifdef WINDOWSHELL From abdf5c101cbe80657f210c0b90800e2c4c6f0c05 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 16:22:46 -0700 Subject: [PATCH 210/241] Makefile: report SHELL --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile b/src/Makefile index 8bb7b54ef..ce0e84987 100644 --- a/src/Makefile +++ b/src/Makefile @@ -295,6 +295,8 @@ ifndef destructive $(shell $(CC) -v) define flags = +SHELL ..... $(SHELL) + CC ........ $(cc) CFLAGS .... $(opts) From 22ab611daa17bd23225f3afeeba39147c0d0fe17 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 16:23:27 -0700 Subject: [PATCH 211/241] Makefile: do not automatically set WINDOWSHELL According to this answer-- https://stackoverflow.com/a/45952425 --Make will always prefer a unix shell, even on Windows, if one can be found in Path. So we can't check PATH to determine if it's a Windows shell... this is just too much bother. --- src/Makefile.d/detect.mk | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk index 3edf0dad4..9c8a0a227 100644 --- a/src/Makefile.d/detect.mk +++ b/src/Makefile.d/detect.mk @@ -29,10 +29,6 @@ $(call Print,$(_m)) # go for a 32-bit sdl mingw exe by default MINGW:=1 -# cmd.exe uses native Windows semicolon delimited PATH -ifneq (,$(findstring ;,$(PATH))) -WINDOWSHELL:=1 -endif else # if you on the *nix From f79e0ee540564fcec5da7c0dc4006906492a7f30 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 14:33:55 -0700 Subject: [PATCH 212/241] Appveyor: remove 64-bit target --- appveyor.yml | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d5f76c344..a74d3c415 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,12 +4,9 @@ os: MinGW environment: CC: ccache CCACHE_CC: i686-w64-mingw32-gcc - CCACHE_CC_64: x86_64-w64-mingw32-gcc WINDRES: windres # c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead MINGW_SDK: c:\msys64\mingw32 - # c:\msys64 x86_64 has gcc 8.2.0, so use c:\mingw-w64 7.3.0 instead - MINGW_SDK_64: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64 CFLAGS: -Wall -W -Werror -Wno-error=implicit-fallthrough -Wimplicit-fallthrough=3 -Wno-tautological-compare -Wno-error=suggest-attribute=noreturn NASM_ZIP: nasm-2.12.01 NASM_URL: http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip @@ -53,11 +50,6 @@ cache: - C:\Users\appveyor\srb2_cache install: -- if [%CONFIGURATION%] == [SDL64] ( set "X86_64=1" ) -- if [%CONFIGURATION%] == [SDL64] ( set "CONFIGURATION=SDL" ) -- if [%X86_64%] == [1] ( set "MINGW_SDK=%MINGW_SDK_64%" ) -- if [%X86_64%] == [1] ( set "CCACHE_CC=%CCACHE_CC_64%" ) - - if not exist "%NASM_ZIP%.zip" appveyor DownloadFile "%NASM_URL%" -FileName "%NASM_ZIP%.zip" - 7z x -y "%NASM_ZIP%.zip" -o%TMP% >null - robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%NASM_ZIP%" "%MINGW_SDK%\bin" nasm.exe || exit 0 @@ -72,13 +64,12 @@ install: configuration: - SDL -- SDL64 before_build: - set "Path=%MINGW_SDK%\bin;%Path%" -- if [%X86_64%] == [1] ( x86_64-w64-mingw32-gcc --version ) else ( i686-w64-mingw32-gcc --version ) +- i686-w64-mingw32-gcc --version - mingw32-make --version -- if not [%X86_64%] == [1] ( nasm -v ) +- nasm -v - if not [%NOUPX%] == [1] ( upx -V ) - ccache -V - ccache -s @@ -91,7 +82,7 @@ before_build: - if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [] ( if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [%APPVEYOR_REPO_NAME%] ( for /f "delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set "REPO=%%a-%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%" ) ) - set "EXENAME=EXENAME=srb2win-%REPO%-%GITSHORT%.exe" - set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 NOOBJDUMP=1 %NOUPX% %EXENAME%" -- if [%X86_64%] == [1] ( set "MINGW_FLAGS=MINGW64=1 X86_64=1 GCC81=1" ) else ( set "MINGW_FLAGS=MINGW=1 GCC91=1" ) +- set "MINGW_FLAGS=MINGW=1 GCC91=1" - set "SRB2_MFLAGS=%SRB2_MFLAGS% %MINGW_FLAGS% %CONFIGURATION%=1" build_script: @@ -99,7 +90,6 @@ build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% ERRORMODE=1 -k after_build: -- if [%X86_64%] == [1] ( set "CONFIGURATION=%CONFIGURATION%64" ) - ccache -s - set BUILD_ARCHIVE=%REPO%-%GITSHORT%-%CONFIGURATION%.7z - set BUILDSARCHIVE=%REPO%-%CONFIGURATION%.7z @@ -134,3 +124,4 @@ test: off on_finish: #- cmd: echo xfreerdp /u:appveyor /cert-ignore +clipboard /v:: #- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +# vim: et ts=1 From faee657572f23cd6f8b68c077873e01c4278414e Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 14:55:06 -0700 Subject: [PATCH 213/241] Appveyor: update for new Makefile --- appveyor.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a74d3c415..26a1e2a9b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,8 +2,7 @@ version: 2.2.9.{branch}-{build} os: MinGW environment: - CC: ccache - CCACHE_CC: i686-w64-mingw32-gcc + CC: i686-w64-mingw32-gcc WINDRES: windres # c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead MINGW_SDK: c:\msys64\mingw32 @@ -16,8 +15,6 @@ environment: CCACHE_URL: http://alam.srb2.org/ccache.exe CCACHE_COMPRESS: true CCACHE_DIR: C:\Users\appveyor\.ccache - # Disable UPX by default. The user can override this in their Appveyor project settings - NOUPX: 1 ############################## # DEPLOYER VARIABLES # DPL_ENABLED=1 builds installers for branch names starting with `deployer`. @@ -67,23 +64,18 @@ configuration: before_build: - set "Path=%MINGW_SDK%\bin;%Path%" -- i686-w64-mingw32-gcc --version - mingw32-make --version - nasm -v - if not [%NOUPX%] == [1] ( upx -V ) - ccache -V - ccache -s -- if [%NOUPX%] == [1] ( set "NOUPX=NOUPX=1" ) else ( set "NOUPX=" ) - if defined [%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%] ( set "COMMIT=%APPVEYOR_PULL_REQUEST_HEAD_COMMIT%" ) else ( set "COMMIT=%APPVEYOR_REPO_COMMIT%" ) - cmd: git rev-parse --short %COMMIT%>%TMP%/gitshort.txt - cmd: set /P GITSHORT=<%TMP%/gitshort.txt # for pull requests, take the owner's name only, if this isn't the same repo of course - set "REPO=%APPVEYOR_REPO_BRANCH%" - if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [] ( if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [%APPVEYOR_REPO_NAME%] ( for /f "delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set "REPO=%%a-%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%" ) ) -- set "EXENAME=EXENAME=srb2win-%REPO%-%GITSHORT%.exe" -- set "SRB2_MFLAGS=-C src WARNINGMODE=1 CCACHE=1 NOOBJDUMP=1 %NOUPX% %EXENAME%" -- set "MINGW_FLAGS=MINGW=1 GCC91=1" -- set "SRB2_MFLAGS=%SRB2_MFLAGS% %MINGW_FLAGS% %CONFIGURATION%=1" +- set "SRB2_MFLAGS=-C src CCACHE=1 EXENAME=srb2win-%REPO%-%GITSHORT%.exe" build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% clean From 44b82dea58612e6f07830647e2b08555f54a7caa Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 19:55:14 -0700 Subject: [PATCH 214/241] Appveyor: remove redundant CFLAGS Also changed -Wno-error=implicit-fallthrough to -Wno-implicit-fallthrough. For some reason Appveyor's version of GCC is triggering these warnings despite the comments, so just shut it up. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 26a1e2a9b..962444a18 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ environment: WINDRES: windres # c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead MINGW_SDK: c:\msys64\mingw32 - CFLAGS: -Wall -W -Werror -Wno-error=implicit-fallthrough -Wimplicit-fallthrough=3 -Wno-tautological-compare -Wno-error=suggest-attribute=noreturn + CFLAGS: -Wno-implicit-fallthrough NASM_ZIP: nasm-2.12.01 NASM_URL: http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip UPX_ZIP: upx391w From db919accd22350c087c1fd0e5122d8e490e2f171 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 29 Jun 2021 20:01:14 -0700 Subject: [PATCH 215/241] Appveyor: suppress real time file names --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 962444a18..b9f84f395 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -75,7 +75,7 @@ before_build: # for pull requests, take the owner's name only, if this isn't the same repo of course - set "REPO=%APPVEYOR_REPO_BRANCH%" - if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [] ( if not [%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%] == [%APPVEYOR_REPO_NAME%] ( for /f "delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set "REPO=%%a-%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%" ) ) -- set "SRB2_MFLAGS=-C src CCACHE=1 EXENAME=srb2win-%REPO%-%GITSHORT%.exe" +- set "SRB2_MFLAGS=-C src NOECHOFILENAMES=1 CCACHE=1 EXENAME=srb2win-%REPO%-%GITSHORT%.exe" build_script: - cmd: mingw32-make.exe %SRB2_MFLAGS% clean From dad361721fa3c1f572ba5d40ae5af0884258fb17 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Wed, 30 Jun 2021 01:32:24 -0400 Subject: [PATCH 216/241] comment cleanup --- src/p_user.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index dadc23193..7ab7d8105 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -776,7 +776,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) { UINT8 oldmare, oldmarelap, oldmarebonuslap; - //! Bots can't be NiGHTSerized, silly!1 :P + // Bots can't be NiGHTSerized, silly!1 :P if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) return; @@ -1188,7 +1188,6 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) { if (!player) return; - //! if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) player = player->botleader; @@ -5965,23 +5964,6 @@ static void P_3dMovement(player_t *player) acceleration = 96 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * 40; topspeed = normalspd; } - //! Kill this! - /* else if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) - { // Bot steals player 1's stats - normalspd = FixedMul(players[consoleplayer].normalspeed, player->mo->scale); - thrustfactor = players[consoleplayer].thrustfactor; - acceleration = players[consoleplayer].accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * players[consoleplayer].acceleration; - - if (player->powers[pw_tailsfly]) - topspeed = normalspd/2; - else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER)) - { - topspeed = normalspd/2; - acceleration = 2*acceleration/3; - } - else - topspeed = normalspd; - } */ else { if (player->powers[pw_super] || player->powers[pw_sneakers]) @@ -11488,7 +11470,7 @@ void P_PlayerThink(player_t *player) I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri)); #endif - //! Reset terrain blocked status for this frame + // Reset terrain blocked status for this frame player->blocked = false; // todo: Figure out what is actually causing these problems in the first place... @@ -11641,7 +11623,7 @@ void P_PlayerThink(player_t *player) INT32 i; for (i = 0; i < MAXPLAYERS; i++) - { //! + { if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (players[i].lives <= 0) @@ -11673,7 +11655,7 @@ void P_PlayerThink(player_t *player) INT32 i, total = 0, exiting = 0; for (i = 0; i < MAXPLAYERS; i++) - { //! + { if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (players[i].quittime > 30 * TICRATE) @@ -12614,7 +12596,6 @@ void P_PlayerAfterThink(player_t *player) player->mo->momy = tails->momy; player->mo->momz = tails->momz; } - //! if (G_CoopGametype() && tails->player && tails->player->bot != BOT_2PAI) { player->mo->angle = tails->angle; From ee765d1043893bb798cdd84cf22d3383812812e6 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Wed, 30 Jun 2021 01:34:21 -0400 Subject: [PATCH 217/241] comment cleanup --- 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 0643350b6..6e900d026 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3005,7 +3005,7 @@ void G_DoReborn(INT32 playernum) // Make sure objectplace is OFF when you first start the level! OP_ResetObjectplace(); - //! Tailsbot + // Tailsbot if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) { // Bots respawn next to their master. mobj_t *oldmo = NULL; From 94441d6eee252c3ebc7cd438c32d3d15dbb3c012 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Wed, 30 Jun 2021 01:36:28 -0400 Subject: [PATCH 218/241] comment cleanup --- src/b_bot.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index c61e56f5f..cdd74fc07 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -25,8 +25,6 @@ void B_UpdateBotleader(player_t *player) fixed_t neardist = INT32_MAX; player_t *nearplayer = NULL; //Find new botleader - //if (!player->botleader) - //{ for (i = 0; i < MAXPLAYERS; i++) { if (players[i].bot || players[i].playerstate != PST_LIVE || players[i].spectator || !players[i].mo) @@ -46,7 +44,6 @@ void B_UpdateBotleader(player_t *player) } //Set botleader to best candidate (or null if none available) player->botleader = nearplayer; - //} } static inline void B_ResetAI(botmem_t *mem) @@ -102,7 +99,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC) { boolean isrelevant = (sonic->player->powers[pw_carry] == CR_MACESPIN || sonic->player->powers[pw_carry] == CR_GENERIC); - //dist = P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y); //! This is totally redundant. if (sonic->player->cmd.buttons & BT_JUMP && (sonic->player->pflags & PF_JUMPED) && isrelevant) cmd->buttons |= BT_JUMP; if (isrelevant) @@ -402,8 +398,6 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward { player_t *player = mo->player; // don't try to do stuff if your sonic is in a minecart or something - //if (players[consoleplayer].powers[pw_carry] && players[consoleplayer].powers[pw_carry] != CR_PLAYER) - //!!! if (&player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER) return; // Turn the virtual keypresses into ticcmd_t. @@ -576,7 +570,6 @@ void B_RespawnBot(INT32 playernum) player->powers[pw_spacetime] = sonic->player->powers[pw_spacetime]; player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots]; player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol]; - //!!! Nuke the speed equivalencies player->pflags |= PF_AUTOBRAKE|(sonic->player->pflags & PF_DIRECTIONCHAR); P_TeleportMove(tails, x, y, z); From afa8466b304207f15367c30352da5af7e1ede59f Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Wed, 30 Jun 2021 01:38:04 -0400 Subject: [PATCH 219/241] comment cleanup --- src/p_mobj.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 4924ec053..8af7ab0d0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1839,7 +1839,6 @@ void P_XYMovement(mobj_t *mo) // blocked move moved = false; - //!!! if (player) B_MoveBlocked(player); From 18cbc1e37047f2fabf61e32a4bc2997125ad21b4 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 5 Jul 2021 18:31:04 -0700 Subject: [PATCH 220/241] Fix aliases bypass COM_SAFE --- src/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index 95b1fd67d..0e0b1a685 100644 --- a/src/command.c +++ b/src/command.c @@ -650,7 +650,7 @@ static void COM_ExecuteString(char *ptext) else { // Monster Iestyn: keep track of how many levels of recursion we're in recursion++; - COM_BufInsertText(a->value); + COM_BufInsertTextEx(a->value, com_flags); recursion--; } return; From 14c5d2c916e42c926dcf8267df3b49bd3dcab31d Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 5 Jul 2021 18:39:12 -0700 Subject: [PATCH 221/241] Warn if Lua attempted access NOLUA consvar And quote variable name. --- src/command.c | 5 ++++- src/lua_consolelib.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/command.c b/src/command.c index 0e0b1a685..e6c6587e8 100644 --- a/src/command.c +++ b/src/command.c @@ -2364,7 +2364,10 @@ static boolean CV_Command(void) return false; if (( com_flags & COM_SAFE ) && ( v->flags & CV_NOLUA )) - return false; + { + CONS_Alert(CONS_WARNING, "Variable '%s' cannot be changed from Lua.\n", v->name); + return true; + } // perform a variable print or set if (COM_Argc() == 1) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 414d9692a..2b8cad69b 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -433,7 +433,7 @@ static int CVarSetFunction consvar_t *cvar = *(consvar_t **)luaL_checkudata(L, 1, META_CVAR); if (cvar->flags & CV_NOLUA) - return luaL_error(L, "Variable %s cannot be set from Lua.", cvar->name); + return luaL_error(L, "Variable '%s' cannot be set from Lua.", cvar->name); switch (lua_type(L, 2)) { From e30d4f954b9ec90632484b31673b7fe6185481a5 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 8 Jul 2021 14:37:03 -0700 Subject: [PATCH 222/241] Revert netvars after demo finishes playback (Demos do not call CL_Reset BTW.) --- src/command.c | 4 +++- src/d_clisrv.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/command.c b/src/command.c index 95b1fd67d..da777310a 100644 --- a/src/command.c +++ b/src/command.c @@ -1738,6 +1738,8 @@ void CV_SaveVars(UINT8 **p, boolean in_demo) static void CV_LoadVars(UINT8 **p, consvar_t *(*got)(UINT8 **p, char **ret_value, boolean *ret_stealth)) { + const boolean store = (client || demoplayback); + consvar_t *cvar; UINT16 count; @@ -1751,7 +1753,7 @@ static void CV_LoadVars(UINT8 **p, { if (cvar->flags & CV_NETVAR) { - if (client && cvar->revert.v.string == NULL) + if (store && cvar->revert.v.string == NULL) { cvar->revert.v.const_munge = cvar->string; cvar->revert.allocated = ( cvar->zstring != NULL ); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1549811c1..1d895c0e1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2599,7 +2599,6 @@ void CL_Reset(void) doomcom->numslots = 1; SV_StopServer(); SV_ResetServer(); - CV_RevertNetVars(); // make sure we don't leave any fileneeded gunk over from a failed join fileneedednum = 0; @@ -3231,6 +3230,8 @@ void SV_ResetServer(void) // clear server_context memset(server_context, '-', 8); + CV_RevertNetVars(); + DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } From c337709d105696f91ed923371346326e11dd93ee Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 11 Jul 2021 16:32:36 -0400 Subject: [PATCH 223/241] Update f_finale.c --- src/f_finale.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index e8757c18a..4d9a8f825 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1166,7 +1166,6 @@ static const char *credits[] = { "Alexander \"DrTapeworm\" Moench-Ford", "Stefan \"Stuf\" Rimalia", "Shane Mychal Sexton", - "\"Spazzo\"", "David \"Big Wave Dave\" Spencer Sr.", "David \"Instant Sonic\" Spencer Jr.", "\"SSNTails\"", @@ -1191,7 +1190,6 @@ static const char *credits[] = { "\"Revan\"", "Anna \"QueenDelta\" Sandlin", "Wessel \"sphere\" Smit", - "\"Spazzo\"", "\"SSNTails\"", "Rob Tisdell", "\"Torgo\"", From 0faecf095987e4df5333a9d4fed6f06cd75bd9f0 Mon Sep 17 00:00:00 2001 From: SteelT Date: Sun, 11 Jul 2021 20:51:06 -0400 Subject: [PATCH 224/241] version.h: Update comment about contacting an MS admin --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 4470fbd6e..28fc71c36 100644 --- a/src/version.h +++ b/src/version.h @@ -1,6 +1,6 @@ #define SRB2VERSION "2.2.9"/* this must be the first line, for cmake !! */ -// The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/showgroups.php ). +// 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. // "18" is the default mod ID for version 2.2 #define MODID 18 From 58fa44e8dc0444eecbe701f31872fad9fa563a6a Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 12 Jul 2021 03:50:44 -0700 Subject: [PATCH 225/241] CMP0115 --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4c125c4b8..721cd6dca 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32) # Core sources target_sourcefile(c) -target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h) +target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h.in) set(SRB2_ASM_SOURCES vid_copy.s) From 33ae95bf134571967f3f9875e5b3efeb2a352127 Mon Sep 17 00:00:00 2001 From: Shane Ellis Date: Mon, 12 Jul 2021 23:38:52 -0400 Subject: [PATCH 226/241] G_RemovePlayer error handling --- src/lua_baselib.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9946a9fd3..34d1b1a94 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3482,15 +3482,16 @@ static int lib_gAddPlayer(lua_State *L) static int lib_gRemovePlayer(lua_State *L) { UINT8 pnum = -1; - //const char *kickreason = luaL_checkstring(L, 2); - if (!lua_isnoneornil(L, 1)) pnum = luaL_checkinteger(L, 1); - if (&players[pnum]) + else // No argument + return luaL_error(L, "argument #1 not given (expected number)"); + if (pnum >= MAXPLAYERS) // Out of range + return luaL_error(L, "playernum %d out of range (0 - %d)", pnum, MAXPLAYERS-1); + if (playeringame[pnum]) // Found player { - if (players[pnum].bot != BOT_NONE) + if (players[pnum].bot != BOT_NONE) // Can't remove clients. { -// CL_RemovePlayer(pnum, *kickreason); CL_RemovePlayer(pnum, pnum); if (netgame) { @@ -3503,9 +3504,11 @@ static int lib_gRemovePlayer(lua_State *L) lua_pushboolean(L, true); return 1; } + else + return luaL_error(L, "G_RemovePlayer can only be used on players with a bot value other than BOT_NONE."); } - lua_pushboolean(L, false); - return 1; + // Fell through. Invalid player + return LUA_ErrInvalid(L, "player_t"); } From aed86781fc2794bb50a8245cbd0f2e5ea455d5c4 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 13 Jul 2021 17:41:38 +0200 Subject: [PATCH 227/241] Bugfix - Fix sporadically occurring incorrect userdata types in Lua, caused by previously loaded userdata which didn't get invalidated in previous sessions. Invalidate userdata for line and mapthing args. Invalidate userdata for slopes and their normal, origin and direction vectors. --- src/lua_script.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/lua_script.c b/src/lua_script.c index 6faff8729..506a888ea 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -25,7 +25,7 @@ #include "byteptr.h" #include "p_saveg.h" #include "p_local.h" -#include "p_slopes.h" // for P_SlopeById +#include "p_slopes.h" // for P_SlopeById and slopelist #include "p_polyobj.h" // polyobj_t, PolyObjects #ifdef LUA_ALLOW_BYTECODE #include "d_netfil.h" // for LUA_DumpFile @@ -851,6 +851,7 @@ void LUA_InvalidateLevel(void) { LUA_InvalidateUserdata(&lines[i]); LUA_InvalidateUserdata(&lines[i].tags); + LUA_InvalidateUserdata(&lines[i].args); LUA_InvalidateUserdata(lines[i].sidenum); } for (i = 0; i < numsides; i++) @@ -863,6 +864,13 @@ void LUA_InvalidateLevel(void) LUA_InvalidateUserdata(&PolyObjects[i].vertices); LUA_InvalidateUserdata(&PolyObjects[i].lines); } + for (pslope_t *slope = slopelist; slope; slope = slope->next) + { + LUA_InvalidateUserdata(slope); + LUA_InvalidateUserdata(&slope->normal); + LUA_InvalidateUserdata(&slope->o); + LUA_InvalidateUserdata(&slope->d); + } #ifdef HAVE_LUA_SEGS for (i = 0; i < numsegs; i++) LUA_InvalidateUserdata(&segs[i]); @@ -885,6 +893,7 @@ void LUA_InvalidateMapthings(void) { LUA_InvalidateUserdata(&mapthings[i]); LUA_InvalidateUserdata(&mapthings[i].tags); + LUA_InvalidateUserdata(&mapthings[i].args); } } From 22dfa05c318b02bd77b9ee75990482b2d1378ad9 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 13 Jul 2021 17:44:28 +0200 Subject: [PATCH 228/241] Forgot the stringargs. --- src/lua_script.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 506a888ea..a7bd67456 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -852,6 +852,7 @@ void LUA_InvalidateLevel(void) LUA_InvalidateUserdata(&lines[i]); LUA_InvalidateUserdata(&lines[i].tags); LUA_InvalidateUserdata(&lines[i].args); + LUA_InvalidateUserdata(&lines[i].stringargs); LUA_InvalidateUserdata(lines[i].sidenum); } for (i = 0; i < numsides; i++) @@ -894,6 +895,7 @@ void LUA_InvalidateMapthings(void) LUA_InvalidateUserdata(&mapthings[i]); LUA_InvalidateUserdata(&mapthings[i].tags); LUA_InvalidateUserdata(&mapthings[i].args); + LUA_InvalidateUserdata(&mapthings[i].stringargs); } } From 3a49b9519dc0faefa8f6f88d1354ac235b29c6c1 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Tue, 13 Jul 2021 17:55:06 +0200 Subject: [PATCH 229/241] Remove &, since args and stringargs are arrays --- src/lua_script.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lua_script.c b/src/lua_script.c index a7bd67456..9eb1912b3 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -851,8 +851,8 @@ void LUA_InvalidateLevel(void) { LUA_InvalidateUserdata(&lines[i]); LUA_InvalidateUserdata(&lines[i].tags); - LUA_InvalidateUserdata(&lines[i].args); - LUA_InvalidateUserdata(&lines[i].stringargs); + LUA_InvalidateUserdata(lines[i].args); + LUA_InvalidateUserdata(lines[i].stringargs); LUA_InvalidateUserdata(lines[i].sidenum); } for (i = 0; i < numsides; i++) @@ -894,8 +894,8 @@ void LUA_InvalidateMapthings(void) { LUA_InvalidateUserdata(&mapthings[i]); LUA_InvalidateUserdata(&mapthings[i].tags); - LUA_InvalidateUserdata(&mapthings[i].args); - LUA_InvalidateUserdata(&mapthings[i].stringargs); + LUA_InvalidateUserdata(mapthings[i].args); + LUA_InvalidateUserdata(mapthings[i].stringargs); } } From 1c3a898bbbd5539f666b08d085692a356501f219 Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Thu, 15 Jul 2021 12:53:13 -0700 Subject: [PATCH 230/241] Fixed locked characters being visible in multiplayer select screen --- 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 c734b6001..86c0bbc54 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -242,7 +242,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) // Force 3. return true; } - if (players[playernum].bot) + if (playernum != -1 && players[playernum].bot) { //Force 4. return true; From 4486ff065af8d6ad3567043af16a58a300aff041 Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Thu, 15 Jul 2021 13:03:26 -0700 Subject: [PATCH 231/241] All remaining player->bot checks modified to rely on BOT_ constants --- src/p_inter.c | 54 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 7e43c46a8..21e3bfa3d 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -151,7 +151,7 @@ boolean P_CanPickupItem(player_t *player, boolean weapon) if (!player->mo || player->mo->health <= 0) return false; - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) { if (weapon) return false; @@ -178,7 +178,7 @@ void P_DoNightsScore(player_t *player) return; // Don't do any fancy shit for failures. dummymo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+player->mo->height/2, MT_NIGHTSCORE); - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) player = &players[consoleplayer]; if (G_IsSpecialStage(gamemap)) // Global link count? Maybe not a good idea... @@ -630,7 +630,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // ***************************** // // Special Stage Token case MT_TOKEN: - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; P_AddPlayerScore(player, 1000); @@ -670,7 +670,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Emerald Hunt case MT_EMERHUNT: - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; if (hunt1 == special) @@ -701,7 +701,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_EMERALD5: case MT_EMERALD6: case MT_EMERALD7: - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; if (special->threshold) @@ -738,7 +738,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Secret emblem thingy case MT_EMBLEM: { - if (demoplayback || (player->bot && player->bot != 3)) + if (demoplayback || (player->bot && player->bot != BOT_MPAI)) return; emblemlocations[special->health-1].collected = true; @@ -751,7 +751,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // CTF Flags case MT_REDFLAG: case MT_BLUEFLAG: - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; if (player->powers[pw_flashing] || player->tossdelay) return; @@ -826,7 +826,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { boolean spec = G_IsSpecialStage(gamemap); boolean cangiveemmy = false; - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; if (player->exiting) return; @@ -1072,7 +1072,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; case MT_EGGCAPSULE: - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; // make sure everything is as it should be, THEN take rings from players in special stages @@ -1164,7 +1164,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; case MT_NIGHTSSUPERLOOP: - if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) player->powers[pw_nights_superloop] = (UINT16)special->info->speed; @@ -1186,7 +1186,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSDRILLREFILL: - if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) player->drillmeter = special->info->speed; @@ -1208,7 +1208,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSHELPER: - if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1240,7 +1240,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSEXTRATIME: - if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1272,7 +1272,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSLINKFREEZE: - if ((player->bot && player->bot != 3) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1332,7 +1332,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) players[i].drillmeter += TICRATE/2; } - else if (player->bot && player->bot != 3) + else if (player->bot && player->bot != BOT_MPAI) players[consoleplayer].drillmeter += TICRATE/2; else player->drillmeter += TICRATE/2; @@ -1385,7 +1385,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) thinker_t *th; mobj_t *mo2; - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; // Initialize my junk @@ -1423,7 +1423,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; } case MT_FIREFLOWER: - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; S_StartSound(toucher, sfx_mario3); @@ -1685,7 +1685,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; // Only go in the mouth // Eaten by player! - if ((!player->bot || player->bot == 3) && (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)) + if ((!player->bot || player->bot == BOT_MPAI) && (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)) { player->powers[pw_underwater] = underwatertics + 1; P_RestoreMusic(player); @@ -1696,7 +1696,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!player->climbing) { - if (player->bot && player->bot != 3 && toucher->state-states != S_PLAY_GASP) + if (player->bot && player->bot != BOT_MPAI && toucher->state-states != S_PLAY_GASP) S_StartSound(toucher, special->info->deathsound); // Force it to play a sound for bots P_SetPlayerMobjState(toucher, S_PLAY_GASP); P_ResetPlayer(player); @@ -1704,7 +1704,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->momx = toucher->momy = toucher->momz = 0; - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; else break; @@ -1736,7 +1736,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_MINECARTSPAWNER: - if (!player->bot && player->bot != 3 && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15))) + if (!player->bot && player->bot != BOT_MPAI && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15))) { mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); P_SetTarget(&mcart->target, toucher); @@ -1789,7 +1789,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; default: // SOC or script pickup - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; P_SetTarget(&special->target, toucher); break; @@ -1813,7 +1813,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) mobj_t *toucher = player->mo; mobj_t *checkbase = snaptopost ? post : toucher; - if (player->bot && player->bot != 3) + if (player->bot && player->bot != BOT_MPAI) return; // In circuit, player must have touched all previous starposts if (circuitmap @@ -2555,7 +2555,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0)) ; - else if ((!target->player->bot || target->player->bot == 3) && !target->player->spectator && (target->player->lives != INFLIVES) + else if ((!target->player->bot || target->player->bot == BOT_MPAI) && !target->player->spectator && (target->player->lives != INFLIVES) && G_GametypeUsesLives()) { if (!(target->player->pflags & PF_FINISHED)) @@ -3475,7 +3475,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (inflictor && inflictor->type == MT_LHRT) return; - if (player->powers[pw_shield] || (player->bot && player->bot != 3)) //If One-Hit Shield + if (player->powers[pw_shield] || (player->bot && player->bot != BOT_MPAI)) //If One-Hit Shield { P_RemoveShield(player); S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss. @@ -3566,7 +3566,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Make sure that boxes cannot be popped by enemies, red rings, etc. - if (target->flags & MF_MONITOR && ((!source || !source->player || (source->player->bot && source->player->bot != 3)) + if (target->flags & MF_MONITOR && ((!source || !source->player || (source->player->bot && source->player->bot != BOT_MPAI)) || (inflictor && (inflictor->type == MT_REDRING || (inflictor->type >= MT_THROWNBOUNCE && inflictor->type <= MT_THROWNGRENADE))))) return false; } @@ -3701,7 +3701,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } else if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) return true; - else if (player->powers[pw_shield] || (player->bot && player->bot != 3 && !ultimatemode)) //If One-Hit Shield + else if (player->powers[pw_shield] || (player->bot && player->bot != BOT_MPAI && !ultimatemode)) //If One-Hit Shield { P_ShieldDamage(player, inflictor, source, damage, damagetype); damage = 0; From 48514ee88d54a5d36a92c2af0fdd1feb587acf2d Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Thu, 15 Jul 2021 15:04:24 -0700 Subject: [PATCH 232/241] Fixed G_RemovePlayer crash in players.iterate This was done by storing flag-for-removal status as a boolean inside the player struct. Bot players are instead removed at the start of G_Ticker, rather than being removed immediately by G_RemovePlayer. --- src/d_player.h | 1 + src/g_game.c | 22 +++++++++++++++++++++- src/lua_baselib.c | 14 ++------------ src/p_saveg.c | 2 ++ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 89776fe5e..a0db1402d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -559,6 +559,7 @@ typedef struct player_s boolean spectator; boolean outofcoop; + boolean removing; UINT8 bot; struct player_s *botleader; UINT16 lastbuttons; diff --git a/src/g_game.c b/src/g_game.c index 0643350b6..4d501f526 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1545,7 +1545,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->forwardmove = (SINT8)(cmd->forwardmove + forward); cmd->sidemove = (SINT8)(cmd->sidemove + side); - //Note: Majority of botstuffs are handled in G_Ticker now. + // Note: Majority of botstuffs are handled in G_Ticker now. if (player->bot == BOT_2PHUMAN) //Player-controlled bot { G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver @@ -2198,6 +2198,23 @@ void G_Ticker(boolean run) UINT32 i; INT32 buf; + // Bot players queued for removal + for (i = MAXPLAYERS-1; i != UINT32_MAX; i--) + { + if (playeringame[i] && players[i].removing) + { + CL_RemovePlayer(i, i); + if (netgame) + { + char kickmsg[256]; + + strcpy(kickmsg, M_GetText("\x82*Bot %s has been removed")); + strcpy(kickmsg, va(kickmsg, player_names[i], i)); + HU_AddChatText(kickmsg, false); + } + } + } + // see also SCR_DisplayMarathonInfo if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL) marathontime++; @@ -2520,6 +2537,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) tic_t quittime; boolean spectator; boolean outofcoop; + boolean removing; INT16 bot; SINT8 pity; INT16 rings; @@ -2536,6 +2554,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) quittime = players[player].quittime; spectator = players[player].spectator; outofcoop = players[player].outofcoop; + removing = players[player].removing; pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER)); playerangleturn = players[player].angleturn; oldrelangleturn = players[player].oldrelangleturn; @@ -2612,6 +2631,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->quittime = quittime; p->spectator = spectator; p->outofcoop = outofcoop; + p->removing = removing; p->angleturn = playerangleturn; p->oldrelangleturn = oldrelangleturn; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9946a9fd3..9e01a98c0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3482,24 +3482,14 @@ static int lib_gAddPlayer(lua_State *L) static int lib_gRemovePlayer(lua_State *L) { UINT8 pnum = -1; - //const char *kickreason = luaL_checkstring(L, 2); if (!lua_isnoneornil(L, 1)) pnum = luaL_checkinteger(L, 1); if (&players[pnum]) { - if (players[pnum].bot != BOT_NONE) + if (players[pnum].bot != BOT_NONE && players[pnum].removing == false) { -// CL_RemovePlayer(pnum, *kickreason); - CL_RemovePlayer(pnum, pnum); - if (netgame) - { - char kickmsg[256]; - - strcpy(kickmsg, M_GetText("\x82*Bot %s has been removed")); - strcpy(kickmsg, va(kickmsg, player_names[pnum], pnum)); - HU_AddChatText(kickmsg, false); - } + players[pnum].removing = true; // This function can be run in players.iterate(), which isn't equipped to deal with players being removed mid-process. Instead we'll remove the player at the beginning of the next ticframe. lua_pushboolean(L, true); return 1; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 7e9d7b6d4..1270064c0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -201,6 +201,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].botmem.lastBlocked); WRITEUINT8(save_p, players[i].botmem.catchup_tics); WRITEUINT8(save_p, players[i].botmem.thinkstate); + WRITEUINT8(save_p, players[i].removing); WRITEUINT8(save_p, players[i].blocked); WRITEUINT16(save_p, players[i].lastbuttons); @@ -428,6 +429,7 @@ static void P_NetUnArchivePlayers(void) players[i].botmem.lastBlocked = READUINT8(save_p); players[i].botmem.catchup_tics = READUINT8(save_p); players[i].botmem.thinkstate = READUINT8(save_p); + players[i].removing = READUINT8(save_p); players[i].blocked = READUINT8(save_p); players[i].lastbuttons = READUINT16(save_p); From 22f42efb61e242a75a017712d6b753149c3a91ce Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Thu, 15 Jul 2021 15:09:02 -0700 Subject: [PATCH 233/241] Cleaned up leftover comments --- src/b_bot.c | 4 ---- src/g_game.c | 2 +- src/p_mobj.c | 1 - src/p_user.c | 29 ++++++----------------------- 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/b_bot.c b/src/b_bot.c index c61e56f5f..6f4b0ce15 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -102,7 +102,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC) { boolean isrelevant = (sonic->player->powers[pw_carry] == CR_MACESPIN || sonic->player->powers[pw_carry] == CR_GENERIC); - //dist = P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y); //! This is totally redundant. if (sonic->player->cmd.buttons & BT_JUMP && (sonic->player->pflags & PF_JUMPED) && isrelevant) cmd->buttons |= BT_JUMP; if (isrelevant) @@ -402,8 +401,6 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward { player_t *player = mo->player; // don't try to do stuff if your sonic is in a minecart or something - //if (players[consoleplayer].powers[pw_carry] && players[consoleplayer].powers[pw_carry] != CR_PLAYER) - //!!! if (&player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER) return; // Turn the virtual keypresses into ticcmd_t. @@ -576,7 +573,6 @@ void B_RespawnBot(INT32 playernum) player->powers[pw_spacetime] = sonic->player->powers[pw_spacetime]; player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots]; player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol]; - //!!! Nuke the speed equivalencies player->pflags |= PF_AUTOBRAKE|(sonic->player->pflags & PF_DIRECTIONCHAR); P_TeleportMove(tails, x, y, z); diff --git a/src/g_game.c b/src/g_game.c index 4d501f526..8cdeaf079 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3025,7 +3025,7 @@ void G_DoReborn(INT32 playernum) // Make sure objectplace is OFF when you first start the level! OP_ResetObjectplace(); - //! Tailsbot + // Tailsbot if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) { // Bots respawn next to their master. mobj_t *oldmo = NULL; diff --git a/src/p_mobj.c b/src/p_mobj.c index 4924ec053..8af7ab0d0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1839,7 +1839,6 @@ void P_XYMovement(mobj_t *mo) // blocked move moved = false; - //!!! if (player) B_MoveBlocked(player); diff --git a/src/p_user.c b/src/p_user.c index dadc23193..b3535623c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -776,7 +776,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) { UINT8 oldmare, oldmarelap, oldmarebonuslap; - //! Bots can't be NiGHTSerized, silly!1 :P + // Bots can't be NiGHTSerized, silly!1 :P if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) return; @@ -1188,7 +1188,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) { if (!player) return; - //! + if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) player = player->botleader; @@ -5965,23 +5965,6 @@ static void P_3dMovement(player_t *player) acceleration = 96 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * 40; topspeed = normalspd; } - //! Kill this! - /* else if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) - { // Bot steals player 1's stats - normalspd = FixedMul(players[consoleplayer].normalspeed, player->mo->scale); - thrustfactor = players[consoleplayer].thrustfactor; - acceleration = players[consoleplayer].accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * players[consoleplayer].acceleration; - - if (player->powers[pw_tailsfly]) - topspeed = normalspd/2; - else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER)) - { - topspeed = normalspd/2; - acceleration = 2*acceleration/3; - } - else - topspeed = normalspd; - } */ else { if (player->powers[pw_super] || player->powers[pw_sneakers]) @@ -11488,7 +11471,7 @@ void P_PlayerThink(player_t *player) I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri)); #endif - //! Reset terrain blocked status for this frame + // Reset terrain blocked status for this frame player->blocked = false; // todo: Figure out what is actually causing these problems in the first place... @@ -11641,7 +11624,7 @@ void P_PlayerThink(player_t *player) INT32 i; for (i = 0; i < MAXPLAYERS; i++) - { //! + { if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (players[i].lives <= 0) @@ -11673,7 +11656,7 @@ void P_PlayerThink(player_t *player) INT32 i, total = 0, exiting = 0; for (i = 0; i < MAXPLAYERS; i++) - { //! + { if (!playeringame[i] || players[i].spectator || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN) continue; if (players[i].quittime > 30 * TICRATE) @@ -12614,7 +12597,7 @@ void P_PlayerAfterThink(player_t *player) player->mo->momy = tails->momy; player->mo->momz = tails->momz; } - //! + if (G_CoopGametype() && tails->player && tails->player->bot != BOT_2PAI) { player->mo->angle = tails->angle; From 95359fef5142d1dce33ebce35b18d13846e2ca56 Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Thu, 15 Jul 2021 15:19:47 -0700 Subject: [PATCH 234/241] Amendment to G_RemovePlayer to preserve lua error handlers --- src/lua_baselib.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9e01a98c0..f287fb78c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3482,20 +3482,25 @@ static int lib_gAddPlayer(lua_State *L) static int lib_gRemovePlayer(lua_State *L) { UINT8 pnum = -1; - if (!lua_isnoneornil(L, 1)) pnum = luaL_checkinteger(L, 1); - if (&players[pnum]) + else // No argument + return luaL_error(L, "argument #1 not given (expected number)"); + if (pnum >= MAXPLAYERS) // Out of range + return luaL_error(L, "playernum %d out of range (0 - %d)", pnum, MAXPLAYERS-1); + if (playeringame[pnum]) // Found player { - if (players[pnum].bot != BOT_NONE && players[pnum].removing == false) + if (players[pnum].bot == BOT_NONE) // Can't remove clients. + return luaL_error(L, "G_RemovePlayer can only be used on players with a bot value other than BOT_NONE."); + else { - players[pnum].removing = true; // This function can be run in players.iterate(), which isn't equipped to deal with players being removed mid-process. Instead we'll remove the player at the beginning of the next ticframe. + players[pnum].removing = true; lua_pushboolean(L, true); return 1; } } - lua_pushboolean(L, false); - return 1; + // Fell through. Invalid player + return LUA_ErrInvalid(L, "player_t"); } From 7dddc631d798469725e40bd3fbc1a2617f4982ee Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 31 Jul 2021 21:14:48 +0100 Subject: [PATCH 235/241] P_ZMovement: add a P_MobjWasRemoved check after P_CheckPosition, so we can bail out if the mobj was removed (by Lua most likely) --- src/p_mobj.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 10220fff6..3bb7ac58d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2549,6 +2549,10 @@ boolean P_ZMovement(mobj_t *mo) } P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly + + if (P_MobjWasRemoved(mobj)) // mobjs can be removed by P_CheckPosition -- Monster Iestyn 31/07/21 + return false; + if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; From df99cde40ffd1163cfec164e72f7b5d3b31261cb Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 31 Jul 2021 22:11:44 +0100 Subject: [PATCH 236/241] mo not mobj! --- 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 3bb7ac58d..da7385be5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2550,7 +2550,7 @@ boolean P_ZMovement(mobj_t *mo) P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly - if (P_MobjWasRemoved(mobj)) // mobjs can be removed by P_CheckPosition -- Monster Iestyn 31/07/21 + if (P_MobjWasRemoved(mo)) // mobjs can be removed by P_CheckPosition -- Monster Iestyn 31/07/21 return false; if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) From 2d218859ff4f879ee13fbf3e45d6dc890be9012a Mon Sep 17 00:00:00 2001 From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com> Date: Fri, 6 Aug 2021 23:25:19 -0500 Subject: [PATCH 237/241] Give coins a drop shadow --- src/p_mobj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index da7385be5..c7e0a7909 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10391,6 +10391,9 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) case MT_RING: case MT_FLINGRING: + + case MT_COIN: + case MT_FLINGCOIN: case MT_BLUESPHERE: case MT_FLINGBLUESPHERE: From 824b1ab28cdddfd1c018454a9af14dabaab49fcd Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 14 Aug 2021 15:29:21 -0700 Subject: [PATCH 238/241] Makefile: use full stem in dependency generation Previously took only the filename, so the directory component was stripped. This broke dependencies for basically every file. --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index ce0e84987..9659a4994 100644 --- a/src/Makefile +++ b/src/Makefile @@ -376,7 +376,7 @@ ifdef Echo_name @printf '%-20.20s\r' $$< endif endif - $(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$(*F).o $(2) $$< + $(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$< endef $(eval $(call _recipe,c)) From f4f7af6f6d87451c3271606c965762755617cdc1 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 30 Aug 2021 18:40:36 -0700 Subject: [PATCH 239/241] Add my full name --- src/f_finale.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 4d9a8f825..acad7b248 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1089,7 +1089,6 @@ static const char *credits[] = { "\"Hannu_Hanhi\"", // For many OpenGL performance improvements! "Kepa \"Nev3r\" Iceta", "Thomas \"Shadow Hog\" Igoe", - "\"james\"", "Iestyn \"Monster Iestyn\" Jealous", "\"Jimita\"", "\"Kaito Sinclaire\"", @@ -1102,6 +1101,7 @@ static const char *credits[] = { "Louis-Antoine \"LJ Sonic\" de Moulins", // de Rochefort doesn't quite fit on the screen sorry lol "John \"JTE\" Muniz", "Colin \"Sonict\" Pfaff", + "James \"james\" Robert Roman", "Sean \"Sryder13\" Ryder", "Ehab \"Wolfy\" Saeed", "Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible From 39bd9c6da8dbcb47660cc41ac53bbbacb4c020ab Mon Sep 17 00:00:00 2001 From: namishere Date: Mon, 30 Aug 2021 23:18:25 -0700 Subject: [PATCH 240/241] Make next compile again --- src/lua_baselib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f287fb78c..1c3b483fa 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3405,7 +3405,7 @@ static int lib_gAddPlayer(lua_State *L) { INT16 i, newplayernum, botcount = 1; player_t *newplayer; - INT8 skinnum = 0, bot; + SINT8 skinnum = 0, bot; for (i = 0; i < MAXPLAYERS; i++) { From 8e0831a183dbcd3dad5696c6f6514c95df861417 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 3 Sep 2021 17:13:12 -0700 Subject: [PATCH 241/241] Fix unused variable warning under NOPNG --- src/r_picformats.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_picformats.h b/src/r_picformats.h index b1bb35edd..c74f8a13a 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -116,9 +116,9 @@ void *Picture_PNGConvert( size_t insize, size_t *outsize, pictureflags_t flags); boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size); -#endif #define PICTURE_PNG_USELOOKUP +#endif // SpriteInfo extern spriteinfo_t spriteinfo[NUMSPRITES];