This repository contains the game code for the 2023 rerelease of Quake II, for users who wish to mod the game, along with the original game code that was use for reference. Mods can be loaded into the rerelease the same way as the original game: launch the game with +set game mymod
or type game mymod
into the console while the game is running. We recommend installing mods into your %USERPROFILE%\Saved Games\Nightdive Studios\Quake II
directory to ensure the original game files do not get modified.
id Software is unable to provide support for this release, however we urge you to take advantage of the depth of community-driven resources already available.
The rerelease of Quake II uses a new version of the API to communicate between the server & the game module. It also introduces a very thin "client game" module, akin to Quake III Arena's cgame module, to allow for extended modding opportunities that change previously hardcoded client behavior. It also has a new network protocol, version 2023.
This codebase is a combination of the separate game modules that were part of the original game: baseq2, ctf, rogue, and xatrix. It requires a C++17 compiler. In cases of conflicting spawnflags, maps were modified in order to resolve issues, so original expansion pack maps may not load correctly with this DLL. The combined FGD as used for development is also available for users wishing to make new maps. A modified TrenchBroom Quake II gameconfig.cfg
is included as there are modified textureflags.
Because the game export interface has changed, existing mods may be able to be moved over to support the API changes. However, in order to support all expansion packs under one codebase and new features in the rerelease, there have been some major changes to structure and layout, so old mods wishing to use the new codebase may need to be rewritten.
The API changes discussed here are written from the perspective of the game DLL.
The game DLL has only been tested with Clang, VS2019 and VS2022.
The code can compile under both C++17 and C++20. Using C++20 allows you to skip fmtlib
as a dependency.
GAME_INCLUDE
must be defined, tells game.h
that this is the game DLL compiling it.KEX_Q2GAME_EXPORTS
must be defined, tells game.h
that we are exporting the GetGameAPI
function.KEX_Q2GAME_DYNAMIC
must be defined. The game DLL supports static linking on console platforms, but is always dynamic on PC.NO_FMT_SOURCE
: this is only here because of a limitation in the internal build system. It must be defined.KEX_Q2_GAME
: must be defined if compiling for Kex. This changes the behavior of the say
command to go through the lobby.KEX_Q2GAME_IMPORTS
: only used by engine, tells game.h
that we are importing GetGameAPI
.USE_CPP20_FORMAT
: if explicitly defined, C++20's <format>
library will be used instead of fmtlib
; otherwise fmtlib
usage will be autodetected.USE_CPP20_FORMAT
is not set, the library needs to be available in the fmt
subdirectory.json
subdirectory.Both of these can also be installed via vcpkg: vcpkg install jsoncpp:x64-windows fmt:x64-windows
baseq2
, make a folder called mymod
, enter that folder, make a folder called src
, and copying the contents of the rerelease
directory into the newly-created src
subfolder.game.sln
Debugging the DLL is possible when attaching to the engine EXE. Note that if you are using VS2022 Hot Reload, due to an internal Hot Reload issue, current edits will be lost when disconnecting from the server, or changing levels using the map
command.
As part of this release, all internal logic in the game DLL has been adjusted to run at 40hz compared to the original 10hz of the original engine. This provides a better gameplay experience, and allows maps and game logic to run at more precise steps than the original 100ms. 40hz was chosen as it is a multiple of the original 10hz, operates at an integral 25ms step, and was the best balance between bandwidth and CPU concerns around the original tech.
As part of the API cleanup, the game DLL no longer uses varargs in any of its functions. Varargs are compiler-specific and not very portable, so instead, the onus is on the caller to handle formatting. As a bonus, this allows the game DLL to more easily hook in modern formatting providers; the game DLL uses fmt
almost exclusively. Several built-in types, like edict_t
and vec3_t
, can be formatted directly.
Since C++ is now used in the game DLL, math functions were made constexpr where appropriate, and operator overloads are used to make math easier to work with and closer to QuakeC. For instance, VectorMA(a, s, b, c)
can now be written as c = a + (b * s)
, which expresses the operation better.
qboolean
, which was aliased to int32_t
, is now instead aliased to bool
. This type should be equivalent to C's _Bool
.
In the original Quake II, all infokey values are purely ASCII with upper bits stripped. Kex and the Quake II rerelease engine supports UTF-8 for things like player names, which necessated a change to the way info keys work. Instead of implementing a whole UTF-8 system in the game DLL, these functions are now imports, so the engine is in control of the parsing and string management.
Userinfo variables are now suffixed with a number for split screen support. For instance, name
and skin
have become name_0
and skin_0
for the first player, name_1
and skin_1
for the second player, and so on.
In an attempt to remain compatible with future community engines, all engine interfaces contain stubbed functions for GetExtension. This is currently unused and will only return nullptr, however other engines may wish to support returning named structs containing extra function pointers based on string parameters. This is similar to getextension
that has become standard in many QuakeC environments.
Conforming engines should return nullptr if an extension is not supported, otherwise they should return a non null pointer value that is relevant to the requested feature. Supporting engines should use namespaces for features to prevent name collisions around common and possibly incompatible implementations.
Player movement ("pmove") is now handled as an export in both game_export_t
and cgame_export_t
. This allows a game module to modify physics while still working with client prediction. Pmove also received several upgrades, such as more bits for flags and full float positioning.
Because a lot of movement quirks in Quake II were indirectly caused by the compression, these behaviors were retained. Trick jumping is now an explicit movement type, to allow for things like the Mega Health box jumps to still work. Some fixes were made, like jumping higher below the 0 z point of the map.
As part of network improvements, some changes were made to the "entity is visible to client in frame" methods:
To fix a legacy bug where lasers only relied on one position for culling, RF_BEAM entities now set their absmin
& absmax
properly. This can cause them to be a bit inflated if they are angled, but should not cause any issues otherwise.
In a similar vein, gi.linkentity
no longer automatically sets old_origin
for beams. This is to make it a bit easier to work with beams, as otherwise you'd be forced to link twice to get it linked into the world correctly. This might break old mods that depends on this behavior.
Entity spatialization underwent an overhaul (CL_GetEntitySoundOrigin
mainly).
s.sound
, and plays their sound on the nearest point between the two beam origins.As a secondary fix to the above, S_StartSound
has slightly different logic now surrounding what origin to pick when playing a sound:
if (entnum < MAX_EDICTS && (origin || fixed_origin)) { // [Paril-KEX] if we can currently see the entity in question // and it's a bmodel or beam, don't use a fixed origin so it sounds correct if (!fixed_origin && entnum > 1 && (cl_entities[entnum].serverframe == cl.frame.serverframe || (cl_entities[entnum].current.solid == PACKED_SOLID_BSP || (cl_entities[entnum].current.renderfx & RF_BEAM)))) { ps->fixed_origin = false; } else { VectorCopy (origin, ps->origin); ps->fixed_origin = true; } } else ps->fixed_origin = false;
fixed_origin
is set to flags & SND_EXPLICIT_POS
for svc_sound packets, and is false
otherwise. If the playsounds' fixed_origin
field is set, then the ps->origin
value will always be used over automatically trying to determine its position.
TE_ELECTRIC_SPARKS
and TE_SCREEN_SPARKS
/TE_SHIELD_SPARKS
will only play sounds once on any given frame.delta_angles
are interpolated now, although this is never used at all in the game.screen_blend
and damage_blend
are interpolated now, but only if the frame prior didn't have a clear color.Configstrings have been overhauled. There is now a theoretical maximum of 32767
entries, although you are still bound by the game APIs value of MAX_CONFIGSTRINGS
.
The maximum length of a configstring has increased from 64
to 96
.
The API now canonizes that certain spans (CS_STATUSBAR
and CS_GENERAL
) can span multiple lines. A CS_SIZE
function is provided to calculate the total size (in bytes) that can be written to for a given configstring ID.
A convenience function, CS_REMAP
, is provided to help remap old configstring IDs to new ones. This is used in our engine to provide old demo support.
MAX_MODELS
, MAX_SOUNDS
and MAX_IMAGES
have been increased from 256 to 8192, 2048, and 512, respectively.
This entry now spans entries 5 to 58 instead of 5 to 28, giving you an effective size of 5184 bytes (minus one for the null terminator) for the statusbar strings, up from 1536 bytes.
This new span each consists of a shadow light entry. Its format is semicolon-separated numerical values, in the following type & order:
This new span consists of entries for the weapon wheel. It consists of pipe-separated integral values, in the following order:
This new span consists of entries for the weapon wheel ammo types. It consists of pipe-separated integral values, in the following order:
This new span consists of entries for the powerup wheel. It consists of pipe-separated integral values, in the following order:
Integer which determines how many times to loop the music before switching to the ambient track. Leave blank to use the clients' preferred value, otherwise it is forced to this value (a value of zero means never switch to ambient track).
Inform the client about the type of game being played.
Quake II has two main shared structures: gclient_t
and edict_t
. These split off into various other shared structures that have to be the same between the game & server.
Like the original release, the "shared" aspects of these structs must be identical, and are stored in game.h
as edict_shared_t
and gclient_shared_t
respectively.
The structure changes will be listed from the bottom-up. Full listings of the structures can be found in the source.
This is a new flag that is solely for the client; it indicates that a cvar is treated like userinfo for the purposes of storage, but is not sent to the server like userinfo usually is. For example, this flag is applied to cl_run_N
, which controls the individual Always Run flags for each split screen player.
This new content flag will be collided against by CONTENTS_PROJECTILE
entities.
This special content type flag is set only on player entities, and allows tracing to exclude/include them.
This special content type flag is set only on projectiles, and allows tracing to exclude/include them.
This bit is widely supported by other engines and is supported in the rerelease.
This flag is specific to N64, and halves texture sizes.
This flag is specific to N64, and causes textures to scroll in the X axis.
This flag is specific to N64, and causes textures to scroll in the Y axis.
This flag is specific to N64, and flips the scroll axis.
This structure has undergone canonization of the 3.2x changes by Zoid.
Uses the proper name length now.
This value must represent a unique ID that corresponds to its texinfo. The same ID must always reference the same texinfo, but they don't necessarily have to be sequential. Zero must always mean "no texinfo".
This is used by the client for indexing footstep sounds.
The material ID for this texinfo, from the corresponding .mat
file.
The only change is a contractual one: this value must never be null.
When a trace impacts multiple planes at the destination, the collision system will now report both of them. The "second best" plane and surface are stored here. surface2
must be null if a second surface was not hit.
This is used to solve some epsilon issues with the player movement system.
The old qboolean modified;
has been changed into an integral value. This value is increased when the cvar has been changed, but is never zero. The reason for this is so that "is cvar modified" checks always succeed on the first check, assuming you initialize the last modified value to 0.
The function Cvar_WasModified
is provided as a convenience function to perform this task for you.
A common extension to Quake II, the integral value is stored at the end of the struct for you to use.
This is a new value which sets the skin number used on the weapon.
This value sets the frame rate (in hz) of the players' weapon. For backwards compatibility, a value of 0 is equivalent to a value of 10. This ia mainly used for the Haste powerup, but in theory it could be used for future mods to have higher tickrate weapons in general.
The full-screen blend
value was split into two values: screen_blend
and damage_blend
.
screen_blend
is the same as the original one, and is a full-screen color change. It is mainly used now for full-screen fades. To reduce the amount of screen flashing,
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。