From acde8152911e658ec30f67d71a2fdacae9dfb6ae Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 21 Jul 2024 21:25:39 +0200 Subject: [PATCH] update --- .gitignore | 6 + camera/Camera.h | 119 ++++ camera/CameraMovement.h | 35 ++ gpuapi/RenderUtils.h | 213 +++++++ gpuapi/opengl/ShaterUtils.h | 91 +++ gpuapi/opengl/UtilsOpengl.h | 73 ++- input/Input.h | 43 +- math/matrix/MatrixFloat32.h | 182 +++++- math/matrix/QuaternionFloat32.h | 117 ++++ math/random/BlueNoise.h | 19 + models/Obj.h | 16 + models/account/Account.h | 67 +++ models/bracket/Bracket.h | 67 +++ models/bracket/BracketMatch.h | 20 + models/bracket/BracketSeeding.h | 20 + models/bracket/BracketTeam.h | 20 + models/item/Equipment.h | 14 + models/mob/MobState.h | 3 + models/mob/MobStats.h | 543 +++++++++++++++++- models/mob/player/LootFilter.h | 0 models/mob/player/Player.h | 6 +- models/mob/player/PlayerStats.h | 349 ----------- models/mob/skill/AoeDistribution.h | 9 + models/mob/skill/AoeShape.h | 12 + models/mob/skill/ProjectileDistribution.h | 11 + models/mob/skill/Skill.h | 160 ++++++ models/mob/skill/SkillLocation.h | 7 + models/mob/skill/StatsTarget.h | 18 + models/mob/skill/definitions/arcane_bolt.cfg | 0 models/mob/skill/definitions/arise.cfg | 4 + models/mob/skill/definitions/back_fist.cfg | 0 models/mob/skill/definitions/beam.cfg | 0 models/mob/skill/definitions/black_fist.cfg | 0 models/mob/skill/definitions/chain.cfg | 2 + .../mob/skill/definitions/chain_lightning.cfg | 1 + .../mob/skill/definitions/corruption_bolt.cfg | 0 models/mob/skill/definitions/cyclone.cfg | 3 + models/mob/skill/definitions/dodge.cfg | 0 models/mob/skill/definitions/earth_bolt.cfg | 0 .../mob/skill/definitions/elemental_pilar.cfg | 0 models/mob/skill/definitions/fire_bolt.cfg | 0 models/mob/skill/definitions/frost_bolt.cfg | 0 models/mob/skill/definitions/ghost_walk.cfg | 1 + models/mob/skill/definitions/holy_bolt.cfg | 0 models/mob/skill/definitions/hook.cfg | 0 models/mob/skill/definitions/kick.cfg | 0 .../mob/skill/definitions/launch_strike.cfg | 0 .../mob/skill/definitions/lightning_bolt.cfg | 0 .../mob/skill/definitions/meteor_strike.cfg | 2 + models/mob/skill/definitions/mirage.cfg | 1 + models/mob/skill/definitions/net.cfg | 2 + models/mob/skill/definitions/palm_strike.cfg | 0 .../mob/skill/definitions/poison_strike.cfg | 0 models/mob/skill/definitions/pull.cfg | 0 models/mob/skill/definitions/punch.cfg | 0 models/mob/skill/definitions/push.cfg | 0 models/mob/skill/definitions/reflect.cfg | 2 + models/mob/skill/definitions/revive.cfg | 1 + models/mob/skill/definitions/root.cfg | 0 models/mob/skill/definitions/shield.cfg | 1 + models/mob/skill/definitions/side_kick.cfg | 0 models/mob/skill/definitions/spikes.cfg | 2 + models/mob/skill/definitions/sprint.cfg | 0 models/mob/skill/definitions/stomp.cfg | 0 models/mob/skill/definitions/summon.cfg | 2 + models/mob/skill/definitions/sword_dance.cfg | 0 models/mob/skill/definitions/totem.cfg | 0 models/mob/skill/definitions/uppercut.cfg | 0 models/mob/skill/definitions/whirlwind.cfg | 0 models/mob/skill/definitions/wind_slashes.cfg | 0 models/mob/skill/modifiers/split_shot.cfg | 1 + models/settings/Settings.h | 120 ++-- network/Client.h | 21 +- network/NetworkOSWrapper.h | 19 + network/Server.h | 50 +- network/SocketConnection.h | 10 +- network/packet/PacketCache.h | 136 +++++ platform/linux/UtilsLinux.h | 146 ++++- platform/win32/UtilsWin32.h | 3 +- platform/win32/audio/DirectSound.h | 2 +- stdlib/Intrinsics.h | 2 +- stdlib/Mathtypes.h | 3 + stdlib/Types.h | 6 +- thread/Thread.h | 164 ------ thread/ThreadJob.h | 10 +- thread/ThreadOSDefines.h | 33 ++ thread/ThreadOSWrapper.h | 21 +- thread/ThreadPool.h | 168 +++++- utils/BitUtils.h | 2 + utils/BufferMemory.h | 125 ++++ utils/MathUtils.h | 57 +- utils/RingMemory.h | 17 +- utils/StringUtils.h | 40 +- utils/TestUtils.h | 45 +- utils/Utils.h | 32 -- 95 files changed, 2740 insertions(+), 757 deletions(-) create mode 100644 .gitignore create mode 100644 camera/Camera.h create mode 100644 camera/CameraMovement.h create mode 100644 gpuapi/RenderUtils.h create mode 100644 gpuapi/opengl/ShaterUtils.h create mode 100644 math/matrix/QuaternionFloat32.h create mode 100644 math/random/BlueNoise.h create mode 100644 models/account/Account.h create mode 100644 models/bracket/Bracket.h create mode 100644 models/bracket/BracketMatch.h create mode 100644 models/bracket/BracketSeeding.h create mode 100644 models/bracket/BracketTeam.h create mode 100644 models/mob/player/LootFilter.h delete mode 100644 models/mob/player/PlayerStats.h create mode 100644 models/mob/skill/AoeDistribution.h create mode 100644 models/mob/skill/AoeShape.h create mode 100644 models/mob/skill/ProjectileDistribution.h create mode 100644 models/mob/skill/Skill.h create mode 100644 models/mob/skill/SkillLocation.h create mode 100644 models/mob/skill/StatsTarget.h create mode 100644 models/mob/skill/definitions/arcane_bolt.cfg create mode 100644 models/mob/skill/definitions/arise.cfg create mode 100644 models/mob/skill/definitions/back_fist.cfg create mode 100644 models/mob/skill/definitions/beam.cfg create mode 100644 models/mob/skill/definitions/black_fist.cfg create mode 100644 models/mob/skill/definitions/chain.cfg create mode 100644 models/mob/skill/definitions/chain_lightning.cfg create mode 100644 models/mob/skill/definitions/corruption_bolt.cfg create mode 100644 models/mob/skill/definitions/cyclone.cfg create mode 100644 models/mob/skill/definitions/dodge.cfg create mode 100644 models/mob/skill/definitions/earth_bolt.cfg create mode 100644 models/mob/skill/definitions/elemental_pilar.cfg create mode 100644 models/mob/skill/definitions/fire_bolt.cfg create mode 100644 models/mob/skill/definitions/frost_bolt.cfg create mode 100644 models/mob/skill/definitions/ghost_walk.cfg create mode 100644 models/mob/skill/definitions/holy_bolt.cfg create mode 100644 models/mob/skill/definitions/hook.cfg create mode 100644 models/mob/skill/definitions/kick.cfg create mode 100644 models/mob/skill/definitions/launch_strike.cfg create mode 100644 models/mob/skill/definitions/lightning_bolt.cfg create mode 100644 models/mob/skill/definitions/meteor_strike.cfg create mode 100644 models/mob/skill/definitions/mirage.cfg create mode 100644 models/mob/skill/definitions/net.cfg create mode 100644 models/mob/skill/definitions/palm_strike.cfg create mode 100644 models/mob/skill/definitions/poison_strike.cfg create mode 100644 models/mob/skill/definitions/pull.cfg create mode 100644 models/mob/skill/definitions/punch.cfg create mode 100644 models/mob/skill/definitions/push.cfg create mode 100644 models/mob/skill/definitions/reflect.cfg create mode 100644 models/mob/skill/definitions/revive.cfg create mode 100644 models/mob/skill/definitions/root.cfg create mode 100644 models/mob/skill/definitions/shield.cfg create mode 100644 models/mob/skill/definitions/side_kick.cfg create mode 100644 models/mob/skill/definitions/spikes.cfg create mode 100644 models/mob/skill/definitions/sprint.cfg create mode 100644 models/mob/skill/definitions/stomp.cfg create mode 100644 models/mob/skill/definitions/summon.cfg create mode 100644 models/mob/skill/definitions/sword_dance.cfg create mode 100644 models/mob/skill/definitions/totem.cfg create mode 100644 models/mob/skill/definitions/uppercut.cfg create mode 100644 models/mob/skill/definitions/whirlwind.cfg create mode 100644 models/mob/skill/definitions/wind_slashes.cfg create mode 100644 models/mob/skill/modifiers/split_shot.cfg create mode 100644 network/NetworkOSWrapper.h create mode 100644 network/packet/PacketCache.h create mode 100644 thread/ThreadOSDefines.h create mode 100644 utils/BufferMemory.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..826e022 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +build/* +data/* +bin/* +*.obj +*.log +*.res \ No newline at end of file diff --git a/camera/Camera.h b/camera/Camera.h new file mode 100644 index 0000000..f767a13 --- /dev/null +++ b/camera/Camera.h @@ -0,0 +1,119 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_CAMERA_H +#define TOS_CAMERA_H + +#include "../stdlib/Types.h" +#include "../stdlib/Mathtypes.h" + +#include "../math/matrix/QuaternionFloat32.h" + +#include "CameraMovement.h" + +struct Camera { + // left handed cartesian coordinates + v3_f32 location; + v4_f32 orientation; + + float speed; + float zoom; +}; + +// you can have up to 4 camera movement inputs at the same time +void camera_movement(Camera* camera, CameraMovement* movement, float dt) +{ + f32 velocity = camera->speed * dt; + + bool has_pos = false; + v4_f32 pos; + + bool has_view = false; + v3_f32 view; + v4_f32 quaternion; + + for (int i = 0; i < 4; i++) { + switch(movement[i]) { + case CAMERA_MOVEMENT_FORWARD: { + pos.z = velocity; + has_pos = true; + } break; + case CAMERA_MOVEMENT_BACK: { + pos.z = velocity; + has_pos = true; + } break; + case CAMERA_MOVEMENT_LEFT: { + pos.x = velocity; + has_pos = true; + } break; + case CAMERA_MOVEMENT_RIGHT: { + pos.x = velocity; + has_pos = true; + } break; + case CAMERA_MOVEMENT_UP: { + pos.y = velocity; + has_pos = true; + } break; + case CAMERA_MOVEMENT_DOWN: { + pos.y = velocity; + has_pos = true; + } break; + case CAMERA_MOVEMENT_PITCH_UP: { + view.pitch += velocity; + has_view = true; + } break; + case CAMERA_MOVEMENT_PITCH_DOWN: { + view.pitch -= velocity; + has_view = true; + } break; + case CAMERA_MOVEMENT_ROLL_LEFT: { + view.roll += velocity; + has_view = true; + } break; + case CAMERA_MOVEMENT_ROLL_RIGHT: { + view.roll -= velocity; + has_view = true; + } break; + case CAMERA_MOVEMENT_YAW_LEFT: { + view.yaw += velocity; + has_view = true; + } break; + case CAMERA_MOVEMENT_YAW_RIGHT: { + view.yaw -= velocity; + has_view = true; + } break; + case CAMERA_MOVEMENT_ZOOM_IN: { + camera->zoom += velocity; + } break; + case CAMERA_MOVEMENT_ZOOM_OUT: { + camera->zoom -= velocity; + } break; + default: {} + } + } + + // A position change updates the position AND the quaternion + if (has_pos) { + // @question this might be wrong/bad since pos is not a normalized vector + v4_f32 quat_temp = camera->orientation; + quaternion_rotate_euler(&camera->orientation, &quat_temp, &pos); + + camera->location.x += pos.x; + camera->location.y += pos.y; + camera->location.z += pos.z; + } + + // A view change only updates the quaternion + if (has_view) { + v4_f32 quat_temp = camera->orientation; + quaternion_from_euler(&quaternion, &view); + quaternion_multiply(&camera->orientation, &quat_temp, &quaternion); + } +} + +#endif \ No newline at end of file diff --git a/camera/CameraMovement.h b/camera/CameraMovement.h new file mode 100644 index 0000000..6798af1 --- /dev/null +++ b/camera/CameraMovement.h @@ -0,0 +1,35 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_CAMERA_MOVEMENT_H +#define TOS_CAMERA_MOVEMENT_H + +enum CameraMovement { + CAMERA_MOVEMENT_FORWARD, + CAMERA_MOVEMENT_BACK, + + CAMERA_MOVEMENT_LEFT, + CAMERA_MOVEMENT_RIGHT, + + CAMERA_MOVEMENT_UP, + CAMERA_MOVEMENT_DOWN, + + CAMERA_MOVEMENT_PITCH_UP, + CAMERA_MOVEMENT_PITCH_DOWN, + + CAMERA_MOVEMENT_ROLL_LEFT, + CAMERA_MOVEMENT_ROLL_RIGHT, + + CAMERA_MOVEMENT_YAW_LEFT, + CAMERA_MOVEMENT_YAW_RIGHT, + + CAMERA_MOVEMENT_ZOOM_IN, + CAMERA_MOVEMENT_ZOOM_OUT +}; + +#endif \ No newline at end of file diff --git a/gpuapi/RenderUtils.h b/gpuapi/RenderUtils.h new file mode 100644 index 0000000..f55fc3d --- /dev/null +++ b/gpuapi/RenderUtils.h @@ -0,0 +1,213 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_GPUAPI_RENDER_UTILS_H +#define TOS_GPUAPI_RENDER_UTILS_H + +#include +#include +#include "../stdlib/Mathtypes.h" +#include "../math/matrix/MatrixFloat32.h" + +void make_character( + float *data, + float x, float y, float n, float m, char c) +{ + float *d = data; + + // Texture atlas is 16 characters + // 1 / 16 = 0.0625 + float a = 0.0625; + float b = 0.0625 * 2; + + // ascii offset + int w = c - 32; + + float du = (w % 16) * a; + float dv = 1 - (w / 16) * b - b; + + // Quad data (2 triangles) + *(d++) = x - n; *(d++) = y - m; + *(d++) = du + 0; *(d++) = dv; + *(d++) = x + n; *(d++) = y - m; + *(d++) = du + a; *(d++) = dv; + *(d++) = x + n; *(d++) = y + m; + *(d++) = du + a; *(d++) = dv + b; + *(d++) = x - n; *(d++) = y - m; + *(d++) = du + 0; *(d++) = dv; + *(d++) = x + n; *(d++) = y + m; + *(d++) = du + a; *(d++) = dv + b; + *(d++) = x - n; *(d++) = y + m; + *(d++) = du + 0; *(d++) = dv + b; +} + +void font_string_dimension(const char *str, v2_int32* dim, const int* width_lookup) +{ + size_t length = strlen(str); + int width = 0; + + for (int i = 0; i < length; ++i) { + if (str[i] == '\n') { + if (width > dim->x) { + dim->x = width; + } + + width = 0; + ++dim->y; + } + + width += width_lookup[str[i]]; + } + + if (width > dim->x) { + dim->x = width; + } + + if (width > 0) { + ++dim->y; + } +} + +inline +void entity_world_space(float* world_space, const float* local_space, const float* model_mat) +{ + mat4vec4_mult(model_mat, local_space, world_space); +} + +inline +void entity_view_space(float* view_space, const float* world_space, const float* view_mat) +{ + mat4vec4_mult(view_mat, world_space, view_space); +} + +inline +void entity_clip_space(float* clip_space, const float* view_space, const float* projection_mat) +{ + mat4vec4_mult(projection_mat, view_space, clip_space); +} + +inline +void entity_clip_space_mat(float* result_mat, const float* model_mat, const float* view_mat, const float* projection_mat) +{ + float temp[16]; + mat4mat4_mult(projection_mat, view_mat, temp); + mat4mat4_mult(temp, model_mat, result_mat); +} + +/** + * Create the matrix used to transform from local space to clip space + * + * This allows us to transform multiple objects with the same matrix + * + * Vclip = Mprojection * Mview * Mmodel * Vlocal + */ +void entity_clip_space_mat_sse(float* result_mat, const float* model_mat, const float* view_mat, const float* projection_mat) +{ + __m128 temp[4]; + + __m128 a[4]; + __m128 b[4]; + + a[0] = _mm_loadu_ps(projection_mat); + a[1] = _mm_loadu_ps(&projection_mat[4]); + a[2] = _mm_loadu_ps(&projection_mat[8]); + a[3] = _mm_loadu_ps(&projection_mat[12]); + + b[0] = _mm_loadu_ps(view_mat); + b[1] = _mm_loadu_ps(&view_mat[4]); + b[2] = _mm_loadu_ps(&view_mat[8]); + b[3] = _mm_loadu_ps(&view_mat[12]); + _MM_TRANSPOSE4_PS(b[0], b[1], b[2], b[3]); + + mat4mat4_mult_sse(a, b, temp); + + a[0] = temp[0]; + a[1] = temp[1]; + a[2] = temp[2]; + a[3] = temp[3]; + + b[0] = _mm_loadu_ps(model_mat); + b[1] = _mm_loadu_ps(&model_mat[4]); + b[2] = _mm_loadu_ps(&model_mat[8]); + b[3] = _mm_loadu_ps(&model_mat[12]); + _MM_TRANSPOSE4_PS(b[0], b[1], b[2], b[3]); + + mat4mat4_mult_sse(a, b, temp); + _mm_store_ps(&result_mat[0], temp[0]); + _mm_store_ps(&result_mat[4], temp[1]); + _mm_store_ps(&result_mat[8], temp[2]); + _mm_store_ps(&result_mat[12], temp[3]); +} + +inline +void entity_clip_space_from_local(float* clip_space, const float* local_space, const float* mat) +{ + mat4vec4_mult(mat, local_space, clip_space); +} + +inline +void entity_clip_space_from_local_sse(float* clip_space, const float* local_space, const float* mat) +{ + mat4vec4_mult_sse(mat, local_space, clip_space); +} + +inline +void entity_screen_space(float* screen_space, const float* clip_space, const float* viewport_mat) +{ + // @todo implement +} + +inline +void entity_world_space_sse(float* world_space, const float* local_space, const float* model_mat) +{ + mat4vec4_mult_sse(model_mat, local_space, world_space); +} + +inline +void entity_view_space_sse(float* view_space, const float* world_space, const float* view_mat) +{ + mat4vec4_mult_sse(view_mat, world_space, view_space); +} + +inline +void entity_clip_space_sse(float* clip_space, const float* view_space, const float* projection_mat) +{ + mat4vec4_mult_sse(projection_mat, view_space, clip_space); +} + +inline +void entity_screen_space_sse(float* screen_space, const float* clip_space, const float* viewport_mat) +{ + // @todo implement +} + +inline +void entity_world_space_sse(__m128* world_space, const __m128* local_space, const __m128* model_mat) +{ + mat4vec4_mult_sse(model_mat, local_space, world_space); +} + +inline +void entity_view_space_sse(__m128* view_space, const __m128* world_space, const __m128* view_mat) +{ + mat4vec4_mult_sse(view_mat, world_space, view_space); +} + +inline +void entity_clip_space_sse(__m128* clip_space, const __m128* view_space, const __m128* projection_mat) +{ + mat4vec4_mult_sse(projection_mat, view_space, clip_space); +} + +inline +void entity_screen_space_sse(__m128* screen_space, const __m128* clip_space, const __m128* viewport_mat) +{ + // @todo implement +} + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/ShaterUtils.h b/gpuapi/opengl/ShaterUtils.h new file mode 100644 index 0000000..20905c0 --- /dev/null +++ b/gpuapi/opengl/ShaterUtils.h @@ -0,0 +1,91 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_GPUAPI_OPENGL_SHADER_UTILS_H +#define TOS_GPUAPI_OPENGL_SHADER_UTILS_H + +#include "../../../EngineDependencies/opengl/glew/include/GL/glew.h" +#include "../../../EngineDependencies/opengl/glfw/include/glfw3.h" + +#include "../../stdlib/Types.h" + +inline +void shader_set_value(uint32 id, const char* name, bool value) +{ + glUniform1i(glGetUniformLocation(id, name), (int) value); +} + +inline +void shader_set_value(uint32 id, const char* name, int value) +{ + glUniform1i(glGetUniformLocation(id, name), value); +} + +inline +void shader_set_value(uint32 id, const char* name, float value) +{ + glUniform1f(glGetUniformLocation(id, name), value); +} + +inline +void shader_set_v2(uint32 id, const char* name, float* value) +{ + glUniform2fv(glGetUniformLocation(id, name), 1, value); +} + +inline +void shader_set_v3(uint32 id, const char* name, float* value) +{ + glUniform3fv(glGetUniformLocation(id, name), 1, value); +} + +inline +void shader_set_v4(uint32 id, const char* name, float* value) +{ + glUniform4fv(glGetUniformLocation(id, name), 1, value); +} + +inline +void shader_set_m2(uint32 id, const char* name, float* value) +{ + glUniformMatrix2fv(glGetUniformLocation(id, name), 1, GL_FALSE, value); +} + +inline +void shader_set_m3(uint32 id, const char* name, float* value) +{ + glUniformMatrix3fv(glGetUniformLocation(id, name), 1, GL_FALSE, value); +} + +inline +void shader_set_m4(uint32 id, const char* name, float* value) +{ + glUniformMatrix4fv(glGetUniformLocation(id, name), 1, GL_FALSE, value); +} + +inline +void shader_check_link_errors(uint32 id, char* log) +{ + GLint success; + glGetProgramiv(id, GL_LINK_STATUS, &success); + if (!success) { + glGetProgramInfoLog(id, 1024, NULL, log); + } +} + +inline +void shader_check_compile_errors(uint32 id, char* log) +{ + GLint success; + glGetShaderiv(id, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(id, 1024, NULL, log); + } +} + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/UtilsOpengl.h b/gpuapi/opengl/UtilsOpengl.h index e087636..aafd855 100644 --- a/gpuapi/opengl/UtilsOpengl.h +++ b/gpuapi/opengl/UtilsOpengl.h @@ -14,6 +14,7 @@ #include "../../models/Attrib.h" #include "../../models/Texture.h" +#include "../RenderUtils.h" #include "../../../EngineDependencies/opengl/glew/include/GL/glew.h" #include "../../../EngineDependencies/opengl/glfw/include/glfw3.h" @@ -54,7 +55,7 @@ void window_create(Window* window, void*) NULL ); - glfwSetInputMode(window->hwnd_lib, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + //glfwSetInputMode(window->hwnd_lib, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwMakeContextCurrent(window->hwnd_lib); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); @@ -109,13 +110,14 @@ uint32 get_texture_data_type(uint32 texture_data_type) } } +// 1. prepare_texture +// 2. define wrap +// 3. define filter +// 4. load_texture_to_gpu + inline void prepare_texture(TextureFile* texture, uint32 texture_unit) { - if (texture->id) { - return; - } - uint32 texture_data_type = get_texture_data_type(texture->texture_data_type); glGenTextures(1, (GLuint *) &texture->id); @@ -133,6 +135,15 @@ void load_texture_to_gpu(const TextureFile* texture) 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->image.pixels ); + + // @question use mipmap? +} + +inline +void texture_use(const TextureFile* texture, uint32 texture_unit) +{ + glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(GL_TEXTURE_2D, texture->id); } GLuint make_shader(GLenum type, const char *source, RingMemory* ring) @@ -152,8 +163,7 @@ GLuint make_shader(GLenum type, const char *source, RingMemory* ring) glGetShaderInfoLog(shader, length, NULL, info); - // @todo use global logger - fprintf(stderr, "glCompileShader failed:\n%s\n", info); + // @todo log } return shader; @@ -166,6 +176,7 @@ GLuint load_shader(GLenum type, const char *path, RingMemory* ring) { file_body file; file.content = ring_get_memory(ring, MEGABYTE * 4); + // @todo consider to accept file as parameter and load file before file_read(path, &file); GLuint result = make_shader(type, (const char *) file.content, ring); @@ -198,8 +209,11 @@ GLuint make_program(GLuint shader1, GLuint shader2, RingMemory* ring) { fprintf(stderr, "glLinkProgram failed: %s\n", info); } + // @question really? glDetachShader(program, shader1); glDetachShader(program, shader2); + + // @question really? glDeleteShader(shader1); glDeleteShader(shader2); @@ -215,8 +229,9 @@ GLuint load_program(const char *path1, const char *path2, RingMemory* ring) { } inline -void activate_texture(TextureFile* texture, uint32 texture_unit) +void shader_use(uint32 id) { + glUseProgram(id); } void draw_triangles_3d(Attrib *attrib, GLuint buffer, int count) { @@ -296,16 +311,44 @@ int calculate_face_size(int components, int faces) // generates faces // data is no longer needed after this inline -GLuint gpuapi_buffer_generate(int size, GLfloat *data) +uint32 gpuapi_buffer_generate(int size, f32 *data) { - GLuint buffer; + uint32 vbo; - glGenBuffers(1, &buffer); - glBindBuffer(GL_ARRAY_BUFFER, buffer); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - return buffer; + return vbo; +} + +inline +uint32 gpuapi_buffer_element_generate(int size, uint32 *data) +{ + uint32 ebo; + + glGenBuffers(1, &ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + + return ebo; +} + +inline +uint32 gpuapi_vertex_array_generate() +{ + uint32 vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + return vao; +} + +inline +void gpuapi_unbind_all() +{ + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); } inline @@ -314,6 +357,4 @@ void gpuapi_buffer_delete(GLuint buffer) glDeleteBuffers(1, &buffer); } - - #endif \ No newline at end of file diff --git a/input/Input.h b/input/Input.h index 26be4b5..4b84bc9 100644 --- a/input/Input.h +++ b/input/Input.h @@ -9,7 +9,7 @@ #ifndef TOS_INPUT_H #define TOS_INPUT_H -#define MAX_KEY_PRESSES 4 +#define MAX_KEY_PRESSES 5 #define MIN_INPUT_DEVICES 2 #define INPUT_TYPE_MOUSE 0x01 @@ -38,16 +38,12 @@ struct InputState { HANDLE handle_mouse; #endif - // Keyboard - bool key_down = false; - bool key_up = false; - uint16 key = 0; - // After handling the keyboard state change the game loop should set this to false bool state_change_keyboard = false; // We only consider up to 4 pressed keys // Depending on the keyboard you may only be able to detect a limited amount of key presses anyway + uint16 keys_down_old[MAX_KEY_PRESSES]; uint16 keys_down[MAX_KEY_PRESSES]; // Mouse @@ -60,20 +56,10 @@ struct InputState { uint32 x_last; uint32 y_last; - bool mouse1_down = false; - bool mouse1_up = false; - - bool mouse2_down = false; - bool mouse2_up = false; - - bool mouse3_down = false; - bool mouse3_up = false; - - bool mouse4_down = false; - bool mouse4_up = false; - - bool mouse5_down = false; - bool mouse5_up = false; + // https://usb.org/sites/default/files/hid1_11.pdf Page 71 or 61 + // @question consider to use bit field (one int32 would be sufficient) + bool mouse_down_old[18]; + bool mouse1_down[18]; int16 wheel_delta = 0; uint32 raw_button = 0; @@ -86,23 +72,18 @@ struct ControllerState { // After handling the state change the game loop should set this to false bool state_change = false; + // @question maybe make part of button bool up = false; bool down = false; bool left = false; bool right = false; - bool start = false; - bool back = false; - bool shoulder_left = false; - bool shoulder_right = false; + byte trigger_old[4]; + byte trigger[4]; - byte trigger_left = 0; - byte trigger_right = 0; - - bool button_a = false; - bool button_b = false; - bool button_x = false; - bool button_y = false; + // @question consider to use bit field (one int32 would be sufficient) + bool button_old[10]; + bool button[10]; int16 stickl_x = 0; int16 stickl_y = 0; diff --git a/math/matrix/MatrixFloat32.h b/math/matrix/MatrixFloat32.h index 74d1d51..3e91dc0 100644 --- a/math/matrix/MatrixFloat32.h +++ b/math/matrix/MatrixFloat32.h @@ -10,6 +10,7 @@ #define TOS_MATH_MATRIX_FLOAT32_H #include "../../stdlib/Intrinsics.h" +#include "../../stdlib/Mathtypes.h" #include "../../utils/MathUtils.h" void mat3_identity_f32(float* matrix) @@ -105,6 +106,7 @@ void mat3vec3_mult(const float* matrix, const float* vector, float* result) */ } +// @question could simple mul add sse be faster? void mat3vec3_mult_sse(const float* matrix, const float* vector, float* result) { __m128 vec = _mm_loadu_ps(vector); @@ -120,6 +122,7 @@ void mat3vec3_mult_sse(const float* matrix, const float* vector, float* result) } } +// @question could simple mul add sse be faster? void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, float* result) { for (int i = 0; i < 3; ++i) { @@ -129,6 +132,7 @@ void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, float* result } } +// @question could simple mul add sse be faster? void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, __m128* result) { for (int i = 0; i < 4; ++i) { @@ -142,17 +146,9 @@ void mat4vec4_mult(const float* matrix, const float* vector, float* result) result[1] = matrix[4] * vector[0] + matrix[5] * vector[1] + matrix[6] * vector[2] + matrix[7] * vector[3]; result[2] = matrix[8] * vector[0] + matrix[9] * vector[1] + matrix[10] * vector[2] + matrix[11] * vector[3]; result[3] = matrix[12] * vector[0] + matrix[13] * vector[1] + matrix[14] * vector[2] + matrix[15] * vector[3]; - - /* - for (int i = 0; i < 4; ++i) { - result[i] = matrix[i * 4 + 0] * vector[0] - + matrix[i * 4 + 1] * vector[1] - + matrix[i * 4 + 2] * vector[2] - + matrix[i * 4 + 3] * vector[3]; - } - */ } +// @question could simple mul add sse be faster? void mat4vec4_mult_sse(const float* matrix, const float* vector, float* result) { __m128 vec = _mm_loadu_ps(vector); @@ -165,6 +161,7 @@ void mat4vec4_mult_sse(const float* matrix, const float* vector, float* result) } } +// @question could simple mul add sse be faster? void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, float* result) { for (int i = 0; i < 4; ++i) { @@ -174,6 +171,7 @@ void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, float* result } } +// @question could simple mul add sse be faster? void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, __m128* result) { for (int i = 0; i < 4; ++i) { @@ -181,6 +179,172 @@ void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, __m128* resul } } +void mat4mat4_mult(const float* a, const float* b, float* result) +{ + // Row 0 + result[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12]; + result[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13]; + result[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14]; + result[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15]; + + // Row 1 + result[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12]; + result[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13]; + result[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14]; + result[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15]; + + // Row 2 + result[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12]; + result[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13]; + result[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14]; + result[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15]; + + // Row 3 + result[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12]; + result[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13]; + result[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14]; + result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15]; +} + +void mat4mat4_mult_sse(const float* a, const float* b, float* result) +{ + // @todo check http://fhtr.blogspot.com/2010/02/4x4-float-matrix-multiplication-using.html + // @question could simple mul add sse be faster? + __m128 a_1 = _mm_loadu_ps(a); + __m128 a_2 = _mm_loadu_ps(&a[4]); + __m128 a_3 = _mm_loadu_ps(&a[8]); + __m128 a_4 = _mm_loadu_ps(&a[12]); + + __m128 b_1 = _mm_loadu_ps(b); + __m128 b_2 = _mm_loadu_ps(&b[4]); + __m128 b_3 = _mm_loadu_ps(&b[8]); + __m128 b_4 = _mm_loadu_ps(&b[12]); + _MM_TRANSPOSE4_PS(b_1, b_2, b_3, b_4); + + __m128 dot; + + // b1 + dot = _mm_dp_ps(a_1, b_1, 0xF1); + result[0] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_2, b_1, 0xF1); + result[1] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_3, b_1, 0xF1); + result[2] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_4, b_1, 0xF1); + result[3] = _mm_cvtss_f32(dot); + + // b2 + dot = _mm_dp_ps(a_1, b_2, 0xF1); + result[4] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_2, b_2, 0xF1); + result[5] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_3, b_2, 0xF1); + result[6] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_4, b_2, 0xF1); + result[7] = _mm_cvtss_f32(dot); + + // b3 + dot = _mm_dp_ps(a_1, b_3, 0xF1); + result[8] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_2, b_3, 0xF1); + result[9] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_3, b_3, 0xF1); + result[10] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_4, b_3, 0xF1); + result[11] = _mm_cvtss_f32(dot); + + // b4 + dot = _mm_dp_ps(a_1, b_4, 0xF1); + result[12] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_2, b_4, 0xF1); + result[13] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_3, b_4, 0xF1); + result[14] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a_4, b_4, 0xF1); + result[15] = _mm_cvtss_f32(dot); +} + +void mat4mat4_mult_sse(const __m128* a, const __m128* b_transposed, float* result) +{ + __m128 dot; + + // @question could simple mul add sse be faster? + // b1 + dot = _mm_dp_ps(a[0], b_transposed[0], 0xF1); + result[0] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[1], b_transposed[0], 0xF1); + result[1] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[2], b_transposed[0], 0xF1); + result[2] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[3], b_transposed[0], 0xF1); + result[3] = _mm_cvtss_f32(dot); + + // b2 + dot = _mm_dp_ps(a[0], b_transposed[1], 0xF1); + result[4] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[1], b_transposed[1], 0xF1); + result[5] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[2], b_transposed[1], 0xF1); + result[6] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[3], b_transposed[1], 0xF1); + result[7] = _mm_cvtss_f32(dot); + + // b3 + dot = _mm_dp_ps(a[0], b_transposed[2], 0xF1); + result[8] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[1], b_transposed[2], 0xF1); + result[9] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[2], b_transposed[2], 0xF1); + result[10] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[3], b_transposed[2], 0xF1); + result[11] = _mm_cvtss_f32(dot); + + // b4 + dot = _mm_dp_ps(a[0], b_transposed[3], 0xF1); + result[12] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[1], b_transposed[3], 0xF1); + result[13] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[2], b_transposed[3], 0xF1); + result[14] = _mm_cvtss_f32(dot); + + dot = _mm_dp_ps(a[3], b_transposed[3], 0xF1); + result[15] = _mm_cvtss_f32(dot); +} + +void mat4mat4_mult_sse(const __m128* a, const __m128* b_transpose, __m128* result) +{ + for (int i = 0; i < 4; ++i) { + result[i] = _mm_mul_ps(a[0], b_transpose[i]); + + for (int j = 1; j < 4; ++j) { + result[i] = _mm_add_ps(_mm_mul_ps(a[j], b_transpose[4 * j + i]), result[i]); + } + } +} + // @question Consider to replace with 1d array void frustum_planes(float planes[6][4], int radius, float *matrix) { // @todo make this a setting diff --git a/math/matrix/QuaternionFloat32.h b/math/matrix/QuaternionFloat32.h new file mode 100644 index 0000000..f19b14c --- /dev/null +++ b/math/matrix/QuaternionFloat32.h @@ -0,0 +1,117 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H +#define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H + +#include "../../stdlib/Intrinsics.h" +#include "../../stdlib/Mathtypes.h" +#include "../../utils/MathUtils.h" + +void quaternion_from_euler(v4_f32* quat, float pitch, float yaw, float roll) +{ + float y = OMS_RAD2DEG(yaw * 0.5f); + float cy = cosf_approx(y); + float sy = sinf_approx(y); + + float p = OMS_RAD2DEG(pitch * 0.5f); + float cp = cosf_approx(p); + float sp = sinf_approx(p); + + float r = OMS_RAD2DEG(roll * 0.5f); + float cr = cosf_approx(r); + float sr = sinf_approx(r); + + quat->w = cr * cp * cy + sr * sp * sy; + quat->x = sr * cp * cy - cr * sp * sy; + quat->y = cr * sp * cy + sr * cp * sy; + quat->z = cr * cp * sy - sr * sp * cy; +} + +void quaternion_from_euler(v4_f32* quat, const v3_f32* v) +{ + float y = OMS_RAD2DEG(v->y * 0.5f); + float cy = cosf_approx(y); + float sy = sinf_approx(y); + + float p = OMS_RAD2DEG(v->x * 0.5f); + float cp = cosf_approx(p); + float sp = sinf_approx(p); + + float r = OMS_RAD2DEG(v->z * 0.5f); + float cr = cosf_approx(r); + float sr = sinf_approx(r); + + quat->w = cr * cp * cy + sr * sp * sy; + quat->x = sr * cp * cy - cr * sp * sy; + quat->y = cr * sp * cy + sr * cp * sy; + quat->z = cr * cp * sy - sr * sp * cy; +} + +void euler_from_quaternion(const v4_f32* quat, v3_f32* v) { + // Pitch + float sinp = 2.0f * (quat->w * quat->x + quat->y * quat->z); + float cosp = 1.0f - 2.0f * (quat->x * quat->x + quat->y * quat->y); + v->pitch = atan2f_approx(sinp, cosp); + + // Yaw + float siny = 2.0f * (quat->w * quat->y - quat->z * quat->x); + + if (siny >= 1.0f) { + v->yaw = OMS_PI_OVER_TWO; + } else if (siny <= -1.0f ) { + v->yaw = -OMS_PI_OVER_TWO; + } else { + v->yaw = asinf_approx(siny); + } + + // Roll + float sinr = 2.0f * (quat->w * quat->z + quat->x * quat->y); + float cosr = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z); + v->roll = atan2f_approx(sinr, cosr); +} + +void quaternion_multiply(v4_f32* quat, const v4_f32* quat1, const v4_f32* quat2) +{ + quat->w = quat1->w * quat2->w - quat1->x * quat2->x - quat1->y * quat2->y - quat1->z * quat2->z; + quat->x = quat1->w * quat2->x + quat1->x * quat2->w + quat1->y * quat2->z - quat1->z * quat2->y; + quat->y = quat1->w * quat2->y - quat1->x * quat2->z + quat1->y * quat2->w + quat1->z * quat2->x; + quat->z = quat1->w * quat2->z + quat1->x * quat2->y - quat1->y * quat2->x + quat1->z * quat2->w; +} + +void quaternion_inverse(v4_f32* quat, const v4_f32* quat_origin) { + float norm = quat_origin->w * quat_origin->w + + quat_origin->x * quat_origin->x + + quat_origin->y * quat_origin->y + + quat_origin->z * quat_origin->z; + + quat->w = quat_origin->w / norm; + quat->x = -quat_origin->x / norm; + quat->y = -quat_origin->y / norm; + quat->z = -quat_origin->z / norm; +} + +inline +void quaternion_rotate_euler(v4_f32* quat, const v4_f32* quat_origin, const v4_f32* euler) +{ + quaternion_multiply(quat, quat_origin, euler); +} + +inline +void quaternion_rotate_quaternion(v4_f32* quat, const v4_f32* quat_origin, const v4_f32* quat_rot) +{ + v4_f32 quat_tmp; + quaternion_multiply(&quat_tmp, quat_rot, quat_origin); + + v4_f32 rot_; + quaternion_inverse(&rot_, quat_rot); + + quaternion_multiply(quat, &quat_tmp, &rot_); +} + +#endif \ No newline at end of file diff --git a/math/random/BlueNoise.h b/math/random/BlueNoise.h new file mode 100644 index 0000000..4bb9a23 --- /dev/null +++ b/math/random/BlueNoise.h @@ -0,0 +1,19 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MATH_RANDOM_BLUE_NOISE +#define TOS_MATH_RANDOM_BLUE_NOISE + +#include "../../stdlib/Types.h" + +// @todo Implement poisson disc sampling for 2d and sphere +// https://observablehq.com/@jrus/bridson-fork/2 +// https://observablehq.com/@jrus/spheredisksample + +#endif \ No newline at end of file diff --git a/models/Obj.h b/models/Obj.h index 4e0b627..2dd61b1 100644 --- a/models/Obj.h +++ b/models/Obj.h @@ -12,6 +12,22 @@ #include "../stdlib/Types.h" struct ObjFile { + // Amount of references to this object + int references; + + bool facing; // front or back + + void* buffer; + void* facingness; + void* normals; + void* uvs; + void* parallaxs; + + void* animations; + void* textures; // could be texture maps + void* mipmaps; + void* samplers; + void* materials; }; #endif \ No newline at end of file diff --git a/models/account/Account.h b/models/account/Account.h new file mode 100644 index 0000000..e2b0359 --- /dev/null +++ b/models/account/Account.h @@ -0,0 +1,67 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MODELS_ACCOUNT_H +#define TOS_MODELS_ACCOUNT_H + +#include "../../stdlib/Types.h" + +#ifndef MAX_CHAR_NAME_LENGTH + #define MAX_CHAR_NAME_LENGTH 32 +#endif + +struct Account { + uint64 id; + char name[MAX_CHAR_NAME_LENGTH]; + + // relative memory position + int64 index; + + // @question Maybe add pointers to Player, PacketCache? +}; + +/** + * Whenever a user connects to the game server we immediately need to allocate a fixed amount of data. + * Instead of putting this data willy-nilly into memory we can put all the user/account data always at the + * same offset respective to the memory area of that data type. + * + * e.g. this means that if the account with the id X is found at position 12 in memory (not in the hashmap) + * the player and packet cache are also all located at position 12 in memory in their respective buffers + * this means we only have to find the memory position ONCE and we know where all the other data is of that account + * this also means we don't have to chase too many pointers + * + * @performance It might be faster to make Player and PacketCache part of the Account? + * It really depends on how we perform the game loop + * Are we handling account by account OR (probably should be inside account for L1 cache) + * Are we handling one data type by data type (then this is correct) + */ +void account_init_game_connect(Account* accounts, Player* players, PacketCache* packet_cache) +{ + int64 index = -1; + + if (index < 0) { + return; + } + + // init account + Account* temp_acc = accounts[index]; + temp_acc->index = index; + + // init player + Player* temp_player = players[index]; + + // init packet cache + PacketCache* temp_packets = packet_cache[index]; +} + +void account_free_game_disconnect() +{ + +} + +#endif \ No newline at end of file diff --git a/models/bracket/Bracket.h b/models/bracket/Bracket.h new file mode 100644 index 0000000..2d1a828 --- /dev/null +++ b/models/bracket/Bracket.h @@ -0,0 +1,67 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MODELS_BRACKET_SIMPLE_BRACKET_H +#define TOS_MODELS_BRACKET_SIMPLE_BRACKET_H + +#include "BracketTeam.h" +#include "BracketSeeding.h" +#include "BracketMatch.h" + +struct SimpleBracket { + int size; + BracketMatch* matches; + BracketSeeding seeding; +}; + +struct DoubleEliminationBracket { + SimpleBracket winners_bracket; + SimpleBracket losers_bracket; +}; + +void bracket_single_elim_create(SimpleBracket* bracket) +{ + for (int i = 0; i < bracket->size / 2; ++i) { + bracket->matches[i].teams[0] = &bracket->seeding.teams[bracket->seeding.team_seedings[i]]; + bracket->matches[i].teams[1] = &bracket->seeding.teams[bracket->seeding.team_seedings[bracket->size - i - 1]]; + } + + int j = 0; + for (int i = bracket->size / 2; bracket->size - 1; ++i) { + bracket->matches[i].teams[0] = bracket->matches[j].winner; + bracket->matches[i].teams[0] = bracket->matches[++j].winner; + ++j; + } +} + +void bracket_double_elim_create(DoubleEliminationBracket* bracket) +{ + bracket_single_elim_create(&bracket->winners_bracket); + + int match_index = 0; + for (int i = 0; i < bracket->winners_bracket.size - 1; ++i) { + if (i % 2 == 0) { + bracket->losers_bracket.matches[match_index].teams[0] = bracket->winners_bracket.matches[i].loser; + bracket->losers_bracket.matches[match_index].teams[1] = bracket->winners_bracket.matches[i + 1].loser; + ++match_index; + } else { + bracket->losers_bracket.matches[match_index].teams[0] = bracket->losers_bracket.matches[match_index - 1].winner; + bracket->losers_bracket.matches[match_index].teams[1] = bracket->winners_bracket.matches[i + 1].loser; + ++match_index; + } + } + + int j = 0; + for (int i = match_index; i < bracket->losers_bracket.size - 1; ++i) { + bracket->losers_bracket.matches[i].teams[0] = bracket->losers_bracket.matches[j].winner; + bracket->losers_bracket.matches[i].teams[1] = bracket->losers_bracket.matches[++j].winner; + ++j; + } +} + +#endif \ No newline at end of file diff --git a/models/bracket/BracketMatch.h b/models/bracket/BracketMatch.h new file mode 100644 index 0000000..6eb7c14 --- /dev/null +++ b/models/bracket/BracketMatch.h @@ -0,0 +1,20 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MODELS_BRACKET_MATCH_H +#define TOS_MODELS_BRACKET_MATCH_H + +#include "BracketTeam.h" + +struct BracketMatch { + BracketTeam* teams[2]; + BracketTeam* winner; + BracketTeam* loser; +}; + +#endif \ No newline at end of file diff --git a/models/bracket/BracketSeeding.h b/models/bracket/BracketSeeding.h new file mode 100644 index 0000000..697fb26 --- /dev/null +++ b/models/bracket/BracketSeeding.h @@ -0,0 +1,20 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MODELS_BRACKET_SEEDING_H +#define TOS_MODELS_BRACKET_SEEDING_H + +#include "../../stdlib/Types.h" +#include "BracketTeam.h" + +struct BracketSeeding { + BracketTeam* teams; + uint32* team_seedings; // stores the index of the respective seed, index + 1 = seed +}; + +#endif \ No newline at end of file diff --git a/models/bracket/BracketTeam.h b/models/bracket/BracketTeam.h new file mode 100644 index 0000000..74e695e --- /dev/null +++ b/models/bracket/BracketTeam.h @@ -0,0 +1,20 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MODELS_BRACKET_TEAM_H +#define TOS_MODELS_BRACKET_TEAM_H + +#include "../../stdlib/Types.h" + +struct BracketTeam { + int size; + uint64* player_ids; + uint32 rating; +}; + +#endif \ No newline at end of file diff --git a/models/item/Equipment.h b/models/item/Equipment.h index 23af979..950a48f 100644 --- a/models/item/Equipment.h +++ b/models/item/Equipment.h @@ -11,9 +11,23 @@ #include "../../stdlib/Types.h" +#include "../../mob/MobStats.h" +#include "../../mob/skill/StatsTarget.h" + struct Equipment { byte type; char* name; + + // @tood how to handle multiplicative stats? + // you can have 2 stats for 2 target types (e.g. you could create a buff and debuff in one skill) + SMobStats stats1; + StatsTarget stats1_target; + + SMobStats stats2; + StatsTarget stats2_target; + + // @todo probably add more of the Skill attributes here + // @question what should be part of skills and what should be part of items?!?!?!? }; #endif \ No newline at end of file diff --git a/models/mob/MobState.h b/models/mob/MobState.h index 7bb6f93..1d84acf 100644 --- a/models/mob/MobState.h +++ b/models/mob/MobState.h @@ -24,7 +24,10 @@ struct MobState { // last 3 bytes = animation to use uint32 action = (MOB_ACTION_INACTIVE << 24); + bool in_battle; + int chunk_id; + byte environment; // dungeon/raid, pvp-openworld, pvp, pvp-tournament, open-world, instance-private, instance-invite, housing, }; #endif \ No newline at end of file diff --git a/models/mob/MobStats.h b/models/mob/MobStats.h index 5183eed..5839286 100644 --- a/models/mob/MobStats.h +++ b/models/mob/MobStats.h @@ -1,6 +1,547 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ #ifndef TOS_MODELS_MOB_STATS_H #define TOS_MODELS_MOB_STATS_H -#include "../../../stdlib/Types.h" +#include "../../stdlib/Types.h" + +struct SMobStatsTotal { + byte stat_str; // strength : effects health + base damage + byte stat_int; // inteligence : effects resource + base demage + byte stat_acc; // accuracy : effects critical chance + base damage + miss chance + byte stat_agi; // agility : effects resource + base damage + dodge change + byte stat_def; // defense : effects resource + base defense + dodge change + byte stat_sta; // stamina : effects health regen + resource regen + + // Naming conventions + // : total + // _base : character stats (see stat_ above) + // _equip : character equipment + // _item : other item effects (consumables, e.g. potions) + // _effect : external aoe/skill effect + // _skill : own skill + + // Damage types + uint32 dmg; + uint32 dmg_base; + uint32 dmg_equip; + uint32 dmg_item; + uint32 dmg_effect; + uint32 dmg_skill; + + uint32 dmg_pircing; + uint32 dmg_pircing_base; + uint32 dmg_pircing_equip; + uint32 dmg_pircing_item; + uint32 dmg_pircing_effect; + uint32 dmg_pircing_skill; + + uint32 dmg_slashing; + uint32 dmg_slashing_base; + uint32 dmg_slashing_equip; + uint32 dmg_slashing_item; + uint32 dmg_slashing_effect; + uint32 dmg_slashing_skill; + + uint32 dmg_bludgeoning; + uint32 dmg_bludgeoning_base; + uint32 dmg_bludgeoning_equip; + uint32 dmg_bludgeoning_item; + uint32 dmg_bludgeoning_effect; + uint32 dmg_bludgeoning_skill; + + uint32 dmg_stabbing; + uint32 dmg_stabbing_base; + uint32 dmg_stabbing_equip; + uint32 dmg_stabbing_item; + uint32 dmg_stabbing_effect; + uint32 dmg_stabbing_skill; + + uint32 dmg_fire; + uint32 dmg_fire_base; + uint32 dmg_fire_equip; + uint32 dmg_fire_item; + uint32 dmg_fire_effect; + uint32 dmg_fire_skill; + + uint32 dmg_water; + uint32 dmg_water_base; + uint32 dmg_water_equip; + uint32 dmg_water_item; + uint32 dmg_water_effect; + uint32 dmg_water_skill; + + uint32 dmg_ice; + uint32 dmg_ice_base; + uint32 dmg_ice_equip; + uint32 dmg_ice_item; + uint32 dmg_ice_effect; + uint32 dmg_ice_skill; + + uint32 dmg_earth; + uint32 dmg_earth_base; + uint32 dmg_earth_equip; + uint32 dmg_earth_item; + uint32 dmg_earth_effect; + uint32 dmg_earth_skill; + + uint32 dmg_wind; + uint32 dmg_wind_base; + uint32 dmg_wind_equip; + uint32 dmg_wind_item; + uint32 dmg_wind_effect; + uint32 dmg_wind_skill; + + uint32 dmg_poison; + uint32 dmg_poison_base; + uint32 dmg_poison_equip; + uint32 dmg_poison_item; + uint32 dmg_poison_effect; + uint32 dmg_poison_skill; + + uint32 dmg_lightning; + uint32 dmg_lightning_base; + uint32 dmg_lightning_equip; + uint32 dmg_lightning_item; + uint32 dmg_lightning_effect; + uint32 dmg_lightning_skill; + + uint32 dmg_holy; + uint32 dmg_holy_base; + uint32 dmg_holy_equip; + uint32 dmg_holy_item; + uint32 dmg_holy_effect; + uint32 dmg_holy_skill; + + uint32 dmg_arcane; + uint32 dmg_arcane_base; + uint32 dmg_arcane_equip; + uint32 dmg_arcane_item; + uint32 dmg_arcane_effect; + uint32 dmg_arcane_skill; + + uint32 dmg_corrupted; + uint32 dmg_corrupted_base; + uint32 dmg_corrupted_equip; + uint32 dmg_corrupted_item; + uint32 dmg_corrupted_effect; + uint32 dmg_corrupted_skill; + + uint32 dmg_crit; + uint32 dmg_crit_base; + uint32 dmg_crit_equip; + uint32 dmg_crit_item; + uint32 dmg_crit_effect; + uint32 dmg_crit_skill; + + f32 dmg_crit_chance; + f32 dmg_crit_chance_base; + f32 dmg_crit_chance_equip; + f32 dmg_crit_chance_item; + f32 dmg_crit_chance_effect; + f32 dmg_crit_chance_skill; + + uint32 dmg_reflection; + uint32 dmg_reflection_base; + uint32 dmg_reflection_equip; + uint32 dmg_reflection_item; + uint32 dmg_reflection_effect; + uint32 dmg_reflection_skill; + + // Health & Resource + uint32 health; + uint32 health_base; + uint32 health_equip; + uint32 health_item; + uint32 health_effect; + uint32 health_skill; + + uint32 health_on_dmg_dealt; + uint32 health_on_dmg_dealt_base; + uint32 health_on_dmg_dealt_equip; + uint32 health_on_dmg_dealt_item; + uint32 health_on_dmg_dealt_effect; + uint32 health_on_dmg_dealt_skill; + + uint32 health_on_dmg_taken; + uint32 health_on_dmg_taken_base; + uint32 health_on_dmg_taken_equip; + uint32 health_on_dmg_taken_item; + uint32 health_on_dmg_taken_effect; + uint32 health_on_dmg_taken_skill; + + uint32 health_regen; + uint32 health_regen_base; + uint32 health_regen_equip; + uint32 health_regen_item; + uint32 health_regen_effect; + uint32 health_regen_skill; + + uint32 health_regen_on_dmg_dealt; + uint32 health_regen_on_dmg_dealt_base; + uint32 health_regen_on_dmg_dealt_equip; + uint32 health_regen_on_dmg_dealt_item; + uint32 health_regen_on_dmg_dealt_effect; + uint32 health_regen_on_dmg_dealt_skill; + + uint32 health_regen_on_dmg_taken; + uint32 health_regen_on_dmg_taken_base; + uint32 health_regen_on_dmg_taken_equip; + uint32 health_regen_on_dmg_taken_item; + uint32 health_regen_on_dmg_taken_effect; + uint32 health_regen_on_dmg_taken_skill; + + uint32 resource; + uint32 resource_base; + uint32 resource_equip; + uint32 resource_item; + uint32 resource_effect; + uint32 resource_skill; + + uint32 resource_on_dmg_dealt; + uint32 resource_on_dmg_dealt_base; + uint32 resource_on_dmg_dealt_equip; + uint32 resource_on_dmg_dealt_item; + uint32 resource_on_dmg_dealt_effect; + uint32 resource_on_dmg_dealt_skill; + + uint32 resource_on_dmg_taken; + uint32 resource_on_dmg_taken_base; + uint32 resource_on_dmg_taken_equip; + uint32 resource_on_dmg_taken_item; + uint32 resource_on_dmg_taken_effect; + uint32 resource_on_dmg_taken_skill; + + uint32 resource_regen; + uint32 resource_regen_base; + uint32 resource_regen_equip; + uint32 resource_regen_item; + uint32 resource_regen_effect; + uint32 resource_regen_skill; + + uint32 resource_regen_on_dmg_dealt; + uint32 resource_regen_on_dmg_dealt_base; + uint32 resource_regen_on_dmg_dealt_equip; + uint32 resource_regen_on_dmg_dealt_item; + uint32 resource_regen_on_dmg_dealt_effect; + uint32 resource_regen_on_dmg_dealt_skill; + + uint32 resource_regen_on_dmg_taken; + uint32 resource_regen_on_dmg_taken_base; + uint32 resource_regen_on_dmg_taken_equip; + uint32 resource_regen_on_dmg_taken_item; + uint32 resource_regen_on_dmg_taken_effect; + uint32 resource_regen_on_dmg_taken_skill; + + uint32 resource_loss; + uint32 resource_loss_base; + uint32 resource_loss_equip; + uint32 resource_loss_item; + uint32 resource_loss_effect; + uint32 resource_loss_skill; + + uint32 resource_loss_on_dmg_dealt; + uint32 resource_loss_on_dmg_dealt_base; + uint32 resource_loss_on_dmg_dealt_equip; + uint32 resource_loss_on_dmg_dealt_item; + uint32 resource_loss_on_dmg_dealt_effect; + uint32 resource_loss_on_dmg_dealt_skill; + + uint32 resource_loss_on_dmg_taken; + uint32 resource_loss_on_dmg_taken_base; + uint32 resource_loss_on_dmg_taken_equip; + uint32 resource_loss_on_dmg_taken_item; + uint32 resource_loss_on_dmg_taken_effect; + uint32 resource_loss_on_dmg_taken_skill; + + // Defense types + // think about it as armor and/or resistence if it helps + uint32 defense; + uint32 defense_base; + uint32 defense_equip; + uint32 defense_item; + uint32 defense_effect; + uint32 defense_skill; + + uint32 defense_pircing; + uint32 defense_pircing_base; + uint32 defense_pircing_equip; + uint32 defense_pircing_item; + uint32 defense_pircing_effect; + uint32 defense_pircing_skill; + + uint32 defense_slashing; + uint32 defense_slashing_base; + uint32 defense_slashing_equip; + uint32 defense_slashing_item; + uint32 defense_slashing_effect; + uint32 defense_slashing_skill; + + uint32 defense_bludgeoning; + uint32 defense_bludgeoning_base; + uint32 defense_bludgeoning_equip; + uint32 defense_bludgeoning_item; + uint32 defense_bludgeoning_effect; + uint32 defense_bludgeoning_skill; + + uint32 defense_stabbing; + uint32 defense_stabbing_base; + uint32 defense_stabbing_equip; + uint32 defense_stabbing_item; + uint32 defense_stabbing_effect; + uint32 defense_stabbing_skill; + + uint32 defense_fire; + uint32 defense_fire_base; + uint32 defense_fire_equip; + uint32 defense_fire_item; + uint32 defense_fire_effect; + uint32 defense_fire_skill; + + uint32 defense_water; + uint32 defense_water_base; + uint32 defense_water_equip; + uint32 defense_water_item; + uint32 defense_water_effect; + uint32 defense_water_skill; + + uint32 defense_ice; + uint32 defense_ice_base; + uint32 defense_ice_equip; + uint32 defense_ice_item; + uint32 defense_ice_effect; + uint32 defense_ice_skill; + + uint32 defense_earth; + uint32 defense_earth_base; + uint32 defense_earth_equip; + uint32 defense_earth_item; + uint32 defense_earth_effect; + uint32 defense_earth_skill; + + uint32 defense_wind; + uint32 defense_wind_base; + uint32 defense_wind_equip; + uint32 defense_wind_item; + uint32 defense_wind_effect; + uint32 defense_wind_skill; + + uint32 defense_poison; + uint32 defense_poison_base; + uint32 defense_poison_equip; + uint32 defense_poison_item; + uint32 defense_poison_effect; + uint32 defense_poison_skill; + + uint32 defense_lightning; + uint32 defense_lightning_base; + uint32 defense_lightning_equip; + uint32 defense_lightning_item; + uint32 defense_lightning_effect; + uint32 defense_lightning_skill; + + uint32 defense_holy; + uint32 defense_holy_base; + uint32 defense_holy_equip; + uint32 defense_holy_item; + uint32 defense_holy_effect; + uint32 defense_holy_skill; + + uint32 defense_arcane; + uint32 defense_arcane_base; + uint32 defense_arcane_equip; + uint32 defense_arcane_item; + uint32 defense_arcane_effect; + uint32 defense_arcane_skill; + + uint32 defense_corrupted; + uint32 defense_corrupted_base; + uint32 defense_corrupted_equip; + uint32 defense_corrupted_item; + uint32 defense_corrupted_effect; + uint32 defense_corrupted_skill; + + uint32 shield_type; + bool shield_dispellable; + + uint32 shield; + uint32 shield_base; + uint32 shield_equip; + uint32 shield_item; + uint32 shield_effect; + uint32 shield_skill; + + // Accuracy + f32 dodge_chance; + f32 dodge_chance_base; + f32 dodge_chance_equip; + f32 dodge_chance_item; + f32 dodge_chance_effect; + f32 dodge_chance_skill; + + f32 root_protection; + f32 root_protection_base; + f32 root_protection_equip; + f32 root_protection_item; + f32 root_protection_effect; + f32 root_protection_skill; + + f32 miss_chance; + f32 miss_chance_base; + f32 miss_chance_equip; + f32 miss_chance_item; + f32 miss_chance_effect; + f32 miss_chance_skill; + + // Movement + // Additional speeds may be defined for Mobs + f32 speed_walk1; // normal/fast + f32 speed_walk1_base; + f32 speed_walk1_equip; + f32 speed_walk1_item; + f32 speed_walk1_effect; + f32 speed_walk1_skill; + + f32 speed_walk2; // casual/slow + + f32 speed_swim1; // normal/fast + f32 speed_swim1_base; + f32 speed_swim1_equip; + f32 speed_swim1_item; + f32 speed_swim1_effect; + f32 speed_swim1_skill; + + f32 speed_swim2; // casual/slow + + f32 speed_fly1; // normal/fast + f32 speed_fly1_base; + f32 speed_fly1_equip; + f32 speed_fly1_item; + f32 speed_fly1_effect; + f32 speed_fly1_skill; + + f32 speed_fly2; // casual/slow + + f32 speed_jump; + f32 speed_dodge; + f32 speed_turn; + + // Fighting speed + f32 speed_cast; + f32 speed_cast_base; + f32 speed_cast_equip; + f32 speed_cast_item; + f32 speed_cast_effect; + f32 speed_cast_skill; + + f32 speed_attack; + f32 speed_attack_base; + f32 speed_attack_equip; + f32 speed_attack_item; + f32 speed_attack_effect; + f32 speed_attack_skill; +}; + +struct SMobStats { + byte stat_str; // strength : effects health + base damage + byte stat_int; // inteligence : effects resource + base demage + byte stat_acc; // accuracy : effects critical chance + base damage + miss chance + byte stat_agi; // agility : effects resource + base damage + dodge change + byte stat_def; // defense : effects resource + base defense + dodge change + byte stat_sta; // stamina : effects health regen + resource regen + + // Damage types + uint32 dmg; + uint32 dmg_pircing; + uint32 dmg_slashing; + uint32 dmg_bludgeoning; + uint32 dmg_stabbing; + uint32 dmg_fire; + uint32 dmg_water; + uint32 dmg_ice; + uint32 dmg_arcane; + uint32 dmg_corrupted; + uint32 dmg_reflection; + + uint32 dmg_crit; + f32 dmg_crit_chance; + + // Health & Resource + uint32 health; + uint32 health_on_dmg_dealt; + uint32 health_on_dmg_taken; + + uint32 health_regen; + uint32 health_regen_on_dmg_dealt; + uint32 health_regen_on_dmg_taken; + + uint32 resource; + uint32 resource_on_dmg_dealt; + uint32 resource_on_dmg_taken; + + uint32 resource_regen; + uint32 resource_regen_on_dmg_dealt; + uint32 resource_regen_on_dmg_taken; + + uint32 resource_loss; + uint32 resource_loss_on_dmg_dealt; + uint32 resource_loss_on_dmg_taken; + + // Defense types + // think about it as armor and/or resistence if it helps + uint32 defense; + uint32 defense_pircing; + uint32 defense_slashing; + uint32 defense_bludgeoning; + uint32 defense_stabbing; + uint32 defense_fire; + uint32 defense_water; + uint32 defense_ice; + uint32 defense_earth; + uint32 defense_wind; + uint32 defense_poison; + uint32 defense_lightning; + uint32 defense_holy; + uint32 defense_arcane; + uint32 defense_corrupted; + + uint32 shield_type; + bool shield_dispellable; + uint32 shield; + + // Accuracy + f32 dodge_chance; + f32 root_protection; + f32 miss_chance; + + // Movement + // Additional speeds may be defined for Mobs + f32 speed_walk1; // normal/fast + f32 speed_walk2; // casual/slow + + f32 speed_swim1; // normal/fast + f32 speed_swim2; // casual/slow + + f32 speed_fly1; // normal/fast + f32 speed_fly2; // casual/slow + + f32 speed_jump; + f32 speed_dodge; + f32 speed_turn; + + // Fighting speed + f32 speed_cast; + f32 speed_attack; +}; + +struct CMobStats { + +}; #endif \ No newline at end of file diff --git a/models/mob/player/LootFilter.h b/models/mob/player/LootFilter.h new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/player/Player.h b/models/mob/player/Player.h index 1ab4dd8..8fd2d4a 100644 --- a/models/mob/player/Player.h +++ b/models/mob/player/Player.h @@ -16,7 +16,7 @@ #include "../MobState.h" #include "../monster/LootTable.h" #include "Backpack.h" -#include "PlayerStats.h" +#include "../MobStats.h" #ifndef MAX_CHAR_NAME_LENGTH #define MAX_CHAR_NAME_LENGTH 32 @@ -29,7 +29,7 @@ #if SERVER struct SPlayer { Mob mob; - SPlayerStats player_stats; + SMobStats player_stats; char name[MAX_CHAR_NAME_LENGTH]; char title[MAX_CHAR_TITLE_LENGTH]; @@ -89,7 +89,7 @@ struct CPlayer { Mob mob; - CPlayerStats player_stats; + CMobStats player_stats; char name[MAX_CHAR_NAME_LENGTH]; char title[MAX_CHAR_TITLE_LENGTH]; diff --git a/models/mob/player/PlayerStats.h b/models/mob/player/PlayerStats.h deleted file mode 100644 index fca23ea..0000000 --- a/models/mob/player/PlayerStats.h +++ /dev/null @@ -1,349 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_MODELS_MOB_PLAYER_STATS_H -#define TOS_MODELS_MOB_PLAYER_STATS_H - -#include "../../../stdlib/Types.h" - -#if SERVER - struct SPlayerStats { - byte stat_str; // strength : effects health + base damage - byte stat_int; // inteligence : effects resource + base demage - byte stat_acc; // accuracy : effects critical chance + base damage + miss chance - byte stat_agi; // agility : effects resource + base damage + dodge change - byte stat_def; // defense : effects resource + base defense + dodge change - byte stat_sta; // stamina : effects health regen + resource regen - - // Naming conventions - // : total - // _base : character stats (see stat_ above) - // _equip : character equipment - // _item : other item effects (consumables, e.g. potions) - // _effect : external aoe/skill effect - // _skill : own skill - - // Damage types - unsigned int dmg; - unsigned int dmg_base; - unsigned int dmg_equip; - unsigned int dmg_item; - unsigned int dmg_effect; - unsigned int dmg_skill; - - unsigned int dmg_pircing; - unsigned int dmg_pircing_base; - unsigned int dmg_pircing_equip; - unsigned int dmg_pircing_item; - unsigned int dmg_pircing_effect; - unsigned int dmg_pircing_skill; - - unsigned int dmg_slashing; - unsigned int dmg_slashing_base; - unsigned int dmg_slashing_equip; - unsigned int dmg_slashing_item; - unsigned int dmg_slashing_effect; - unsigned int dmg_slashing_skill; - - unsigned int dmg_bludgeoning; - unsigned int dmg_bludgeoning_base; - unsigned int dmg_bludgeoning_equip; - unsigned int dmg_bludgeoning_item; - unsigned int dmg_bludgeoning_effect; - unsigned int dmg_bludgeoning_skill; - - unsigned int dmg_fire; - unsigned int dmg_fire_base; - unsigned int dmg_fire_equip; - unsigned int dmg_fire_item; - unsigned int dmg_fire_effect; - unsigned int dmg_fire_skill; - - unsigned int dmg_water; - unsigned int dmg_water_base; - unsigned int dmg_water_equip; - unsigned int dmg_water_item; - unsigned int dmg_water_effect; - unsigned int dmg_water_skill; - - unsigned int dmg_ice; - unsigned int dmg_ice_base; - unsigned int dmg_ice_equip; - unsigned int dmg_ice_item; - unsigned int dmg_ice_effect; - unsigned int dmg_ice_skill; - - unsigned int dmg_earth; - unsigned int dmg_earth_base; - unsigned int dmg_earth_equip; - unsigned int dmg_earth_item; - unsigned int dmg_earth_effect; - unsigned int dmg_earth_skill; - - unsigned int dmg_wind; - unsigned int dmg_wind_base; - unsigned int dmg_wind_equip; - unsigned int dmg_wind_item; - unsigned int dmg_wind_effect; - unsigned int dmg_wind_skill; - - unsigned int dmg_poison; - unsigned int dmg_poison_base; - unsigned int dmg_poison_equip; - unsigned int dmg_poison_item; - unsigned int dmg_poison_effect; - unsigned int dmg_poison_skill; - - unsigned int dmg_lightning; - unsigned int dmg_lightning_base; - unsigned int dmg_lightning_equip; - unsigned int dmg_lightning_item; - unsigned int dmg_lightning_effect; - unsigned int dmg_lightning_skill; - - unsigned int dmg_holy; - unsigned int dmg_holy_base; - unsigned int dmg_holy_equip; - unsigned int dmg_holy_item; - unsigned int dmg_holy_effect; - unsigned int dmg_holy_skill; - - unsigned int dmg_arcane; - unsigned int dmg_arcane_base; - unsigned int dmg_arcane_equip; - unsigned int dmg_arcane_item; - unsigned int dmg_arcane_effect; - unsigned int dmg_arcane_skill; - - unsigned int dmg_corrupted; - unsigned int dmg_corrupted_base; - unsigned int dmg_corrupted_equip; - unsigned int dmg_corrupted_item; - unsigned int dmg_corrupted_effect; - unsigned int dmg_corrupted_skill; - - unsigned int dmg_crit; - unsigned int dmg_crit_base; - unsigned int dmg_crit_equip; - unsigned int dmg_crit_item; - unsigned int dmg_crit_effect; - unsigned int dmg_crit_skill; - - float dmg_crit_chance; - float dmg_crit_chance_base; - float dmg_crit_chance_equip; - float dmg_crit_chance_item; - float dmg_crit_chance_effect; - float dmg_crit_chance_skill; - - // Health & Resource - unsigned int health; - unsigned int health_base; - unsigned int health_equip; - unsigned int health_item; - unsigned int health_effect; - unsigned int health_skill; - - unsigned int health_regen; - unsigned int health_regen_base; - unsigned int health_regen_equip; - unsigned int health_regen_item; - unsigned int health_regen_effect; - unsigned int health_regen_skill; - - unsigned int resource; - unsigned int resource_base; - unsigned int resource_equip; - unsigned int resource_item; - unsigned int resource_effect; - unsigned int resource_skill; - - unsigned int resource_regen; - unsigned int resource_regen_base; - unsigned int resource_regen_equip; - unsigned int resource_regen_item; - unsigned int resource_regen_effect; - unsigned int resource_regen_skill; - - // Defense types - // think about it as armor and/or resistence if it helps - unsigned int defense; - unsigned int defense_base; - unsigned int defense_equip; - unsigned int defense_item; - unsigned int defense_effect; - unsigned int defense_skill; - - unsigned int defense_pircing; - unsigned int defense_pircing_base; - unsigned int defense_pircing_equip; - unsigned int defense_pircing_item; - unsigned int defense_pircing_effect; - unsigned int defense_pircing_skill; - - unsigned int defense_slashing; - unsigned int defense_slashing_base; - unsigned int defense_slashing_equip; - unsigned int defense_slashing_item; - unsigned int defense_slashing_effect; - unsigned int defense_slashing_skill; - - unsigned int defense_bludgeoning; - unsigned int defense_bludgeoning_base; - unsigned int defense_bludgeoning_equip; - unsigned int defense_bludgeoning_item; - unsigned int defense_bludgeoning_effect; - unsigned int defense_bludgeoning_skill; - - unsigned int defense_fire; - unsigned int defense_fire_base; - unsigned int defense_fire_equip; - unsigned int defense_fire_item; - unsigned int defense_fire_effect; - unsigned int defense_fire_skill; - - unsigned int defense_water; - unsigned int defense_water_base; - unsigned int defense_water_equip; - unsigned int defense_water_item; - unsigned int defense_water_effect; - unsigned int defense_water_skill; - - unsigned int defense_ice; - unsigned int defense_ice_base; - unsigned int defense_ice_equip; - unsigned int defense_ice_item; - unsigned int defense_ice_effect; - unsigned int defense_ice_skill; - - unsigned int defense_earth; - unsigned int defense_earth_base; - unsigned int defense_earth_equip; - unsigned int defense_earth_item; - unsigned int defense_earth_effect; - unsigned int defense_earth_skill; - - unsigned int defense_wind; - unsigned int defense_wind_base; - unsigned int defense_wind_equip; - unsigned int defense_wind_item; - unsigned int defense_wind_effect; - unsigned int defense_wind_skill; - - unsigned int defense_poison; - unsigned int defense_poison_base; - unsigned int defense_poison_equip; - unsigned int defense_poison_item; - unsigned int defense_poison_effect; - unsigned int defense_poison_skill; - - unsigned int defense_lightning; - unsigned int defense_lightning_base; - unsigned int defense_lightning_equip; - unsigned int defense_lightning_item; - unsigned int defense_lightning_effect; - unsigned int defense_lightning_skill; - - unsigned int defense_holy; - unsigned int defense_holy_base; - unsigned int defense_holy_equip; - unsigned int defense_holy_item; - unsigned int defense_holy_effect; - unsigned int defense_holy_skill; - - unsigned int defense_arcane; - unsigned int defense_arcane_base; - unsigned int defense_arcane_equip; - unsigned int defense_arcane_item; - unsigned int defense_arcane_effect; - unsigned int defense_arcane_skill; - - unsigned int defense_corrupted; - unsigned int defense_corrupted_base; - unsigned int defense_corrupted_equip; - unsigned int defense_corrupted_item; - unsigned int defense_corrupted_effect; - unsigned int defense_corrupted_skill; - - // Accuracy - float dodge_chance; - float dodge_chance_base; - float dodge_chance_equip; - float dodge_chance_item; - float dodge_chance_effect; - float dodge_chance_skill; - - float root_protection; - float root_protection_base; - float root_protection_equip; - float root_protection_item; - float root_protection_effect; - float root_protection_skill; - - float miss_chance; - float miss_chance_base; - float miss_chance_equip; - float miss_chance_item; - float miss_chance_effect; - float miss_chance_skill; - - // Movement - // Additional speeds may be defined for players - float speed_walk1; // normal/fast - float speed_walk1_base; - float speed_walk1_equip; - float speed_walk1_item; - float speed_walk1_effect; - float speed_walk1_skill; - - float speed_walk2; // casual/slow - - float speed_swim1; // normal/fast - float speed_swim1_base; - float speed_swim1_equip; - float speed_swim1_item; - float speed_swim1_effect; - float speed_swim1_skill; - - float speed_swim2; // casual/slow - - float speed_fly1; // normal/fast - float speed_fly1_base; - float speed_fly1_equip; - float speed_fly1_item; - float speed_fly1_effect; - float speed_fly1_skill; - - float speed_fly2; // casual/slow - - float speed_jump; - float speed_dodge; - float speed_turn; - - // Fighting speed - float speed_cast; - float speed_cast_base; - float speed_cast_equip; - float speed_cast_item; - float speed_cast_effect; - float speed_cast_skill; - - float speed_attack; - float speed_attack_base; - float speed_attack_equip; - float speed_attack_item; - float speed_attack_effect; - float speed_attack_skill; - }; -#endif - -struct CPlayerStats { - -}; - -#endif \ No newline at end of file diff --git a/models/mob/skill/AoeDistribution.h b/models/mob/skill/AoeDistribution.h new file mode 100644 index 0000000..234eac9 --- /dev/null +++ b/models/mob/skill/AoeDistribution.h @@ -0,0 +1,9 @@ +#ifndef TOS_MODELS_SKILL_AOE_DISTRIBUTIOM_H +#define TOS_MODELS_SKILL_AOE_DISTRIBUTIOM_H + +enum AoeDistribution { + AOE_DISTRIBUTION_FILL, + AOE_DISTRIBUTION_SPOTTY +}; + +#endif \ No newline at end of file diff --git a/models/mob/skill/AoeShape.h b/models/mob/skill/AoeShape.h new file mode 100644 index 0000000..001415d --- /dev/null +++ b/models/mob/skill/AoeShape.h @@ -0,0 +1,12 @@ +#ifndef TOS_MODELS_SKILL_AOE_SHAPE_H +#define TOS_MODELS_SKILL_AOE_SHAPE_H + +enum AoeShape { + AOE_SHAPE_RECTANGLE, + AOE_SHAPE_CIRCLE, + AOE_SHAPE_SPHEAR, + AOE_SHAPE_BOX, + AOE_SHAPE_FUNNEL +}; + +#endif \ No newline at end of file diff --git a/models/mob/skill/ProjectileDistribution.h b/models/mob/skill/ProjectileDistribution.h new file mode 100644 index 0000000..01a2d21 --- /dev/null +++ b/models/mob/skill/ProjectileDistribution.h @@ -0,0 +1,11 @@ +#ifndef TOS_MODELS_SKILL_PROJECTILE_DISTRIBUTION_H +#define TOS_MODELS_SKILL_PROJECTILE_DISTRIBUTION_H + +enum ProjectileDistribution +{ + PROJECTILE_DISTRIBUTION_HORIZONTAL, + PROJECTILE_DISTRIBUTION_LINE, + PROJECTILE_DISTRIBUTION_CIRCLE +}; + +#endif \ No newline at end of file diff --git a/models/mob/skill/Skill.h b/models/mob/skill/Skill.h new file mode 100644 index 0000000..080d2f2 --- /dev/null +++ b/models/mob/skill/Skill.h @@ -0,0 +1,160 @@ +#ifndef TOS_MODELS_SKILL_H +#define TOS_MODELS_SKILL_H + +#include "../../../stdlib/Types.h" +#include "ProjectileDistribution.h" +#include "SkillLocation.h" +#include "AoeDistribution.h" +#include "StatsTarget.h" +#include "../MobStats.h" + +#define MAX_SKILL_NAME 32 +#define MAX_SKILL_DESCRIPTION 128 + +struct Skill +{ + // not required for server + // const char name[MAX_SKILL_NAME]; + // const char description[MAX_SKILL_DESCRIPTION]; + + int id; + + // animations + void* animation_casting; + void* animation_channeling; + + bool projectile_animation_uses_item; // Use the equiped item for the projectile + + byte target; // what is targatable (self, enemies, allies, ground, none?) Has to be bitset 2^n to define multiple + byte default_target; + + f32 visual_scale; // make visual larger/smaller + + // @tood how to handle multiplicative stats? + // you can have 2 stats for 2 target types (e.g. you could create a buff and debuff in one skill) + SMobStats stats1; + StatsTarget stats1_target; + + SMobStats stats2; + StatsTarget stats2_target; + + byte skill_movement; // none, follows target, random moevement, random movement in aoe + + byte count; // how often is the skill executed @question can this also be used as tick count for heals? or is this in the MobStats? + byte count_delay; // delay between executions + byte count_manual; // you can manually perform the skill count * times + // @todo how to implement random distribution e.g. place n totems in random distribution close to selected spot + + // General + int resource_cost; + int health_cost; + + bool is_range; + f32 attack_range; + void* attack_anim; + + bool is_melee; + f32 melee_range; + + // Projectile data + bool is_projectile; + f32 projectile_speed; + int projectile_count; + int projectile_shape; // 3d Model + + int projectile_distribution; + bool projectile_angle; // Projectiles fan out from start point + + // Either creates new sub-projectiles on shatter OR + // shatter is basically a second hit + bool shatter; + int shatter_projectiles; + int shatter_count; // How often can it shatter at most + f32 shatter_probability; + f32 shatter_range; + f32 shatter_duration; + uint32 shatter_damage; + + bool is_retargatable; // If multiple you may be able to switch targets in between + bool is_boomerang; + + // Casting happens before the skill + f32 cast_duration; + bool is_cast_cancalable; + bool is_cast_disruptable; + bool is_cast_movable; + + // Channeling happens during the skill. + // even a normal punch attack is a channelled skill + f32 channeling_duration; // -1.0 = infinite (e.g. aura), 0 = no duration = instant + bool is_channeling; // duration = skill_duration + it shows the channeling timeline + bool is_channeling_cancalable; + bool is_channeling_disruptable; + bool is_channeling_movable; + + byte channeling_distribution; // beginning, on hit, end, intervals, smooth -> also effects dmg if channeling is cancled + byte channeling_ticks; // how often is dmg dealt + + f32 passthrough_damage; // How much of your damage in % is passing through to the next mob. + int passtrhough_count; + + // AOE + bool is_aoe; + f32 aoe_distance; + int aoe_shape; // circle, square, donut + AoeDistribution aoe_fill_pattern; + f32 aoe_dim1; + f32 aoe_dim2; + f32 aoe_dim3; + int aoe_shatter; + SkillLocation aoe_location; + byte aoe_apply; // Applies while in aoe, applies even after moving out of aoe + + // DOT + f32 dot_duration; + int dot_count; + byte dot_state; // only when moving, standing still, always + + byte dot_effective; // always; on move; on stand still + + byte dot_buff_effective; // buff modifier (e.g. increase by/decrease by) + float dot_buff; // buff dot when on move or on standstill + + int bleeding_dot; + int poison_dot; + int burn_dot; + int ice_dot; + int resource_drain; + int dot_shatter; + + // Minion (and totems) + int minion_type; + int minon_count; // Max minion count + int minion_duration; + int minion_summon_count; // How many summons per summon cast @question still required with general skill count? I don't think so. + + // Effects + bool is_effect_spreading; + f32 effect_spreading_probability; + f32 effect_spreading_radius; // What is the maximum distance for spreading + f32 effect_spreading_max_count; // How many mobs can be effected at maximum + f32 effect_duration; + + // Aura + f32 aura_range; + + // Push/pull + byte push_pull_distance; + byte push_pull_direction; // circle, pov = fan like; > 0 = push, < 0 = pull + + byte player_visibility; // = e.g. sneak skill + + // @todo skill jumps over to close by enemies = chain lightning + + // @todo illusion skill that multiplies the targeted mob and also shuffels the position + + // move_distances (e.g. launch attack propells attacker forward x distance) + byte movement_distances; +}; + +#endif \ No newline at end of file diff --git a/models/mob/skill/SkillLocation.h b/models/mob/skill/SkillLocation.h new file mode 100644 index 0000000..996db76 --- /dev/null +++ b/models/mob/skill/SkillLocation.h @@ -0,0 +1,7 @@ + +enum SkillLocation { + SKILL_LOCATION_NONE, + SKILL_LOCATION_CAST_POINT, + SKILL_LOCATION_TARGET_POINT, + SKILL_LOCATION_BETWEEN_CAST_TARGET +}; \ No newline at end of file diff --git a/models/mob/skill/StatsTarget.h b/models/mob/skill/StatsTarget.h new file mode 100644 index 0000000..d9f0333 --- /dev/null +++ b/models/mob/skill/StatsTarget.h @@ -0,0 +1,18 @@ +#ifndef TOS_MODELS_SKILL_STATS_TARGET_H +#define TOS_MODELS_SKILL_STATS_TARGET_H + +enum StatsTarget { + STATS_TARGET_NONE, + + STATS_TARGET_SELF, + + STATS_TARGET_ENEMY, + STATS_TARGET_ENEMY_AOE, + STATS_TARGET_ENEMY_AURA, + + STATS_TARGET_ALLY, + STATS_TARGET_ALLY_AOE, + STATS_TARGET_ALLY_AURA +}; + +#endif \ No newline at end of file diff --git a/models/mob/skill/definitions/arcane_bolt.cfg b/models/mob/skill/definitions/arcane_bolt.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/arise.cfg b/models/mob/skill/definitions/arise.cfg new file mode 100644 index 0000000..eb26324 --- /dev/null +++ b/models/mob/skill/definitions/arise.cfg @@ -0,0 +1,4 @@ +# Revive slain enemies +# Requires sub skill to re-summon if they die +# Requires sub option to pick who to revive +# Requires sub option to pick who should be released if already full \ No newline at end of file diff --git a/models/mob/skill/definitions/back_fist.cfg b/models/mob/skill/definitions/back_fist.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/beam.cfg b/models/mob/skill/definitions/beam.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/black_fist.cfg b/models/mob/skill/definitions/black_fist.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/chain.cfg b/models/mob/skill/definitions/chain.cfg new file mode 100644 index 0000000..fb9993c --- /dev/null +++ b/models/mob/skill/definitions/chain.cfg @@ -0,0 +1,2 @@ +# Chain enemy to the ground using actual chains +# @todo Consider multiple chains = chained in places OR one chain to player = some movement around center allowed \ No newline at end of file diff --git a/models/mob/skill/definitions/chain_lightning.cfg b/models/mob/skill/definitions/chain_lightning.cfg new file mode 100644 index 0000000..7eaf8b8 --- /dev/null +++ b/models/mob/skill/definitions/chain_lightning.cfg @@ -0,0 +1 @@ +# Lightning attack that jumps from target to target \ No newline at end of file diff --git a/models/mob/skill/definitions/corruption_bolt.cfg b/models/mob/skill/definitions/corruption_bolt.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/cyclone.cfg b/models/mob/skill/definitions/cyclone.cfg new file mode 100644 index 0000000..a337cda --- /dev/null +++ b/models/mob/skill/definitions/cyclone.cfg @@ -0,0 +1,3 @@ +# Cyclone with random movement +# Can be split into multiple cyclones that move randomely +# Can be modified to different elemental types \ No newline at end of file diff --git a/models/mob/skill/definitions/dodge.cfg b/models/mob/skill/definitions/dodge.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/earth_bolt.cfg b/models/mob/skill/definitions/earth_bolt.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/elemental_pilar.cfg b/models/mob/skill/definitions/elemental_pilar.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/fire_bolt.cfg b/models/mob/skill/definitions/fire_bolt.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/frost_bolt.cfg b/models/mob/skill/definitions/frost_bolt.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/ghost_walk.cfg b/models/mob/skill/definitions/ghost_walk.cfg new file mode 100644 index 0000000..75776d2 --- /dev/null +++ b/models/mob/skill/definitions/ghost_walk.cfg @@ -0,0 +1 @@ +# Turns person invisible while walking/running \ No newline at end of file diff --git a/models/mob/skill/definitions/holy_bolt.cfg b/models/mob/skill/definitions/holy_bolt.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/hook.cfg b/models/mob/skill/definitions/hook.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/kick.cfg b/models/mob/skill/definitions/kick.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/launch_strike.cfg b/models/mob/skill/definitions/launch_strike.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/lightning_bolt.cfg b/models/mob/skill/definitions/lightning_bolt.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/meteor_strike.cfg b/models/mob/skill/definitions/meteor_strike.cfg new file mode 100644 index 0000000..aa3e450 --- /dev/null +++ b/models/mob/skill/definitions/meteor_strike.cfg @@ -0,0 +1,2 @@ +# Drops a meteor to the ground +# Can have different elemental attributes (fire = burning meteor, default = earth) \ No newline at end of file diff --git a/models/mob/skill/definitions/mirage.cfg b/models/mob/skill/definitions/mirage.cfg new file mode 100644 index 0000000..c3b4209 --- /dev/null +++ b/models/mob/skill/definitions/mirage.cfg @@ -0,0 +1 @@ +# creates illusions \ No newline at end of file diff --git a/models/mob/skill/definitions/net.cfg b/models/mob/skill/definitions/net.cfg new file mode 100644 index 0000000..5231112 --- /dev/null +++ b/models/mob/skill/definitions/net.cfg @@ -0,0 +1,2 @@ +# Holds person in place +# Can have elemental damage = burning net etc. \ No newline at end of file diff --git a/models/mob/skill/definitions/palm_strike.cfg b/models/mob/skill/definitions/palm_strike.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/poison_strike.cfg b/models/mob/skill/definitions/poison_strike.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/pull.cfg b/models/mob/skill/definitions/pull.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/punch.cfg b/models/mob/skill/definitions/punch.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/push.cfg b/models/mob/skill/definitions/push.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/reflect.cfg b/models/mob/skill/definitions/reflect.cfg new file mode 100644 index 0000000..41d480f --- /dev/null +++ b/models/mob/skill/definitions/reflect.cfg @@ -0,0 +1,2 @@ +# Reflects damage +# either one attack, attack during short window, attack long window \ No newline at end of file diff --git a/models/mob/skill/definitions/revive.cfg b/models/mob/skill/definitions/revive.cfg new file mode 100644 index 0000000..4a11cb3 --- /dev/null +++ b/models/mob/skill/definitions/revive.cfg @@ -0,0 +1 @@ +# Revive player \ No newline at end of file diff --git a/models/mob/skill/definitions/root.cfg b/models/mob/skill/definitions/root.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/shield.cfg b/models/mob/skill/definitions/shield.cfg new file mode 100644 index 0000000..679be4b --- /dev/null +++ b/models/mob/skill/definitions/shield.cfg @@ -0,0 +1 @@ +# Elemental shield \ No newline at end of file diff --git a/models/mob/skill/definitions/side_kick.cfg b/models/mob/skill/definitions/side_kick.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/spikes.cfg b/models/mob/skill/definitions/spikes.cfg new file mode 100644 index 0000000..21beefd --- /dev/null +++ b/models/mob/skill/definitions/spikes.cfg @@ -0,0 +1,2 @@ +# Spikes coming from the ground +# different elements change looks of spikes \ No newline at end of file diff --git a/models/mob/skill/definitions/sprint.cfg b/models/mob/skill/definitions/sprint.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/stomp.cfg b/models/mob/skill/definitions/stomp.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/summon.cfg b/models/mob/skill/definitions/summon.cfg new file mode 100644 index 0000000..5944938 --- /dev/null +++ b/models/mob/skill/definitions/summon.cfg @@ -0,0 +1,2 @@ +# Summon monster +# Requires sub option for selecting mob \ No newline at end of file diff --git a/models/mob/skill/definitions/sword_dance.cfg b/models/mob/skill/definitions/sword_dance.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/totem.cfg b/models/mob/skill/definitions/totem.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/uppercut.cfg b/models/mob/skill/definitions/uppercut.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/whirlwind.cfg b/models/mob/skill/definitions/whirlwind.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/definitions/wind_slashes.cfg b/models/mob/skill/definitions/wind_slashes.cfg new file mode 100644 index 0000000..e69de29 diff --git a/models/mob/skill/modifiers/split_shot.cfg b/models/mob/skill/modifiers/split_shot.cfg new file mode 100644 index 0000000..fe38f99 --- /dev/null +++ b/models/mob/skill/modifiers/split_shot.cfg @@ -0,0 +1 @@ +# turns a single attack into a split shot \ No newline at end of file diff --git a/models/settings/Settings.h b/models/settings/Settings.h index 78705b1..2c2dc81 100644 --- a/models/settings/Settings.h +++ b/models/settings/Settings.h @@ -10,47 +10,87 @@ #define TOS_MODELS_SETTINGS_H #include "../../stdlib/Types.h" - #include "../chat/ChatStatus.h" #include "setting_types.h" -#if SERVER - struct SSettings { - byte distance_terrain = RENDER_CHUNK_RADIUS; - byte distance_terrain_secondary = RENDER_BLOCK_OBJECT_CHUNK_RADIUS; - byte distance_terrain_tertiary = RENDER_INTERACTIVE_CHUNK_RADIUS; - byte distance_models = RENDER_OBJECT_CHUNK_RADIUS; - byte distance_monster = RENDER_MONSTER_CHUNK_RADIUS; - byte distance_npc = RENDER_NPC_CHUNK_RADIUS; - byte distance_player = RENDER_PAYER_CHUNK_RADIUS; - - uint32 player_cache = 8192; // = max active players on a server - uint32 monster_cache = 8192; - uint32 npc_cache = 8192; - uint32 guild_cache = 128; - uint32 message_cache = 1024; - - uint32 interpolation_buffer; - byte simd_version; - }; - - // Player settings that the server needs to know about - struct PSettings { - byte render_distance_models = RENDER_OBJECT_CHUNK_RADIUS; - byte render_distance_monster = RENDER_MONSTER_CHUNK_RADIUS; - byte render_distance_npc = RENDER_NPC_CHUNK_RADIUS; - byte render_distance_player = RENDER_PAYER_CHUNK_RADIUS; - - byte chat_status = CHAT_STATUS_OFFLINE; - bool allow_invites = true; - }; +#if __linux__ + #include + #define MAX_PATH PATH_MAX #endif +#ifndef RENDER_CHUNK_RADIUS + #define RENDER_CHUNK_RADIUS 10 +#endif + +#ifndef RENDER_BLOCK_OBJECT_CHUNK_RADIUS + #define RENDER_BLOCK_OBJECT_CHUNK_RADIUS 10 +#endif + +#ifndef RENDER_INTERACTIVE_CHUNK_RADIUS + #define RENDER_INTERACTIVE_CHUNK_RADIUS 1 +#endif + +#ifndef RENDER_OBJECT_CHUNK_RADIUS + #define RENDER_OBJECT_CHUNK_RADIUS 1 +#endif + +#ifndef RENDER_MONSTER_CHUNK_RADIUS + #define RENDER_MONSTER_CHUNK_RADIUS 3 +#endif + +#ifndef RENDER_NPC_CHUNK_RADIUS + #define RENDER_NPC_CHUNK_RADIUS 3 +#endif + +#ifndef RENDER_PAYER_CHUNK_RADIUS + #define RENDER_PAYER_CHUNK_RADIUS 3 +#endif + +// @todo remove default values because we will load them during startup +struct SSettings { + char path[MAX_PATH]; + bool is_changed = false; + byte simd_version; + + char network_hostname[64]; + uint16 network_port; + + byte distance_terrain = RENDER_CHUNK_RADIUS; + byte distance_terrain_secondary = RENDER_BLOCK_OBJECT_CHUNK_RADIUS; + byte distance_terrain_tertiary = RENDER_INTERACTIVE_CHUNK_RADIUS; + byte distance_models = RENDER_OBJECT_CHUNK_RADIUS; + byte distance_monster = RENDER_MONSTER_CHUNK_RADIUS; + byte distance_npc = RENDER_NPC_CHUNK_RADIUS; + byte distance_player = RENDER_PAYER_CHUNK_RADIUS; + + uint32 player_cache = 8192; // = max active players on a server + uint32 monster_cache = 8192; + uint32 npc_cache = 8192; + uint32 guild_cache = 128; + uint32 message_cache = 1024; + + uint32 interpolation_buffer; +}; + +// Player settings that the server needs to know about +struct PSettings { + byte render_distance_models = RENDER_OBJECT_CHUNK_RADIUS; + byte render_distance_monster = RENDER_MONSTER_CHUNK_RADIUS; + byte render_distance_npc = RENDER_NPC_CHUNK_RADIUS; + byte render_distance_player = RENDER_PAYER_CHUNK_RADIUS; + + byte chat_status = CHAT_STATUS_OFFLINE; + bool allow_invites = true; +}; + struct CSettings { char path[MAX_PATH]; bool is_changed = false; byte simd_version; + char network_hostname[64]; + uint16 network_port; + byte gpu_api = SETTING_TYPE_GPU_API_NONE; byte gpu_type = SETTING_TYPE_GPU_MEDIUM; byte gpu_fps = SETTING_TYPE_UNLIMITED; @@ -63,9 +103,6 @@ struct CSettings { byte gpu_fov; byte gpu_sync = SETTING_TYPE_DISABLED; - char editor_hostname[64]; - uint16 editor_port; - uint32 gpu_number_of_npc_characters = 128; uint32 gpu_number_of_player_characters = 512; uint32 gpu_number_of_monster_characters = 128; @@ -113,6 +150,10 @@ struct CSettings { bool gpu_particles_skills = true; bool gpu_particles_weapons = true; + byte gpu_shadow_type = SETTING_TYPE_DISABLED; // none, baked, shadow mapping, point shadow, ray tracing + byte gpu_light_ssao = SETTING_TYPE_DISABLED; + byte gpu_light_bloom = SETTING_TYPE_DISABLED; + byte gpu_reflection_blur = SETTING_TYPE_DISABLED; byte gpu_motion_blur = SETTING_TYPE_DISABLED; byte gpu_blur = SETTING_TYPE_DISABLED; @@ -120,6 +161,10 @@ struct CSettings { byte gpu_sharpening = SETTING_TYPE_DISABLED; byte gpu_ambient_occlusion = SETTING_TYPE_DISABLED; + bool gpu_gamma_correction = true; + bool gpu_normal_mapping = true; + bool gpu_parallax_mapping = true; + bool gpu_depth_of_field = true; bool gpu_chromatic_aberration = true; bool gpu_vignetting = true; @@ -299,6 +344,7 @@ struct CSettings { bool input_click_to_move = true; // Hotkey settings + // @todo hotkey combination e.g. alt+1 byte hotkeys_movement_up = 0x57; // W byte hotkeys_movement_down = 0x53; // S byte hotkeys_movement_left = 0x41; // A @@ -354,6 +400,12 @@ struct CSettings { byte hotkeys_menu = 0x1B; // ESC byte hotkeys_window_close = 0x1B; // ESC + + byte hotkeys_marker_1 = 0x31; // 1 + byte hotkeys_marker_2 = 0x32; // 2 + byte hotkeys_marker_3 = 0x33; // 3 + byte hotkeys_marker_4 = 0x34; // 4 + byte hotkeys_marker_5 = 0x35; // 5 }; #endif \ No newline at end of file diff --git a/network/Client.h b/network/Client.h index 9c36e19..1322d22 100644 --- a/network/Client.h +++ b/network/Client.h @@ -20,19 +20,19 @@ #if _WIN32 #include #include - #define close closesocket - #define sleep Sleep #else #include #include #include #endif +#include "NetworkOSWrapper.h" + #ifndef MAX_STATIC_NETWORK_PACKET_SIZE #define MAX_STATIC_NETWORK_PACKET_SIZE 8192 #endif -SOCKET socket_client_udb_connect(const char *hostname, int port, sockaddr_in6 *server_addr) { +void socket_client_udb_connect(const char *hostname, SocketConnection* con) { addrinfo hints, *res, *p; memset(&hints, 0, sizeof(hints)); @@ -40,29 +40,22 @@ SOCKET socket_client_udb_connect(const char *hostname, int port, sockaddr_in6 *s hints.ai_socktype = SOCK_DGRAM; char port_str[6]; - snprintf(port_str, sizeof(port_str), "%d", port); + snprintf(port_str, sizeof(port_str), "%d", con->port); if (getaddrinfo(hostname, port_str, &hints, &res) != 0) { - return NULL; + return; } - SOCKET sd = NULL; for (p = res; p != NULL; p = p->ai_next) { - if ((sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + if ((con->sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { continue; } - memcpy(server_addr, p->ai_addr, p->ai_addrlen); + memcpy((void *) &con->server_addr, p->ai_addr, p->ai_addrlen); break; } freeaddrinfo(res); - - if (p == NULL) { - return NULL; - } - - return sd; } int socket_client_send(SOCKET sd, char *data, size_t length, sockaddr_in6 *server_addr, socklen_t addr_len) { diff --git a/network/NetworkOSWrapper.h b/network/NetworkOSWrapper.h new file mode 100644 index 0000000..d409409 --- /dev/null +++ b/network/NetworkOSWrapper.h @@ -0,0 +1,19 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_NETWORK_OS_WRAPPER_H +#define TOS_NETWORK_OS_WRAPPER_H + +#if _WIN32 + #include + #include + #define close closesocket + #define sleep Sleep +#endif + +#endif \ No newline at end of file diff --git a/network/Server.h b/network/Server.h index 6fb4de8..931624e 100644 --- a/network/Server.h +++ b/network/Server.h @@ -5,4 +5,52 @@ * @license OMS License 2.0 * @version 1.0.0 * @link https://jingga.app - */ \ No newline at end of file + */ +#ifndef TOS_NETWORK_SERVER_H +#define TOS_NETWORK_SERVER_H + +#include +#include +#include + +#if _WIN32 + #include + #include +#else + #include + #include + #include + #include + #include + #include + #include +#endif + +#include "NetworkOSWrapper.h" +#include "SocketConnection.h" + +void socket_server_udb_create(const char *hostname, SocketConnection* con) { + con->sd = socket(AF_INET6, SOCK_DGRAM, 0); + + int flags; + if ((flags = fcntl(con->sd, F_GETFL, 0)) < 0) { + close(con->sd); + con->sd = 0; + } + + if (fcntl(con->sd, F_SETFL, flags | O_NONBLOCK) < 0) { + close(con->sd); + con->sd = 0; + } + + con->server_addr.sin6_family = AF_INET6; + con->server_addr.sin6_addr = in6addr_any; + con->server_addr.sin6_port = htons(con->port); + + if (bind(con->sd, (sockaddr *) &con->server_addr, sizeof(sockaddr_in6)) < 0) { + close(con->sd); + con->sd = 0; + } +} + +#endif \ No newline at end of file diff --git a/network/SocketConnection.h b/network/SocketConnection.h index b33b879..61bbc8d 100644 --- a/network/SocketConnection.h +++ b/network/SocketConnection.h @@ -9,6 +9,8 @@ #ifndef TOS_NETWORK_SOCKET_CONNECTION_H #define TOS_NETWORK_SOCKET_CONNECTION_H +#include "../stdlib/Types.h" + #if _WIN32 #include #include @@ -19,9 +21,15 @@ #endif struct SocketConnection { - SOCKET sd; + #if _WIN32 + SOCKET sd; + #else + int sd; + #endif + sockaddr_in6 server_addr; socklen_t addr_len; + uint16 port; }; #endif \ No newline at end of file diff --git a/network/packet/PacketCache.h b/network/packet/PacketCache.h new file mode 100644 index 0000000..1aafc0c --- /dev/null +++ b/network/packet/PacketCache.h @@ -0,0 +1,136 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_NETWORK_PACKET_CACHE_H +#define TOS_NETWORK_PACKET_CACHE_H + +#include "../../utils/RingMemory.h" +#include "../../utils/BufferMemory.h" + +#if _WIN32 + #include + #include + #include +#else + #include + #include +#endif + +struct PacketCache { + sockaddr_in6 addr; + + int last_received; + int last_sent; + + RingMemory packets_received; + RingMemory packets_sent; + + int packets_received_ack[64]; + int packets_sent_ack[64]; +}; + +struct PacketCacheHashEntry { + in6_addr* key; + PacketCache* value; + PacketCacheHashEntry* next; +}; + +struct PacketCacheHashTable { + uint32 size; + PacketCacheHashEntry** entries; + + // BufferMemory for PacketCacheHashEntry NOT PacketCache + BufferMemory buf; +}; + +uint32 hash_ipv6_address(uint32 hashmap_size, sockaddr_in6 *addr) { + uint32 hash_val = addr->sin6_addr; + + hash_val = ((hash_val >> 16) ^ hash_val) * 0x45d9f3b; + hash_val = ((hash_val >> 16) ^ hash_val) * 0x45d9f3b; + hash_val = (hash_val >> 16) ^ hash_val; + + return hash_val % hashmap_size; +} + +PacketCache* hash_packet_cache_get(PacketCacheHashTable* ht, sockaddr_in6* addr) { + uint32 index = hash_ipv6_address(ht->size, addr); + + PacketCacheHashEntry* entry; + if (!(entry = ht->entries[index])) { + return NULL; + } + + bool no_match; + while ((no_match = (memcmp(&addr->sin6_addr, entry->key, sizeof(in6_addr)) != 0)) + && entry->next != NULL + ) { + entry = entry->next; + } + + if (no_match) { + return NULL; + } + + return entry->value; +} + +PacketCacheHashEntry* hash_packet_cache_insert(PacketCacheHashTable* ht, sockaddr_in6* addr, PacketCache* value) { + uint32 index = hash_ipv6_address(ht->size, addr); + + PacketCacheHashEntry* element = (PacketCacheHashEntry *) buffer_find_free(&ht->buf); + element->key = &value->addr.sin6_addr; + element->value = value; + element->next = NULL; + + PacketCacheHashEntry* entry = ht->entries[index]; + if (entry == NULL) { + ht->entries[index] = element; + + return element; + } + + while (entry->next != NULL) { + entry = entry->next; + } + + entry->next = element; + + return element; +} + +void hash_packet_cache_remove(PacketCacheHashTable* ht, sockaddr_in6* addr) { + uint32 index = hash_ipv6_address(ht->size, addr); + + PacketCacheHashEntry* entry; + if (!(entry = ht->entries[index])) { + return; + } + + PacketCacheHashEntry* prev = NULL; + + bool no_match = false; + while (entry && (no_match = (memcmp(&addr->sin6_addr, entry->key, sizeof(in6_addr)) != 0))) { + prev = entry; + entry = entry->next; + } + + if (no_match) { + return; + } + + if (!prev) { + ht->entries[index] = NULL; + + return; + } + + prev->next = NULL; +} + +#endif \ No newline at end of file diff --git a/platform/linux/UtilsLinux.h b/platform/linux/UtilsLinux.h index 7468309..04ccfad 100644 --- a/platform/linux/UtilsLinux.h +++ b/platform/linux/UtilsLinux.h @@ -12,23 +12,36 @@ #include #include #include +#include #include #include +#include #include "../../stdlib/Types.h" #include "../../utils/Utils.h" #include "../../utils/TestUtils.h" -inline uint64 last_modification(const char* filename) +inline +uint64 file_size(const char* filename) { + struct stat st; + if (stat(filename, &st) != 0) { + return 0; + } + + return st.st_size; +} + +inline +uint64 last_modified(const char* filename) { struct stat buffer; stat(filename, &buffer); - return (uint64) buffer.st_mtime.tv_sec; + return (uint64) buffer.st_mtime; } -inline void -file_read(const char* filename, file_body* file) +inline +void file_read(const char* filename, file_body* file) { FILE *fp = fopen(filename, "rb"); fseek(fp, 0, SEEK_END); @@ -41,6 +54,131 @@ file_read(const char* filename, file_body* file) fclose(fp); } +inline +uint64_t file_read_struct(const char* filename, void* file, uint32 size) { + FILE *fp = fopen(filename, "rb"); + if (!fp) { + return 0; + } + + fseek(fp, 0, SEEK_END); + long fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + ASSERT_SIMPLE(fsize > size); + size_t read_bytes = fread(file, 1, size, fp); + fclose(fp); + + return read_bytes; +} + +inline +bool file_write(const char* filename, const file_body* file) { + FILE *fp = fopen(filename, "wb"); + if (!fp) { + return false; + } + + size_t written = fwrite(file->content, 1, file->size, fp); + fclose(fp); + + return written == file->size; +} + +inline +bool file_write_struct(const char* filename, const void* file, uint32_t size) { + FILE *fp = fopen(filename, "wb"); + if (!fp) { + return false; + } + + size_t written = fwrite(file, 1, size, fp); + fclose(fp); + + return written == size; +} + +inline +void file_copy(const char* src, const char* dst) { + FILE *src_fp = fopen(src, "rb"); + FILE *dst_fp = fopen(dst, "wb"); + + if (!src_fp || !dst_fp) { + if (src_fp) fclose(src_fp); + if (dst_fp) fclose(dst_fp); + return; + } + + char buffer[4096]; + size_t bytes; + while ((bytes = fread(buffer, 1, sizeof(buffer), src_fp)) > 0) { + fwrite(buffer, 1, bytes, dst_fp); + } + + fclose(src_fp); + fclose(dst_fp); +} + +inline +FILE* get_append_handle(const char* filename) { + FILE *fp = fopen(filename, "ab"); + if (!fp) { + return NULL; + } + return fp; +} + +inline bool file_append(const char* filename, const char* file) { + FILE *fp = get_append_handle(filename); + if (!fp) { + return false; + } + + size_t length = strlen(file); + ASSERT_SIMPLE(length < INT32_MAX); + size_t written = fwrite(file, 1, length, fp); + fclose(fp); + + return written == length; +} + +inline bool file_append(FILE* fp, const char* file) { + if (!fp) { + return false; + } + + size_t length = strlen(file); + ASSERT_SIMPLE(length < INT32_MAX); + size_t written = fwrite(file, 1, length, fp); + fclose(fp); + + return written == length; +} + +inline bool file_append(const char* filename, const file_body* file) { + FILE *fp = get_append_handle(filename); + if (!fp) { + return false; + } + + size_t length = file->size; + ASSERT_SIMPLE(length < INT32_MAX); + size_t written = fwrite(file->content, 1, length, fp); + fclose(fp); + + return written == length; +} + +inline +void self_path(char* path) { + size_t len = readlink("/proc/self/exe", path, PATH_MAX); + if (len > 0) { + path[len] = '\0'; + } else { + path[0] = '\0'; + } +} + inline void strncpy_s(char *dest, size_t destsz, const char *src, size_t count) { size_t i; diff --git a/platform/win32/UtilsWin32.h b/platform/win32/UtilsWin32.h index 0558395..8d0f59d 100644 --- a/platform/win32/UtilsWin32.h +++ b/platform/win32/UtilsWin32.h @@ -271,7 +271,8 @@ file_append(const char* filename, const file_body* file) return true; } -inline uint64 last_modified(const char* filename) +inline +uint64 last_modified(const char* filename) { FILETIME modified = {}; diff --git a/platform/win32/audio/DirectSound.h b/platform/win32/audio/DirectSound.h index 6260f5a..5420888 100644 --- a/platform/win32/audio/DirectSound.h +++ b/platform/win32/audio/DirectSound.h @@ -108,7 +108,7 @@ void audio_play(AudioSetting* setting, DirectSoundSetting* api_setting) } inline -void audio_free(AudioSetting* setting, DirectSoundSetting* api_setting) +void audio_free(AudioSetting*, DirectSoundSetting* api_setting) { if (api_setting->direct_sound) { api_setting->direct_sound->Release(); diff --git a/stdlib/Intrinsics.h b/stdlib/Intrinsics.h index e0d24b5..5fac405 100644 --- a/stdlib/Intrinsics.h +++ b/stdlib/Intrinsics.h @@ -13,7 +13,7 @@ #include #include -#ifdef _LINUX +#if __linux__ #include #endif diff --git a/stdlib/Mathtypes.h b/stdlib/Mathtypes.h index ba718f7..83ae528 100644 --- a/stdlib/Mathtypes.h +++ b/stdlib/Mathtypes.h @@ -118,14 +118,17 @@ struct v3_f32 { union { f32 x; f32 r; + f32 pitch; }; union { f32 y; f32 g; + f32 yaw; }; union { f32 z; f32 b; + f32 roll; }; }; diff --git a/stdlib/Types.h b/stdlib/Types.h index 1302060..76e6466 100644 --- a/stdlib/Types.h +++ b/stdlib/Types.h @@ -80,8 +80,6 @@ uint16 float_to_f16(float f) { } float f16_to_float(f16 f) { - uint32_t f_bits = 0; - uint32_t sign = (f & HALF_FLOAT_SIGN_MASK) << 16; int32_t exponent = (f & HALF_FLOAT_EXP_MASK) >> HALF_FLOAT_EXP_SHIFT; uint32_t fraction = (f & HALF_FLOAT_FRAC_MASK) << (FLOAT32_EXP_SHIFT - HALF_FLOAT_EXP_SHIFT); @@ -101,9 +99,9 @@ float f16_to_float(f16 f) { exponent += FLOAT32_EXP_BIAS - HALF_FLOAT_EXP_BIAS; } - f_bits = sign | (exponent << FLOAT32_EXP_SHIFT) | fraction; + uint32_t f_bits = sign | (exponent << FLOAT32_EXP_SHIFT) | fraction; - return *((float*)&f_bits); + return *((float *) &f_bits); } #endif diff --git a/thread/Thread.h b/thread/Thread.h index 99eff84..3faa8d2 100644 --- a/thread/Thread.h +++ b/thread/Thread.h @@ -43,168 +43,4 @@ void thread_stop(Worker* worker) } } -ThreadJob *thread_pool_work_poll(ThreadPool *pool) -{ - if (pool == NULL) { - return NULL; - } - - ThreadJob *work = pool->work_first; - if (work == NULL) { - return NULL; - } - - if (work->next == NULL) { - pool->work_first = NULL; - pool->work_last = NULL; - } else { - pool->work_first = work->next; - } - - return work; -} - -#ifdef _WIN32 -static DWORD WINAPI thread_pool_worker(void* arg) -#else -static void* thread_pool_worker(void *arg) -#endif -{ - ThreadPool *pool = (ThreadPool *) arg; - ThreadJob *work; - - while (true) { - pthread_mutex_lock(&pool->work_mutex); - - while (pool->work_first == NULL && !pool->stop) { - pthread_cond_wait(&pool->work_cond, &pool->work_mutex); - } - - if (pool->stop) { - break; - } - - work = thread_pool_work_poll(pool); - ++(pool->working_cnt); - pthread_mutex_unlock(&pool->work_mutex); - - if (work != NULL) { - work->func(work); - } - - pthread_mutex_lock(&pool->work_mutex); - --(pool->working_cnt); - - if (!pool->stop && pool->working_cnt == 0 && pool->work_first == NULL) { - pthread_cond_signal(&pool->working_cond); - } - - pthread_mutex_unlock(&pool->work_mutex); - } - - --(pool->thread_cnt); - pthread_cond_signal(&pool->working_cond); - pthread_mutex_unlock(&pool->work_mutex); - - return NULL; -} - -ThreadPool *thread_pool_create(size_t num, ThreadPool* pool) -{ - pthread_t thread; - size_t i; - - if (num == 0) { - num = 2; - } - - pool->thread_cnt = num; - - // @todo switch from pool mutex and pool cond to threadjob mutex/cond - // thread_pool_wait etc. should just itereate over all mutexes - pthread_mutex_init(&pool->work_mutex, NULL); - pthread_cond_init(&pool->work_cond, NULL); - pthread_cond_init(&pool->working_cond, NULL); - - pool->work_first = NULL; - pool->work_last = NULL; - - for (i = 0; i < num; i++) { - pthread_create(&thread, NULL, thread_pool_worker, pool); - ++(pool->size); - - pthread_detach(thread); - } - - return pool; -} - -void thread_pool_wait(ThreadPool *pool) -{ - if (pool == NULL) { - return; - } - - pthread_mutex_lock(&pool->work_mutex); - - while (true) { - if ((!pool->stop && pool->working_cnt != 0) || (pool->stop && pool->thread_cnt != 0)) { - pthread_cond_wait(&pool->working_cond, &pool->work_mutex); - } else { - break; - } - } - - pthread_mutex_unlock(&pool->work_mutex); -} - -void thread_pool_destroy(ThreadPool *pool) -{ - if (pool == NULL) { - return; - } - - pthread_mutex_lock(&pool->work_mutex); - ThreadJob *work = pool->work_first; - - while (work != NULL) { - work = work->next; - } - - pool->stop = true; - pthread_cond_broadcast(&pool->work_cond); - pthread_mutex_unlock(&pool->work_mutex); - - thread_pool_wait(pool); - - pthread_mutex_destroy(&pool->work_mutex); - pthread_cond_destroy(&pool->work_cond); - pthread_cond_destroy(&pool->working_cond); -} - -ThreadJob* thread_pool_add_work(ThreadPool *pool, ThreadJob* job) -{ - if (pool == NULL) { - return NULL; - } - - if (job == NULL) { - return NULL; - } - - pthread_mutex_lock(&pool->work_mutex); - if (pool->work_first == NULL) { - pool->work_first = job; - pool->work_last = pool->work_first; - } else { - pool->work_last->next = job; - pool->work_last = job; - } - - pthread_cond_broadcast(&pool->work_cond); - pthread_mutex_unlock(&pool->work_mutex); - - return job; -} - #endif \ No newline at end of file diff --git a/thread/ThreadJob.h b/thread/ThreadJob.h index 43cda5c..115b8f7 100644 --- a/thread/ThreadJob.h +++ b/thread/ThreadJob.h @@ -12,15 +12,7 @@ #include #include -#ifdef _WIN32 - #include - - typedef DWORD (WINAPI *ThreadJobFunc)(void*); -#else - typedef void (*ThreadJobFunc)(void*); -#endif - -#include "ThreadOSWrapper.h" +#include "ThreadOSDefines.h" struct job_t { ThreadJobFunc func; diff --git a/thread/ThreadOSDefines.h b/thread/ThreadOSDefines.h new file mode 100644 index 0000000..8836dd6 --- /dev/null +++ b/thread/ThreadOSDefines.h @@ -0,0 +1,33 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_THREADS_OS_DEFINES_H +#define TOS_THREADS_OS_DEFINES_H + +#if _WIN32 + #include + + typedef DWORD (WINAPI *ThreadJobFunc)(void*); + typedef CRITICAL_SECTION pthread_mutex_t; + typedef void pthread_mutexattr_t; + typedef void pthread_condattr_t; + typedef void pthread_rwlockattr_t; + typedef HANDLE pthread_t; + typedef CONDITION_VARIABLE pthread_cond_t; + + struct pthread_rwlock_t { + SRWLOCK lock; + bool exclusive; + }; +#else + #include + #include + typedef void * (*ThreadJobFunc)(void*); +#endif + +#endif \ No newline at end of file diff --git a/thread/ThreadOSWrapper.h b/thread/ThreadOSWrapper.h index 7a1ee96..98280c4 100644 --- a/thread/ThreadOSWrapper.h +++ b/thread/ThreadOSWrapper.h @@ -9,12 +9,13 @@ #ifndef TOS_THREADS_OS_WRAPPER_H #define TOS_THREADS_OS_WRAPPER_H +#include + #include "../stdlib/Types.h" +#include "ThreadOSDefines.h" #ifdef _WIN32 - #include #include - #include #else #include #include @@ -33,18 +34,6 @@ void ms_to_timespec(timespec *ts, uint32 ms) } #ifdef _WIN32 - typedef CRITICAL_SECTION pthread_mutex_t; - typedef void pthread_mutexattr_t; - typedef void pthread_condattr_t; - typedef void pthread_rwlockattr_t; - typedef HANDLE pthread_t; - typedef CONDITION_VARIABLE pthread_cond_t; - - struct pthread_rwlock_t { - SRWLOCK lock; - bool exclusive; - }; - int pthread_create(pthread_t* thread, void*, ThreadJobFunc start_routine, void* arg) { if (thread == NULL || start_routine == NULL) { @@ -59,7 +48,7 @@ void ms_to_timespec(timespec *ts, uint32 ms) return 0; } - int pthread_join(pthread_t thread, void** value_ptr) + int pthread_join(pthread_t thread, void**) { WaitForSingleObject(thread, INFINITE); CloseHandle(thread); @@ -202,7 +191,7 @@ void ms_to_timespec(timespec *ts, uint32 ms) return 0; } - int pthread_rwlock_destroy(pthread_rwlock_t* rwlock) + int pthread_rwlock_destroy(pthread_rwlock_t*) { return 0; } diff --git a/thread/ThreadPool.h b/thread/ThreadPool.h index 828d7c2..6247bc9 100644 --- a/thread/ThreadPool.h +++ b/thread/ThreadPool.h @@ -23,7 +23,7 @@ #include "ThreadJob.h" #include "ThreadOSWrapper.h" -typedef struct { +struct ThreadPool { ThreadJob *work_first; ThreadJob *work_last; @@ -36,6 +36,170 @@ typedef struct { int32 size; bool stop; -} ThreadPool; +}; + +ThreadJob *thread_pool_work_poll(ThreadPool *pool) +{ + if (pool == NULL) { + return NULL; + } + + ThreadJob *work = pool->work_first; + if (work == NULL) { + return NULL; + } + + if (work->next == NULL) { + pool->work_first = NULL; + pool->work_last = NULL; + } else { + pool->work_first = work->next; + } + + return work; +} + +#ifdef _WIN32 +static DWORD WINAPI thread_pool_worker(void* arg) +#else +static void* thread_pool_worker(void *arg) +#endif +{ + ThreadPool *pool = (ThreadPool *) arg; + ThreadJob *work; + + while (true) { + pthread_mutex_lock(&pool->work_mutex); + + while (pool->work_first == NULL && !pool->stop) { + pthread_cond_wait(&pool->work_cond, &pool->work_mutex); + } + + if (pool->stop) { + break; + } + + work = thread_pool_work_poll(pool); + ++(pool->working_cnt); + pthread_mutex_unlock(&pool->work_mutex); + + if (work != NULL) { + work->func(work); + } + + pthread_mutex_lock(&pool->work_mutex); + --(pool->working_cnt); + + if (!pool->stop && pool->working_cnt == 0 && pool->work_first == NULL) { + pthread_cond_signal(&pool->working_cond); + } + + pthread_mutex_unlock(&pool->work_mutex); + } + + --(pool->thread_cnt); + pthread_cond_signal(&pool->working_cond); + pthread_mutex_unlock(&pool->work_mutex); + + return NULL; +} + +ThreadPool *thread_pool_create(size_t num, ThreadPool* pool) +{ + pthread_t thread; + size_t i; + + if (num == 0) { + num = 2; + } + + pool->thread_cnt = num; + + // @todo switch from pool mutex and pool cond to threadjob mutex/cond + // thread_pool_wait etc. should just itereate over all mutexes + pthread_mutex_init(&pool->work_mutex, NULL); + pthread_cond_init(&pool->work_cond, NULL); + pthread_cond_init(&pool->working_cond, NULL); + + pool->work_first = NULL; + pool->work_last = NULL; + + for (i = 0; i < num; i++) { + pthread_create(&thread, NULL, thread_pool_worker, pool); + ++(pool->size); + + pthread_detach(thread); + } + + return pool; +} + +void thread_pool_wait(ThreadPool *pool) +{ + if (pool == NULL) { + return; + } + + pthread_mutex_lock(&pool->work_mutex); + + while (true) { + if ((!pool->stop && pool->working_cnt != 0) || (pool->stop && pool->thread_cnt != 0)) { + pthread_cond_wait(&pool->working_cond, &pool->work_mutex); + } else { + break; + } + } + + pthread_mutex_unlock(&pool->work_mutex); +} + +void thread_pool_destroy(ThreadPool *pool) +{ + if (pool == NULL) { + return; + } + + pthread_mutex_lock(&pool->work_mutex); + ThreadJob *work = pool->work_first; + + while (work != NULL) { + work = work->next; + } + + pool->stop = true; + pthread_cond_broadcast(&pool->work_cond); + pthread_mutex_unlock(&pool->work_mutex); + + thread_pool_wait(pool); + + pthread_mutex_destroy(&pool->work_mutex); + pthread_cond_destroy(&pool->work_cond); + pthread_cond_destroy(&pool->working_cond); +} + +ThreadJob* thread_pool_add_work(ThreadPool *pool, ThreadJob* job) +{ + if (pool == NULL) { + return NULL; + } + + if (job == NULL) { + return NULL; + } + + pthread_mutex_lock(&pool->work_mutex); + if (pool->work_first == NULL) { + pool->work_first = job; + pool->work_last = pool->work_first; + } else { + pool->work_last->next = job; + pool->work_last = job; + } + + pthread_cond_broadcast(&pool->work_cond); + pthread_mutex_unlock(&pool->work_mutex); + + return job; +} #endif \ No newline at end of file diff --git a/utils/BitUtils.h b/utils/BitUtils.h index 03270b0..e621fec 100644 --- a/utils/BitUtils.h +++ b/utils/BitUtils.h @@ -11,6 +11,7 @@ #include "../stdlib/Types.h" +inline uint32 bytes_merge(byte b0, byte b1, byte b2, byte b3) { uint32 result = 0; @@ -22,6 +23,7 @@ uint32 bytes_merge(byte b0, byte b1, byte b2, byte b3) { return result; } +inline uint64 bytes_merge( byte b0, byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7 diff --git a/utils/BufferMemory.h b/utils/BufferMemory.h new file mode 100644 index 0000000..e506968 --- /dev/null +++ b/utils/BufferMemory.h @@ -0,0 +1,125 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_UTILS_BUFFER_MEMORY_H +#define TOS_UTILS_BUFFER_MEMORY_H + +#include "../stdlib/Types.h" +#include "MathUtils.h" + +struct BufferMemory { + byte* memory; + + uint64 count; + uint64 element_size; + uint64 last_pos = -1; + + // length = count + // free describes which locations are used and which are free + // @performance using uint32 or even uint64 might be faster + // since we can check for free elements faster if the memory is almost filled + // at the moment we can only check 8 elements at a time + byte* free; +}; + +inline +byte* buffer_element_get(BufferMemory* buf, uint64 element) +{ + return buf->memory + element * buf->element_size; +} + +int64 buffer_reserve(BufferMemory* buf) +{ + int byte_index = (buf->last_pos + 1) / 8; + int bit_index; + + int64 free_element = -1; + byte mask; + + int i = 0; + int max_loop = buf->count * buf->element_size; + + while (free_element < 0 && i < max_loop) { + if (buf->free[byte_index] == 0xFF) { + ++i; + ++byte_index; + + continue; + } + + // This always breaks! + // @performance on the first iteration through the buffer we could optimize this by starting at a different bit_index + // because we know that the bit_index is based on last_pos + for (bit_index = 0; bit_index < 8; ++bit_index) { + mask = 1 << bit_index; + if ((buf->free[byte_index] & mask) == 0) { + free_element = byte_index * 8 + bit_index; + break; + } + } + } + + if (free_element < 0) { + return -1; + } + + buf->free[byte_index] |= (1 << bit_index); + + return byte_index * 8 + bit_index; +} + +byte* buffer_find_free(BufferMemory* buf, bool zeroed = false) +{ + int byte_index = (buf->last_pos + 1) / 8; + int bit_index; + + int64 free_element = -1; + byte mask; + + int i = 0; + int max_loop = buf->count * buf->element_size; + + while (free_element < 0 && i < max_loop) { + if (buf->free[byte_index] == 0xFF) { + ++i; + ++byte_index; + + continue; + } + + // This always breaks! + // @performance on the first iteration through the buffer we could optimize this by starting at a different bit_index + // because we know that the bit_index is based on last_pos + for (bit_index = 0; bit_index < 8; ++bit_index) { + mask = 1 << bit_index; + if ((buf->free[byte_index] & mask) == 0) { + free_element = byte_index * 8 + bit_index; + break; + } + } + } + + if (free_element < 0) { + return NULL; + } + + buf->free[byte_index] |= (1 << bit_index); + + return buf->memory + free_element * buf->element_size; +} + +inline +void buffer_element_free(BufferMemory* buf, uint64 element) +{ + int byte_index = element / 8; + int bit_index = element % 8; + + buf->free[byte_index] &= ~(1 << bit_index); +} + +#endif \ No newline at end of file diff --git a/utils/MathUtils.h b/utils/MathUtils.h index f530234..eb8c85b 100644 --- a/utils/MathUtils.h +++ b/utils/MathUtils.h @@ -14,6 +14,7 @@ #define OMS_PI 3.14159265358979323846f #define OMS_PI_OVER_TWO OMS_PI / 2.0f +#define OMS_PI_OVER_FOUR OMS_PI / 4.0f #define OMS_TWO_PI 2 * OMS_PI #define OMS_MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -24,6 +25,10 @@ #define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI) #define ROUND_TO_NEAREST(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) +#ifndef FLT_MIN + #define FLT_MIN 1.175494e-038 +#endif + // @question Consider to implement table based sine wave + approximation if necessary // [-PI/2, PI/2] inline @@ -35,7 +40,6 @@ float sin_approx_pih_pih(float x) inline float sinf_approx(float x) { - x = OMS_RAD2DEG(x); return 4 * x * (180 - x) / (40500 - x * (180 - x)); } @@ -58,4 +62,55 @@ float tanf_approx(float x) return sin_x / cos_x; } +inline +float atanf_approx(float x) +{ + float abs_x = OMS_ABS(x); + float result; + + if (abs_x > 1.0f) { + result = OMS_PI_OVER_TWO - (1.0f / abs_x); + } else { + result = abs_x - (abs_x * abs_x * abs_x / 3.0f); + } + + return (x < 0.0f) ? -result : result; +} + +inline +float atan2f_approx(float y, float x) +{ + float abs_y = OMS_ABS(y) + FLT_MIN; // prevent division by zero + float angle; + + if (x >= 0.0f) { + float r = (x - abs_y) / (x + abs_y); + angle = OMS_PI_OVER_FOUR - OMS_PI_OVER_FOUR * r; + } else { + float r = (x + abs_y) / (abs_y - x); + angle = (3.0f * OMS_PI / 4.0f) - OMS_PI_OVER_FOUR * r; + } + + return (y < 0.0f) ? -angle : angle; +} + +inline +float asinf_approx(float x) +{ + float negate = (x < 0) ? 1.0f : 0.0f; + x = OMS_ABS(x); + + float result = -0.0187293f; + result *= x; + result += 0.0742610f; + result *= x; + result -= 0.2121144f; + result *= x; + result += 1.5707288f; + result *= sqrt(1.0f - x); + result -= 2 * negate * result; + + return negate * OMS_PI + result; +} + #endif diff --git a/utils/RingMemory.h b/utils/RingMemory.h index be7e8cc..f904dbe 100644 --- a/utils/RingMemory.h +++ b/utils/RingMemory.h @@ -54,7 +54,7 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, byte aligned = 1, bool zero ring->pos = 0; } - byte* offset = (byte *) ring->memory[ring->pos]; + byte* offset = (byte *) (ring->memory + ring->pos); if (zeroed) { memset((void *) offset, 0, size); } @@ -64,6 +64,17 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, byte aligned = 1, bool zero return offset; } +// Used if the ring only contains elements of a certain size +// This way you can get a certain element +inline +byte *ring_get_element(const RingMemory* ring, uint64 element_count, uint64 element, uint64 size) +{ + uint64 index = (element % element_count) - 1; + index = index < 0 ? element_count : index; + + return ring->memory + index * size; +} + inline void ring_reset(RingMemory* ring) { @@ -78,6 +89,10 @@ bool ring_commit_safe(const RingMemory* ring, uint64 size, byte aligned = 1) { uint64 pos = ring_calculate_position(ring, ring->pos, size, aligned); + if (ring->start == ring->end && ring->pos == 0) { + return true; + } + return ring->start < ring->pos ? ring->start < pos : pos < ring->start; diff --git a/utils/StringUtils.h b/utils/StringUtils.h index a92c225..1512a32 100644 --- a/utils/StringUtils.h +++ b/utils/StringUtils.h @@ -14,7 +14,6 @@ #include #include "../stdlib/Types.h" -#include "../stdlib/Mathtypes.h" inline size_t str_count(const char *str, const char *substr) { @@ -59,15 +58,13 @@ str_concat( const char* src2, size_t src2_length, char* dst ) { - for (size_t i = 0; i < src1_length; ++i) { - *dst++ = *src1++; - } + memcpy(dst, src1, src1_length); + dst += src1_length; - for (size_t i = 0; i < src2_length; ++i) { - *dst++ = *src2++; - } + memcpy(dst, src2, src2_length); + dst += src2_length; - *dst++ = '\0'; + *dst = '\0'; } char *strtok(char *str, const char *delim, char **saveptr) @@ -144,33 +141,6 @@ void create_const_name(const unsigned char *name, unsigned char* modified_name) } } -void font_string_dimension(const char *str, v2_int32* dim, const int* width_lookup) -{ - size_t length = strlen(str); - int width = 0; - - for (int i = 0; i < length; ++i) { - if (str[i] == '\n') { - if (width > dim->x) { - dim->x = width; - } - - width = 0; - ++dim->y; - } - - width += width_lookup[str[i]]; - } - - if (width > dim->x) { - dim->x = width; - } - - if (width > 0) { - ++dim->y; - } -} - /** * Custom implementation of strtok_r/strtok_s */ diff --git a/utils/TestUtils.h b/utils/TestUtils.h index 8d5858d..407d070 100644 --- a/utils/TestUtils.h +++ b/utils/TestUtils.h @@ -12,6 +12,12 @@ #include #include "../stdlib/Types.h" +#if _WIN32 + #include +#else + #include +#endif + #define MAX_LOG_LENGTH 128 global_persist uint64 performance_count_frequency; @@ -31,36 +37,21 @@ struct LogPool { // uint32 size = count * MAX_LOG_LENGTH }; -#if _WIN32 - inline - void update_timing_stat(TimingStat *stat) - { - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); +// IMPORTANT: This function should only be called when you actually use this data +// e.g. log to display or file +inline +void update_timing_stat(TimingStat *stat) +{ + stat->new_tick_count = __rdtsc(); - stat->new_tick_count = counter.QuadPart; + stat->delta_tick = stat->new_tick_count - stat->old_tick_count; + stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency; - // @performance Consider to only do the following two calculations when outputting the tick/time - stat->delta_tick = stat->new_tick_count - stat->old_tick_count; - stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency; - - stat->old_tick_count = stat->new_tick_count; - } -#else - void update_timing_stat(TimingStat *stat) - { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - stat->new_tick_count = now.tv_sec + now.tv_nsec; - - // @performance Consider to only do the following two calculations when outputting the tick/time - stat->delta_tick = stat->new_tick_count - stat->old_tick_count; - stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency; - - stat->old_tick_count = stat->new_tick_count; - } -#endif + stat->old_tick_count = stat->new_tick_count; +} +// Sometimes we want to only do logging in debug mode. +// In such cases use the following macro. #if DEBUG #define UPDATE_TIMING_STAT(stat) update_timing_stat(stat) #else diff --git a/utils/Utils.h b/utils/Utils.h index f9c4ccf..a9b67b3 100644 --- a/utils/Utils.h +++ b/utils/Utils.h @@ -37,36 +37,4 @@ bool is_bit_set(byte data, byte bit) return (data & (1 << bit)) == 0; } -void make_character( - float *data, - float x, float y, float n, float m, char c) -{ - float *d = data; - - // Texture atlas is 16 characters - // 1 / 16 = 0.0625 - float a = 0.0625; - float b = 0.0625 * 2; - - // ascii offset - int w = c - 32; - - float du = (w % 16) * a; - float dv = 1 - (w / 16) * b - b; - - // Quad data (2 triangles) - *(d++) = x - n; *(d++) = y - m; - *(d++) = du + 0; *(d++) = dv; - *(d++) = x + n; *(d++) = y - m; - *(d++) = du + a; *(d++) = dv; - *(d++) = x + n; *(d++) = y + m; - *(d++) = du + a; *(d++) = dv + b; - *(d++) = x - n; *(d++) = y - m; - *(d++) = du + 0; *(d++) = dv; - *(d++) = x + n; *(d++) = y + m; - *(d++) = du + a; *(d++) = dv + b; - *(d++) = x - n; *(d++) = y + m; - *(d++) = du + 0; *(d++) = dv + b; -} - #endif \ No newline at end of file