This commit is contained in:
Dennis Eichhorn 2024-07-21 21:25:39 +02:00
parent 2b8a31ff7c
commit acde815291
95 changed files with 2740 additions and 757 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
build/*
data/*
bin/*
*.obj
*.log
*.res

119
camera/Camera.h Normal file
View File

@ -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

35
camera/CameraMovement.h Normal file
View File

@ -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

213
gpuapi/RenderUtils.h Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

19
math/random/BlueNoise.h Normal file
View File

@ -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

View File

@ -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

67
models/account/Account.h Normal file
View File

@ -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

67
models/bracket/Bracket.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

View File

@ -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];

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

160
models/mob/skill/Skill.h Normal file
View File

@ -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

View File

@ -0,0 +1,7 @@
enum SkillLocation {
SKILL_LOCATION_NONE,
SKILL_LOCATION_CAST_POINT,
SKILL_LOCATION_TARGET_POINT,
SKILL_LOCATION_BETWEEN_CAST_TARGET
};

View File

@ -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

View File

@ -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

View File

View File

@ -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

View File

@ -0,0 +1 @@
# Lightning attack that jumps from target to target

View File

@ -0,0 +1,3 @@
# Cyclone with random movement
# Can be split into multiple cyclones that move randomely
# Can be modified to different elemental types

View File

View File

@ -0,0 +1 @@
# Turns person invisible while walking/running

View File

View File

View File

@ -0,0 +1,2 @@
# Drops a meteor to the ground
# Can have different elemental attributes (fire = burning meteor, default = earth)

View File

@ -0,0 +1 @@
# creates illusions

View File

@ -0,0 +1,2 @@
# Holds person in place
# Can have elemental damage = burning net etc.

View File

View File

View File

View File

@ -0,0 +1,2 @@
# Reflects damage
# either one attack, attack during short window, attack long window

View File

@ -0,0 +1 @@
# Revive player

View File

View File

@ -0,0 +1 @@
# Elemental shield

View File

@ -0,0 +1,2 @@
# Spikes coming from the ground
# different elements change looks of spikes

View File

View File

View File

@ -0,0 +1,2 @@
# Summon monster
# Requires sub option for selecting mob

View File

View File

@ -0,0 +1 @@
# turns a single attack into a split shot

View File

@ -10,12 +10,51 @@
#define TOS_MODELS_SETTINGS_H
#include "../../stdlib/Types.h"
#include "../chat/ChatStatus.h"
#include "setting_types.h"
#if SERVER
struct SSettings {
#if __linux__
#include <linux/limits.h>
#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;
@ -31,11 +70,10 @@
uint32 message_cache = 1024;
uint32 interpolation_buffer;
byte simd_version;
};
};
// Player settings that the server needs to know about
struct PSettings {
// 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;
@ -43,14 +81,16 @@
byte chat_status = CHAT_STATUS_OFFLINE;
bool allow_invites = true;
};
#endif
};
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

View File

@ -20,19 +20,19 @@
#if _WIN32
#include <winsock2.h>
#include <windows.h>
#define close closesocket
#define sleep Sleep
#else
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#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) {

View File

@ -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 <winsock2.h>
#include <windows.h>
#define close closesocket
#define sleep Sleep
#endif
#endif

View File

@ -6,3 +6,51 @@
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_NETWORK_SERVER_H
#define TOS_NETWORK_SERVER_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if _WIN32
#include <winsock2.h>
#include <windows.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#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

View File

@ -9,6 +9,8 @@
#ifndef TOS_NETWORK_SOCKET_CONNECTION_H
#define TOS_NETWORK_SOCKET_CONNECTION_H
#include "../stdlib/Types.h"
#if _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
@ -19,9 +21,15 @@
#endif
struct SocketConnection {
#if _WIN32
SOCKET sd;
#else
int sd;
#endif
sockaddr_in6 server_addr;
socklen_t addr_len;
uint16 port;
};
#endif

View File

@ -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 <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#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

View File

@ -12,23 +12,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/limits.h>
#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;

View File

@ -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 = {};

View File

@ -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();

View File

@ -13,7 +13,7 @@
#include <inttypes.h>
#include <xmmintrin.h>
#ifdef _LINUX
#if __linux__
#include <x86intrin.h>
#endif

View File

@ -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;
};
};

View File

@ -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

View File

@ -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

View File

@ -12,15 +12,7 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
typedef DWORD (WINAPI *ThreadJobFunc)(void*);
#else
typedef void (*ThreadJobFunc)(void*);
#endif
#include "ThreadOSWrapper.h"
#include "ThreadOSDefines.h"
struct job_t {
ThreadJobFunc func;

33
thread/ThreadOSDefines.h Normal file
View File

@ -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 <windows.h>
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 <pthread.h>
#include <unistd.h>
typedef void * (*ThreadJobFunc)(void*);
#endif
#endif

View File

@ -9,12 +9,13 @@
#ifndef TOS_THREADS_OS_WRAPPER_H
#define TOS_THREADS_OS_WRAPPER_H
#include <time.h>
#include "../stdlib/Types.h"
#include "ThreadOSDefines.h"
#ifdef _WIN32
#include <stdbool.h>
#include <windows.h>
#include <time.h>
#else
#include <pthread.h>
#include <unistd.h>
@ -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;
}

View File

@ -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

View File

@ -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

125
utils/BufferMemory.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -14,7 +14,6 @@
#include <ctype.h>
#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
*/

View File

@ -12,6 +12,12 @@
#include <time.h>
#include "../stdlib/Types.h"
#if _WIN32
#include <intrin.h>
#else
#include <x86intrin.h>
#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;
// @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
}
// 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

View File

@ -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