Merge branch 'develop' into branding
This commit is contained in:
commit
555a33e62d
34
CHANGELOG.md
34
CHANGELOG.md
@ -4,7 +4,39 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog v0.3.0](http://keepachangelog.com/en/0.3.0/) and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [0.7.0] - 2022-01-05
|
||||
## [0.7.1] - 2022-05-03
|
||||
|
||||
### Added
|
||||
|
||||
- Add ToUpper GSC Function (#216)
|
||||
- Add StrICmp GSC Function (#216)
|
||||
- Add IsEndStr GSC Function (#216)
|
||||
- Add DropAllBots GSC Function (#174)
|
||||
- Add GSC entity field `entityflags` (#228)
|
||||
- Add GSC client field `clientflags` (#228)
|
||||
- Add bg_surfacePenetration Dvar (#241)
|
||||
- Add bg_bulletRange Dvar (#241)
|
||||
|
||||
### Changed
|
||||
|
||||
- Test clients' native functionality has been restored by default (#162)
|
||||
- Custom GSC functions can be called correctly from a game script (#216)
|
||||
- Master server list will be used instead of the node system (load server list faster) (#234)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed issue with mouse acceleration when polling rate is greater than 125Hz (#230)
|
||||
- Fixed issue with player speed caused by sprinting from the prone position (#232)
|
||||
- Fixed client crash when cg_chatHeight was set to 0 (#237)
|
||||
- Fixed GSC function Scr_TableLookupIStringByRow (#162)
|
||||
|
||||
### Known issue
|
||||
|
||||
- HTTPS is not supported for fast downloads at the moment.
|
||||
- Sound issue fix is experimental as the bug is not fully understood.
|
||||
- `reloadmenus` command does not free resources used by custom menus.
|
||||
|
||||
## [0.7.0] - 2022-05-01
|
||||
|
||||
### Added
|
||||
|
||||
|
@ -107,6 +107,7 @@ namespace Components
|
||||
Loader::Register(new ScriptExtension());
|
||||
Loader::Register(new Branding());
|
||||
Loader::Register(new RawMouse());
|
||||
Loader::Register(new Bullet());
|
||||
|
||||
Loader::Pregame = false;
|
||||
}
|
||||
|
@ -138,3 +138,4 @@ namespace Components
|
||||
#include "Modules/ScriptExtension.hpp"
|
||||
#include "Modules/Branding.hpp"
|
||||
#include "Modules/RawMouse.hpp"
|
||||
#include "Modules/Bullet.hpp"
|
||||
|
60
src/Components/Modules/Bullet.cpp
Normal file
60
src/Components/Modules/Bullet.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include <STDInclude.hpp>
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Dvar::Var Bullet::BGSurfacePenetration;
|
||||
Game::dvar_t* Bullet::BGBulletRange;
|
||||
|
||||
float Bullet::BG_GetSurfacePenetrationDepthStub(const Game::WeaponDef* weapDef, int surfaceType)
|
||||
{
|
||||
assert(weapDef != nullptr);
|
||||
assert(weapDef->penetrateType != Game::PenetrateType::PENETRATE_TYPE_NONE);
|
||||
assert(weapDef->penetrateType < Game::PenetrateType::PENETRATE_TYPE_COUNT);
|
||||
assert(static_cast<size_t>(surfaceType) < Game::materialSurfType_t::SURF_TYPE_COUNT);
|
||||
|
||||
const auto penetrationDepth = BGSurfacePenetration.get<float>();
|
||||
if (penetrationDepth > 0.0f)
|
||||
{
|
||||
// Custom depth
|
||||
return penetrationDepth;
|
||||
}
|
||||
|
||||
// Game's code
|
||||
if (surfaceType != Game::materialSurfType_t::SURF_TYPE_DEFAULT)
|
||||
{
|
||||
return (*Game::penetrationDepthTable)[weapDef->penetrateType][surfaceType];
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
__declspec(naked) void Bullet::Bullet_FireStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
mov eax, BGBulletRange
|
||||
fld dword ptr [eax + 0x10] // dvar_t.current.value
|
||||
pop eax
|
||||
|
||||
push 0x440346
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
Bullet::Bullet()
|
||||
{
|
||||
Dvar::OnInit([]
|
||||
{
|
||||
BGSurfacePenetration = Dvar::Register<float>("bg_surfacePenetration", 0.0f,
|
||||
0.0f, std::numeric_limits<float>::max(), Game::dvar_flag::DVAR_CODINFO,
|
||||
"Set to a value greater than 0 to override the surface penetration depth");
|
||||
BGBulletRange = Game::Dvar_RegisterFloat("bg_bulletRange", 8192.0f,
|
||||
0.0f, std::numeric_limits<float>::max(), Game::dvar_flag::DVAR_CODINFO,
|
||||
"Max range used when calculating the bullet end position");
|
||||
});
|
||||
|
||||
Utils::Hook(0x4F6980, BG_GetSurfacePenetrationDepthStub, HOOK_JUMP).install()->quick();
|
||||
Utils::Hook(0x440340, Bullet_FireStub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
}
|
19
src/Components/Modules/Bullet.hpp
Normal file
19
src/Components/Modules/Bullet.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class Bullet : public Component
|
||||
{
|
||||
public:
|
||||
Bullet();
|
||||
|
||||
private:
|
||||
static Dvar::Var BGSurfacePenetration;
|
||||
// Can't use Var class inside assembly stubs
|
||||
static Game::dvar_t* BGBulletRange;
|
||||
|
||||
static float BG_GetSurfacePenetrationDepthStub(const Game::WeaponDef* weapDef, int surfaceType);
|
||||
|
||||
static void Bullet_FireStub();
|
||||
};
|
||||
}
|
@ -110,6 +110,7 @@ namespace Components
|
||||
inputBuffer += lastFontIconPos - lineBuffer;
|
||||
lineBuffer = lastFontIconPos;
|
||||
}
|
||||
|
||||
*lineBuffer = 0;
|
||||
len = 0.0f;
|
||||
Game::cgsArray[0].teamChatMsgTimes[Game::cgsArray[0].teamChatPos % chatHeight] = Game::cgArray[0].time;
|
||||
@ -132,7 +133,7 @@ namespace Components
|
||||
const auto chatHeight = (*cg_chatHeight)->current.integer;
|
||||
const auto chatWidth = static_cast<float>(cg_chatWidth.get<int>());
|
||||
const auto chatTime = (*cg_chatTime)->current.integer;
|
||||
if (chatHeight < 0 || static_cast<unsigned>(chatHeight) > std::extent_v<decltype(Game::cgs_t::teamChatMsgs)> || chatWidth <= 0 || chatTime <= 0)
|
||||
if (chatHeight <= 0 || static_cast<unsigned>(chatHeight) > std::extent_v<decltype(Game::cgs_t::teamChatMsgs)> || chatWidth <= 0 || chatTime <= 0)
|
||||
{
|
||||
Game::cgsArray[0].teamLastChatPos = 0;
|
||||
Game::cgsArray[0].teamChatPos = 0;
|
||||
|
@ -3,7 +3,9 @@
|
||||
namespace Components
|
||||
{
|
||||
SteamID Dedicated::PlayerGuids[18][2];
|
||||
|
||||
Dvar::Var Dedicated::SVRandomMapRotation;
|
||||
Dvar::Var Dedicated::SVLanOnly;
|
||||
|
||||
bool Dedicated::IsEnabled()
|
||||
{
|
||||
@ -251,8 +253,14 @@ namespace Components
|
||||
|
||||
void Dedicated::Heartbeat()
|
||||
{
|
||||
int masterPort = Dvar::Var("masterPort").get<int>();
|
||||
const char* masterServerName = Dvar::Var("masterServerName").get<const char*>();
|
||||
// Do not send a heartbeat if sv_lanOnly is set to true
|
||||
if (Dedicated::SVLanOnly.get<bool>())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto masterPort = Dvar::Var("masterPort").get<int>();
|
||||
const auto* masterServerName = Dvar::Var("masterServerName").get<const char*>();
|
||||
|
||||
Network::Address master(Utils::String::VA("%s:%u", masterServerName, masterPort));
|
||||
|
||||
@ -290,7 +298,11 @@ namespace Components
|
||||
// Make sure all callbacks are handled
|
||||
Scheduler::OnFrame(Steam::SteamAPI_RunCallbacks);
|
||||
|
||||
Dvar::Register<bool>("sv_lanOnly", false, Game::dvar_flag::DVAR_NONE, "Don't act as node");
|
||||
Dvar::OnInit([]
|
||||
{
|
||||
Dedicated::SVLanOnly = Dvar::Register<bool>("sv_lanOnly", false,
|
||||
Game::dvar_flag::DVAR_NONE, "Don't act as node");
|
||||
});
|
||||
|
||||
Utils::Hook(0x60BE98, Dedicated::InitDedicatedServer, HOOK_CALL).install()->quick();
|
||||
|
||||
@ -374,7 +386,6 @@ namespace Components
|
||||
}
|
||||
});
|
||||
|
||||
#ifdef USE_LEGACY_SERVER_LIST
|
||||
// Heartbeats
|
||||
Scheduler::Once(Dedicated::Heartbeat);
|
||||
Scheduler::OnFrame([]()
|
||||
@ -387,7 +398,6 @@ namespace Components
|
||||
Dedicated::Heartbeat();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
Dvar::OnInit([]()
|
||||
{
|
||||
|
@ -8,6 +8,7 @@ namespace Components
|
||||
Dedicated();
|
||||
|
||||
static SteamID PlayerGuids[18][2];
|
||||
static Dvar::Var SVLanOnly;
|
||||
|
||||
static bool IsEnabled();
|
||||
|
||||
|
@ -1531,11 +1531,9 @@ namespace Components
|
||||
gpad_present.setRaw(gpadPresent);
|
||||
}
|
||||
|
||||
|
||||
void Gamepad::IN_Frame_Hk()
|
||||
{
|
||||
// Call original method
|
||||
Utils::Hook::Call<void()>(0x64C490)();
|
||||
RawMouse::IN_MouseMove();
|
||||
|
||||
IN_GamePadsMove();
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ namespace Components
|
||||
|
||||
void Node::StoreNodes(bool force)
|
||||
{
|
||||
if (Dedicated::IsEnabled() && Dvar::Var("sv_lanOnly").get<bool>()) return;
|
||||
if (Dedicated::IsEnabled() && Dedicated::SVLanOnly.get<bool>()) return;
|
||||
|
||||
static Utils::Time::Interval interval;
|
||||
if (!force && !interval.elapsed(1min)) return;
|
||||
@ -167,7 +167,8 @@ namespace Components
|
||||
|
||||
void Node::RunFrame()
|
||||
{
|
||||
if (Dedicated::IsEnabled() && Dvar::Var("sv_lanOnly").get<bool>()) return;
|
||||
if (ServerList::useMasterServer) return;
|
||||
if (Dedicated::IsEnabled() && Dedicated::SVLanOnly.get<bool>()) return;
|
||||
|
||||
if (!Dedicated::IsEnabled() && *Game::clcState > 0)
|
||||
{
|
||||
@ -246,7 +247,7 @@ namespace Components
|
||||
|
||||
if (list.isnode() && (!list.port() || list.port() == address.getPort()))
|
||||
{
|
||||
if (!Dedicated::IsEnabled() && ServerList::IsOnlineList() && list.protocol() == PROTOCOL)
|
||||
if (!Dedicated::IsEnabled() && ServerList::IsOnlineList() && !ServerList::useMasterServer && list.protocol() == PROTOCOL)
|
||||
{
|
||||
NODE_LOG("Inserting %s into the serverlist\n", address.getCString());
|
||||
ServerList::InsertRequest(address);
|
||||
|
@ -146,7 +146,6 @@ namespace Components
|
||||
{
|
||||
Utils::Hook(0x475E65, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick();
|
||||
Utils::Hook(0x475E8D, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick();
|
||||
Utils::Hook(0x475E9E, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick();
|
||||
|
||||
Utils::Hook(0x467C03, RawMouse::IN_Init, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x64D095, RawMouse::IN_Init, HOOK_JUMP).install()->quick();
|
||||
|
@ -6,6 +6,9 @@ namespace Components
|
||||
{
|
||||
public:
|
||||
RawMouse();
|
||||
|
||||
static void IN_MouseMove();
|
||||
|
||||
private:
|
||||
static Dvar::Var M_RawInput;
|
||||
static int MouseRawX, MouseRawY;
|
||||
@ -15,6 +18,5 @@ namespace Components
|
||||
static void IN_RawMouseMove();
|
||||
static void IN_RawMouse_Init();
|
||||
static void IN_Init();
|
||||
static void IN_MouseMove();
|
||||
};
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ namespace Components
|
||||
Dvar::Var ServerList::NETServerQueryLimit;
|
||||
Dvar::Var ServerList::NETServerFrames;
|
||||
|
||||
bool ServerList::useMasterServer = true;
|
||||
|
||||
std::vector<ServerList::ServerInfo>* ServerList::GetList()
|
||||
{
|
||||
if (ServerList::IsOnlineList())
|
||||
@ -205,13 +207,6 @@ namespace Components
|
||||
auto list = ServerList::GetList();
|
||||
if (!list) return;
|
||||
|
||||
// Refresh entirely, if there is no entry in the list
|
||||
if (list->empty())
|
||||
{
|
||||
ServerList::Refresh(UIScript::Token());
|
||||
return;
|
||||
}
|
||||
|
||||
bool ui_browserShowFull = Dvar::Var("ui_browserShowFull").get<bool>();
|
||||
bool ui_browserShowEmpty = Dvar::Var("ui_browserShowEmpty").get<bool>();
|
||||
int ui_browserShowHardcore = Dvar::Var("ui_browserKillcam").get<int>();
|
||||
@ -274,22 +269,28 @@ namespace Components
|
||||
}
|
||||
else if (ServerList::IsOnlineList())
|
||||
{
|
||||
#ifdef USE_LEGACY_SERVER_LIST
|
||||
const auto masterPort = Dvar::Var("masterPort").get<int>();
|
||||
const auto masterServerName = Dvar::Var("masterServerName").get<const char*>();
|
||||
|
||||
// Check if our dvars can properly convert to a address
|
||||
Game::netadr_t masterServerAddr;
|
||||
if (!ServerList::GetMasterServer(masterServerName, masterPort, masterServerAddr))
|
||||
{
|
||||
Logger::Print("Could not resolve address for %s:%u", masterServerName, masterPort);
|
||||
Toast::Show("cardicon_headshot", "^1Error", Utils::String::VA("Could not resolve address for %s:%u", masterServerName, masterPort), 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
Toast::Show("cardicon_headshot", "Server Browser", "Fetching servers...", 3000);
|
||||
|
||||
useMasterServer = true;
|
||||
|
||||
ServerList::RefreshContainer.awatingList = true;
|
||||
ServerList::RefreshContainer.awaitTime = Game::Sys_Milliseconds();
|
||||
|
||||
int masterPort = Dvar::Var("masterPort").get<int>();
|
||||
const char* masterServerName = Dvar::Var("masterServerName").get<const char*>();
|
||||
|
||||
ServerList::RefreshContainer.host = Network::Address(Utils::String::VA("%s:%u", masterServerName, masterPort));
|
||||
|
||||
Logger::Print("Sending serverlist request to master: %s:%u\n", masterServerName, masterPort);
|
||||
|
||||
Logger::Print("Sending serverlist request to master\n");
|
||||
Network::SendCommand(ServerList::RefreshContainer.host, "getservers", Utils::String::VA("IW4 %i full empty", PROTOCOL));
|
||||
//Network::SendCommand(ServerList::RefreshContainer.Host, "getservers", "0 full empty");
|
||||
#else
|
||||
Node::Synchronize();
|
||||
#endif
|
||||
}
|
||||
else if (ServerList::IsFavouriteList())
|
||||
{
|
||||
@ -570,8 +571,7 @@ namespace Components
|
||||
void ServerList::SortList()
|
||||
{
|
||||
// Only sort when the serverlist is open
|
||||
Game::menuDef_t* menu = Game::Menus_FindByName(Game::uiContext, "pc_join_unranked");
|
||||
if (!menu || !Game::Menu_IsVisible(Game::uiContext, menu)) return;
|
||||
if (!ServerList::IsServerListOpen()) return;
|
||||
|
||||
std::stable_sort(ServerList::VisibleList.begin(), ServerList::VisibleList.end(), [](const unsigned int &server1, const unsigned int &server2) -> bool
|
||||
{
|
||||
@ -637,12 +637,22 @@ namespace Components
|
||||
|
||||
if (ServerList::RefreshContainer.awatingList)
|
||||
{
|
||||
// Check if we haven't got a response within 10 seconds
|
||||
// Stop counting if we are out of the server browser menu
|
||||
if (!ServerList::IsServerListOpen())
|
||||
{
|
||||
ServerList::RefreshContainer.awatingList = false;
|
||||
}
|
||||
|
||||
// Check if we haven't got a response within 5 seconds
|
||||
if (Game::Sys_Milliseconds() - ServerList::RefreshContainer.awaitTime > 5000)
|
||||
{
|
||||
ServerList::RefreshContainer.awatingList = false;
|
||||
|
||||
Logger::Print("We haven't received a response from the master within %d seconds!\n", (Game::Sys_Milliseconds() - ServerList::RefreshContainer.awaitTime) / 1000);
|
||||
Toast::Show("cardicon_headshot", "^1Error", "Failed to reach master server, using node servers instead.", 5000);
|
||||
|
||||
useMasterServer = false;
|
||||
Node::Synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
@ -733,6 +743,20 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerList::GetMasterServer(const char* ip, int port, Game::netadr_t& address)
|
||||
{
|
||||
return Game::NET_StringToAdr(Utils::String::VA("%s:%u", ip, port), &address);
|
||||
}
|
||||
|
||||
bool ServerList::IsServerListOpen()
|
||||
{
|
||||
auto* menu = Game::Menus_FindByName(Game::uiContext, "pc_join_unranked");
|
||||
if (!menu)
|
||||
return false;
|
||||
|
||||
return Game::Menu_IsVisible(Game::uiContext, menu);
|
||||
}
|
||||
|
||||
ServerList::ServerList()
|
||||
{
|
||||
ServerList::OnlineList.clear();
|
||||
@ -792,11 +816,9 @@ namespace Components
|
||||
});
|
||||
|
||||
// Set default masterServerName + port and save it
|
||||
#ifdef USE_LEGACY_SERVER_LIST
|
||||
Utils::Hook::Set<char*>(0x60AD92, "127.0.0.1");
|
||||
Utils::Hook::Set<const char*>(0x60AD92, "master.xlabs.dev");
|
||||
Utils::Hook::Set<BYTE>(0x60AD90, Game::dvar_flag::DVAR_ARCHIVE); // masterServerName
|
||||
Utils::Hook::Set<BYTE>(0x60ADC6, Game::dvar_flag::DVAR_ARCHIVE); // masterPort
|
||||
#endif
|
||||
|
||||
// Add server list feeder
|
||||
UIFeeder::Add(2.0f, ServerList::GetServerCount, ServerList::GetServerText, ServerList::SelectServer);
|
||||
|
@ -50,6 +50,9 @@ namespace Components
|
||||
|
||||
static void UpdateVisibleInfo();
|
||||
|
||||
static bool GetMasterServer(const char* ip, int port, Game::netadr_t& address);
|
||||
static bool useMasterServer;
|
||||
|
||||
private:
|
||||
enum Column
|
||||
{
|
||||
@ -143,5 +146,7 @@ namespace Components
|
||||
static Dvar::Var UIServerSelectedMap;
|
||||
static Dvar::Var NETServerQueryLimit;
|
||||
static Dvar::Var NETServerFrames;
|
||||
|
||||
static bool IsServerListOpen();
|
||||
};
|
||||
}
|
||||
|
@ -553,6 +553,8 @@ namespace Game
|
||||
|
||||
level_locals_t* level = reinterpret_cast<level_locals_t*>(0x1A831A8);
|
||||
|
||||
float(*penetrationDepthTable)[PENETRATE_TYPE_COUNT][SURF_TYPE_COUNT] = reinterpret_cast<float(*)[PENETRATE_TYPE_COUNT][SURF_TYPE_COUNT]>(0x7C4878);
|
||||
|
||||
WinMouseVars_t* s_wmv = reinterpret_cast<WinMouseVars_t*>(0x649D640);
|
||||
|
||||
int* window_center_x = reinterpret_cast<int*>(0x649D638);
|
||||
|
@ -1153,6 +1153,8 @@ namespace Game
|
||||
|
||||
extern level_locals_t* level;
|
||||
|
||||
extern float(*penetrationDepthTable)[PENETRATE_TYPE_COUNT][SURF_TYPE_COUNT];
|
||||
|
||||
extern WinMouseVars_t* s_wmv;
|
||||
|
||||
extern int* window_center_x;
|
||||
|
@ -96,6 +96,43 @@ namespace Game
|
||||
ASSET_TYPE_INVALID = -1,
|
||||
};
|
||||
|
||||
enum materialSurfType_t
|
||||
{
|
||||
SURF_TYPE_DEFAULT,
|
||||
SURF_TYPE_BARK,
|
||||
SURF_TYPE_BRICK,
|
||||
SURF_TYPE_CARPET,
|
||||
SURF_TYPE_CLOTH,
|
||||
SURF_TYPE_CONCRETE,
|
||||
SURF_TYPE_DIRT,
|
||||
SURF_TYPE_FLESH,
|
||||
SURF_TYPE_FOLIAGE,
|
||||
SURF_TYPE_GLASS,
|
||||
SURF_TYPE_GRASS,
|
||||
SURF_TYPE_GRAVEL,
|
||||
SURF_TYPE_ICE,
|
||||
SURF_TYPE_METAL,
|
||||
SURF_TYPE_MUD,
|
||||
SURF_TYPE_PAPER,
|
||||
SURF_TYPE_PLASTER,
|
||||
SURF_TYPE_ROCK,
|
||||
SURF_TYPE_SAND,
|
||||
SURF_TYPE_SNOW,
|
||||
SURF_TYPE_WATER,
|
||||
SURF_TYPE_WOOD,
|
||||
SURF_TYPE_ASPHALT,
|
||||
SURF_TYPE_CERAMIC,
|
||||
SURF_TYPE_PLASTIC,
|
||||
SURF_TYPE_RUBBER,
|
||||
SURF_TYPE_CUSHION,
|
||||
SURF_TYPE_FRUIT,
|
||||
SURF_TYPE_PAINTED_METAL,
|
||||
SURF_TYPE_RIOT_SHIELD,
|
||||
SURF_TYPE_SLUSH,
|
||||
|
||||
SURF_TYPE_COUNT
|
||||
};
|
||||
|
||||
enum dvar_flag : unsigned __int16
|
||||
{
|
||||
DVAR_NONE = 0x0, // No flags
|
||||
|
Loading…
x
Reference in New Issue
Block a user