Project Icon

quake2-rerelease-dll

Quake II重制版源代码 支持模组开发和功能扩展

2023年重制版Quake II源代码提供给开发者用于模组创作。代码库整合了原游戏模块,引入新API和客户端游戏模块,扩展了模组开发空间。主要特性包括C++17支持、40Hz帧率、数学函数优化和UTF-8兼容。这些改进为Quake II带来更流畅的游戏体验和更广阔的开发前景。

Quake II Rerelease Game Source

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.

Compiling

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.

Required preprocessor definitions

  • 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.

Optional preprocessor definitions

  • 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.

Dependencies

  • fmtlib: If USE_CPP20_FORMAT is not set, the library needs to be available in the fmt subdirectory.
  • jsoncpp: Must be placed inside json subdirectory.

Both of these can also be installed via vcpkg: vcpkg install jsoncpp:x64-windows fmt:x64-windows

Windows (Visual Studio 2019 / 2022):

  • We recommend placing the source in a subfolder within a mod directory. For example, alongside 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.
  • Open game.sln
  • Build solution

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.

40hz Tickrate Support

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.

Print Adjustments

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.

Math Changes

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.

Type Changes

qboolean, which was aliased to int32_t, is now instead aliased to bool. This type should be equivalent to C's _Bool.

Info Keys

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.

Extensions

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

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.

Frame visibility

As part of network improvements, some changes were made to the "entity is visible to client in frame" methods:

  • Split-screen support since all clients share a frame.
  • Entities with shadows will be visible if their shadows may be visible to a player.
  • Sound attenuation culling is now calculated formulaically to match the sound system, and takes loop_attenuation into account.

Entity linkage

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.

Audio positioning

Entity spatialization underwent an overhaul (CL_GetEntitySoundOrigin mainly).

  • Brush models will use the closest point on the bmodel's absmin/absmax to the listener's origin. This allows moving brush models with sounds to make consistent sounds, and be full volume if you are inside of them.
  • Beams now support 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.

Client entity adjustments

  • Beam origin points are interpolated if they exist between frames.
  • TE_ELECTRIC_SPARKS and TE_SCREEN_SPARKS/TE_SHIELD_SPARKS will only play sounds once on any given frame.
  • Entities will never play the same footstep sound twice in a row.
  • Beams now squash the ends of their beams so they don't intersect walls or end early.
  • Alpha and transparency settings now get copied over to all sub-modelindices.
  • Lightramps are now interpolated, which looks nicer and helps with epilepsy.
  • 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

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.

CS_STATUSBAR

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.

CS_SHADOWLIGHTS

This new span each consists of a shadow light entry. Its format is semicolon-separated numerical values, in the following type & order:

  • int entity_order
  • int type (0 = point, 1 = cone)
  • float radius
  • int resolution
  • float intensity
  • float fade_start
  • float fade_end
  • int lightstyle
  • float coneangle
  • float direction_x
  • float direction_y
  • float direction_z

CS_WHEEL_WEAPONS

This new span consists of entries for the weapon wheel. It consists of pipe-separated integral values, in the following order:

  • CS_ITEMS item index
  • CS_IMAGES image index
  • CS_WHEEL_AMMO ammo index (or -1 for no ammo)
  • minimum ammo to use weapon
  • whether the weapon is on the powerup wheel or the weapon wheel
  • additional sort integer
  • quantity to warn on low ammo on
  • whether this weapon is droppable or not

CS_WHEEL_AMMO

This new span consists of entries for the weapon wheel ammo types. It consists of pipe-separated integral values, in the following order:

  • CS_ITEMS item index
  • CS_IMAGES image index

CS_WHEEL_POWERUPS

This new span consists of entries for the powerup wheel. It consists of pipe-separated integral values, in the following order:

  • CS_ITEMS image index
  • CS_IMAGES image index
  • if 1, it is a togglable powerup instead of having a count
  • additional sort integer
  • whether we can drop this powerup or not
  • CS_WHEEL_AMMO ammo index, if applicable (-1 for no ammo)

CS_CD_LOOP_COUNT

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).

CS_GAME_STYLE

Inform the client about the type of game being played.

Structures

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.

cvar_flags_t

CVAR_USER_PROFILE (bit 5)

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.

contents_t

CONTENTS_PROJECTILECLIP (bit 14)

This new content flag will be collided against by CONTENTS_PROJECTILE entities.

CONTENTS_PLAYER (bit 30)

This special content type flag is set only on player entities, and allows tracing to exclude/include them.

CONTENTS_PROJECTILE (bit 31)

This special content type flag is set only on projectiles, and allows tracing to exclude/include them.

surfflags_t

SURF_ALPHATEST (bit 25)

This bit is widely supported by other engines and is supported in the rerelease.

SURF_N64_UV (bit 28)

This flag is specific to N64, and halves texture sizes.

SURF_N64_SCROLL_X (bit 29)

This flag is specific to N64, and causes textures to scroll in the X axis.

SURF_N64_SCROLL_Y (bit 30)

This flag is specific to N64, and causes textures to scroll in the Y axis.

SURF_N64_SCROLL_FLIP (bit 31)

This flag is specific to N64, and flips the scroll axis.

csurface_t

This structure has undergone canonization of the 3.2x changes by Zoid.

char[32] name

Uses the proper name length now.

uint32_t id

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.

char[16] material

The material ID for this texinfo, from the corresponding .mat file.

trace_t

csurface_t *surface

The only change is a contractual one: this value must never be null.

cplane_t plane2 / csurface_t *surface2

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.

cvar_t

int32_t modified_count

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.

int32_t integer

A common extension to Quake II, the integral value is stored at the end of the struct for you to use.

player_state_t

int32_t gunskin

This is a new value which sets the skin number used on the weapon.

int32_t gunrate

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.

float[4] screen_blend / damage_blend

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,

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

稿定AI

稿定设计 是一个多功能的在线设计和创意平台,提供广泛的设计工具和资源,以满足不同用户的需求。从专业的图形设计师到普通用户,无论是进行图片处理、智能抠图、H5页面制作还是视频剪辑,稿定设计都能提供简单、高效的解决方案。该平台以其用户友好的界面和强大的功能集合,帮助用户轻松实现创意设计。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号