Fix console cursor, add chat

This commit is contained in:
Federico Cecchetto 2021-04-23 16:45:33 +02:00
parent e78eb74060
commit 90427d7324
9 changed files with 142 additions and 7 deletions

88
src/component/chat.cpp Normal file
View File

@ -0,0 +1,88 @@
#include <stdinc.hpp>
#include "chat.hpp"
#include "scheduler.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include <utils/string.hpp>
#include <utils/hook.hpp>
#define chat_font game::R_RegisterFont("fonts/fira_mono_regular.ttf", 25)
#define material_white game::Material_RegisterHandle("white")
namespace chat
{
namespace
{
struct message
{
std::string text;
std::chrono::steady_clock::time_point time;
};
std::deque<message> history;
float color_white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float screen_max[2];
void check_resize()
{
screen_max[0] = game::ScrPlace_GetViewPlacement()->realViewportSize[0];
screen_max[1] = game::ScrPlace_GetViewPlacement()->realViewportSize[1];
}
float relative(float value)
{
const auto ratio = screen_max[0] / 2560.f;
return value * ratio;
}
void draw_chat()
{
check_resize();
const auto now = std::chrono::high_resolution_clock::now();
for (auto i = 0; i < std::min(15, (int)history.size()); i++)
{
if (now - history[i].time > 11s)
{
return;
}
const auto diff = now - history[i].time;
float color[4] = { color_white[0], color_white[1], color_white[2], 1.f };
if (diff > 10.5s)
{
const auto milliseconds = (float)(11000 - std::chrono::duration_cast<std::chrono::milliseconds>(diff).count());
color[3] = (float)(milliseconds / 500.f);
}
game::R_AddCmdDrawText(history[i].text.data(), 0x7FFFFFFF, chat_font, relative(15.f), relative(600.f + i * 25), 1.f, 1.f, 0.f, color, 0);
}
}
}
void print(const std::string& msg)
{
message m;
m.text = msg;
m.time = std::chrono::high_resolution_clock::now();
history.push_front(m);
}
void init()
{
scheduler::loop([]()
{
draw_chat();
}, scheduler::pipeline::renderer);
}
}

8
src/component/chat.hpp Normal file
View File

@ -0,0 +1,8 @@
#pragma once
namespace chat
{
void print(const std::string& msg);
void init();
}

View File

@ -146,6 +146,11 @@ namespace command
{ {
utils::hook::jump(game::base_address + 0x5A74F0, dvar_command_stub, true); utils::hook::jump(game::base_address + 0x5A74F0, dvar_command_stub, true);
add("say", [](const params& params)
{
chat::print(params.join(1));
});
add("listassetpool", [](const params& params) add("listassetpool", [](const params& params)
{ {
if (params.size() < 2) if (params.size() < 2)

View File

@ -6,6 +6,10 @@
#include "game/game.hpp" #include "game/game.hpp"
#include "game/dvars.hpp" #include "game/dvars.hpp"
#include "game/scripting/event.hpp"
#include "game/scripting/execution.hpp"
#include "game/scripting/lua/engine.hpp"
#include <utils/string.hpp> #include <utils/string.hpp>
#include <utils/hook.hpp> #include <utils/hook.hpp>
#include <deque> #include <deque>
@ -215,9 +219,9 @@ namespace game_console
con.globals.left_x = con.globals.x; con.globals.left_x = con.globals.x;
con.globals.auto_complete_choice[0] = 0; con.globals.auto_complete_choice[0] = 0;
game::R_AddCmdDrawText(con.buffer, 0x7FFFFFFF, console_font, con.globals.x, game::R_AddCmdDrawTextWithCursor(con.buffer, 0x7FFFFFFF, console_font, 18, con.globals.x,
con.globals.y + con.globals.font_height, 1.0f, 1.0f, 0.0f, color_white, 0/*, con.globals.y + con.globals.font_height, 1.0f, 1.0f, 0, color_white, 0,
con.cursor, '|'*/); con.cursor, '|');
// check if using a prefixed '/' or not // check if using a prefixed '/' or not
const auto input = con.buffer[1] && (con.buffer[0] == '/' || con.buffer[0] == '\\') const auto input = con.buffer[1] && (con.buffer[0] == '/' || con.buffer[0] == '\\')
@ -470,6 +474,18 @@ namespace game_console
return true; return true;
} }
void execute(const char* cmd)
{
scripting::event e;
e.name = "console_command";
e.arguments.push_back(cmd);
e.entity = *game::levelEntityId;
scripting::lua::engine::notify(e);
game::Cbuf_AddText(0, utils::string::va("%s \n", cmd));
}
bool console_key_event(const int localClientNum, const int key, const int down) bool console_key_event(const int localClientNum, const int key, const int down)
{ {
if (key == game::keyNum_t::K_F10) if (key == game::keyNum_t::K_F10)
@ -573,7 +589,7 @@ namespace game_console
if (key == game::keyNum_t::K_ENTER) if (key == game::keyNum_t::K_ENTER)
{ {
game::Cbuf_AddText(0, utils::string::va("%s \n", fixed_input.data())); execute(fixed_input.data());
if (history_index != -1) if (history_index != -1)
{ {

View File

@ -14,5 +14,7 @@ namespace game_console
bool console_char_event(int local_client_num, int key); bool console_char_event(int local_client_num, int key);
bool console_key_event(int local_client_num, int key, int down); bool console_key_event(int local_client_num, int key, int down);
void execute(const char* cmd);
void init(); void init();
} }

View File

@ -17,7 +17,7 @@ DWORD WINAPI dwConsole(LPVOID)
std::cout << "\n"; std::cout << "\n";
std::getline(std::cin, cmd); std::getline(std::cin, cmd);
game::Cbuf_AddText(0, cmd.data()); game_console::execute(cmd.data());
} }
return 0; return 0;
@ -36,6 +36,7 @@ void init()
scheduler::init(); scheduler::init();
game_console::init(); game_console::init();
scripting::init(); scripting::init();
chat::init();
} }
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)

View File

@ -168,6 +168,11 @@ namespace scripting::lua
{ {
command::execute(command, false); command::execute(command, false);
}; };
game_type["say"] = [](const game&, const std::string& msg)
{
chat::print(msg);
};
} }
} }

View File

@ -44,8 +44,8 @@ namespace game
float* color, Material* material)> R_AddCmdDrawStretchPic{0x3C9710}; float* color, Material* material)> R_AddCmdDrawStretchPic{0x3C9710};
WEAK symbol<void(const char* text, int maxChars, Font_s* font, float x, float y, float xScale, float yScale, WEAK symbol<void(const char* text, int maxChars, Font_s* font, float x, float y, float xScale, float yScale,
float rotation, float* color, int style)> R_AddCmdDrawText{0x76C660}; float rotation, float* color, int style)> R_AddCmdDrawText{0x76C660};
WEAK symbol<void(const char*, int, Font_s*, float, float, float, float, float, const float*, int, int, char)> WEAK symbol<void(const char* text, int maxChars, Font_s* font, int fontSize, float x, float y, float xScale, float yScale, float rotation,
R_AddCmdDrawTextWithCursor{0x769D90}; const float* color, int style, int cursorPos, char cursor)> R_AddCmdDrawTextWithCursor{0x76CAF0};
WEAK symbol<Font_s*(const char* font, int size)> R_RegisterFont{0x746FE0}; WEAK symbol<Font_s*(const char* font, int size)> R_RegisterFont{0x746FE0};
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x7472A0}; WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x7472A0};

View File

@ -21,6 +21,15 @@
#include <cstdarg> #include <cstdarg>
#include <unordered_set> #include <unordered_set>
#include <csetjmp> #include <csetjmp>
#include <deque>
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#include <MinHook.h> #include <MinHook.h>
#include <gsl/gsl> #include <gsl/gsl>
@ -42,3 +51,4 @@ using namespace std::literals;
#include "component/scheduler.hpp" #include "component/scheduler.hpp"
#include "component/input.hpp" #include "component/input.hpp"
#include "component/game_console.hpp" #include "component/game_console.hpp"
#include "component/chat.hpp"