#include #include #include "common.hpp" #include #include #include #include #include #include #include #define PIXUNIT 1.0f / 16.0f #ifndef SERVER extern Camera camera; extern Font fnt; extern Texture2D terrain; Texture2D playerTex; Texture2D bomb; Sound nekit_idle; void EntitiesInit() { playerTex = LoadTexture(Pathify("player.png")); bomb = LoadTexture(Pathify("bomb.png")); nekit_idle = LoadSound(Pathify("sound/nekit/idle.ogg")); } extern bool online; extern Vector3 player_position; extern Vector3 player_velocity; void TakeDamage(float amount); void SetBlockNetwork(World &world, int bx, int by, int bz, int t); #else bool online = true; #endif std::list entities; Entity NewEntity() { Entity ent; ent.id = entities.size(); ent.type = 0; ent.yaw = 0; ent.free = false; return ent; } void AddEntity(Entity ent) { entities.push_back(ent); } static void UpdateEntityPhysics(World &world, Entity& ent, float dt) { Vector3 velocityTgt = Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}); Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt)); Vector3 final = ent.position; if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) { final.x = tgt.x; } if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) { final.y = tgt.y; } else { velocityTgt.y = 0; } if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) { final.z = tgt.z; } ent.velocity = velocityTgt; ent.position = final; } void UpdateEntities(World &world, float dt) { if(entities.size() > 0) { int idx = 0; for(Entity& ent : entities) { ent.smoothing = 0; if(ent.type != 1) { ent.lifetime += dt; } else { ent.lifetime += dt * ent.data[1] / 255.0f; if(ent.data[1]-4 >= 0) { ent.data[1]-=4; } } if(ent.damage_flash != 0) { ent.damage_flash--; } if(ent.type == 2) { Vector3 target = Vector3Zero(); #ifndef SERVER target = player_position; #endif Vector3 direction = Vector3Normalize(Vector3Subtract(target, ent.position)); float degYaw = -atan2f(direction.z, direction.x) * RAD2DEG + 90; if(GetRandomValue(0, 2000) == 0) { MS_PlaySound(nekit_idle, GetRandomValue(75,125)/100.0f, 1.0f, ent.position); } ent.velocity = Vector3Add(ent.velocity, (Vector3){direction.x * 20.0f, 0, direction.z * 20.0f}*dt); if(GetBlock(world, (int)ent.position.x, (int)ent.position.y-1, (int)ent.position.z) && GetRandomValue(0, 100) == 0) { ent.velocity.y += 10.0f; } UpdateEntityPhysics(world, ent, dt); if(Vector3Distance(target, ent.position) < 1.5f && ent.data[2] > 80) { player_velocity += (Vector3){direction.x, 0, direction.z} * 30.0f; player_velocity += {0, 2, 0}; ent.data[2] = 0; TakeDamage(10.0f); } if(ent.health < 0.1f) { ent.free = true; } if(ent.data[2] < 90) ent.data[2]++; ent.yaw = (unsigned short)(degYaw/360.0f*65535); } /*if(ent.type == 3) { Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f}); Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt)); Vector3 final = ent.position; if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) { final.x = tgt.x; } if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) { final.y = tgt.y; } else { velocityTgt.y = -velocityTgt.y / 2.0f; velocityTgt = Vector3Scale(velocityTgt, 0.9f); } if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) { final.z = tgt.z; } Entity* entp = &ent; entp->yaw = 0; entp->position = final; entp->velocity = velocityTgt; if(ent.lifetime > 5.0f) { int radius = 3; for (int x = -radius; x < radius; x++) { for (int y = -radius; y < radius; y++) { for (int z = -radius; z < radius; z++) { if(Vector3Distance({final.x + x, final.y + y, final.z + z}, final) <= radius) { if(!CheckOOBWorld(final.x + x, final.y + y, final.z + z)) { #ifndef SERVER SetBlockNetwork(world, final.x + x, final.y + y, final.z + z, 0); #endif } } } } } entp->free = true; } idx++; }*/ if(ent.type == 4) { Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f}); Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt)); Vector3 final = ent.position; bool hit = false; if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) { final.x = tgt.x; } else { hit = true; } if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) { final.y = tgt.y; } else { hit = true; } if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) { final.z = tgt.z; } else { hit = true; } Entity* entp = &ent; if(hit) { SetBlockNetwork(world, (int)ent.position.x, (int)ent.position.y, (int)ent.position.z, ent.data[1]); entp->free = true; } entp->yaw = 0; entp->position = final; entp->velocity = velocityTgt; idx++; } } auto match = [&](const Entity ent){ return ent.free; }; auto it = std::find_if(entities.begin(), entities.end(), match); if (it != entities.end()) { entities.erase(it); } } } float globalCounter = 0; #ifndef SERVER void DrawEntities(float dt) { globalCounter += dt; for(Entity& ent : entities) { ent.smoothing += dt; if(ent.smoothing > TPS_DIV) { ent.smoothing = 0; } Vector3 pos_lerped = Vector3Lerp(ent.position, Vector3Add(ent.position, ent.velocity*TPS_DIV), ent.smoothing * TPS); if(ent.type == 0 || ent.type == 2) { Color color = ColorLerp(WHITE, RED, ent.damage_flash / 50.0f); Vector3 posLerp = Vector3Add(pos_lerped, {-0.5f, -0.1f, -0.5f}); float time = (ent.lifetime + ent.smoothing) * 4.0f; float armWave0 = sinf(time * PI); float armWave1 = -abs(cosf(time * PI)); float headWave = cosf(time * PI); posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0}); Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0}); float yaw = ent.yaw / 65535.0f * 360.0f; rlColor4f(color.r, color.g, color.b, color.a); rlPushMatrix(); rlTranslatef(posLerp.x, posLerp.y, posLerp.z); // move to model origin rlRotatef(yaw, 0, 1, 0); // rotate around Y rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z); // move back (optional depending on your pivots) // rlPushMatrix(); rlTranslatef(headPivot.x, headPivot.y, headPivot.z); rlRotatef(25.0f * armWave0, 1, 0, 0); rlRotatef(25.0f * headWave, 0, 0, 1); // Head DrawCubeTexture(playerTex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8); rlPopMatrix(); Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0}); Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0}); rlPushMatrix(); rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z); rlRotatef(45.0f * armWave0, 1, 0, 0); rlRotatef(45.0f * armWave1, 0, 0, 1); DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4); rlPopMatrix(); rlPushMatrix(); rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z); rlRotatef(-45.0f * armWave0, 1, 0, 0); rlRotatef(-45.0f * armWave1, 0, 0, 1); DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4); rlPopMatrix(); Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0}); rlPushMatrix(); rlTranslatef(body.x, body.y, body.z); DrawCubeTexture(playerTex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4); rlPopMatrix(); leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0}); rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0}); rlPushMatrix(); rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z); rlRotatef(-45.0f * armWave0, 1, 0, 0); DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4); rlPopMatrix(); rlPushMatrix(); rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z); rlRotatef(45.0f * armWave0, 1, 0, 0); DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4); rlPopMatrix(); rlPopMatrix(); } if(ent.type == 1) { Color color = WHITE; Vector3 posLerp = Vector3Add(ent.position, {-0.5f, -0.1f, -0.5f}); float time = ent.lifetime * 4.0f; float armWave0 = sinf(time * PI); float armWave1 = -abs(cosf(time * PI)); float headWave = cosf(time * PI); posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0}); Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0}); float yaw = -ent.yaw / 65535.0f * 360.0f - 90; rlPushMatrix(); rlTranslatef(posLerp.x, posLerp.y, posLerp.z); rlRotatef(yaw, 0, 1, 0); rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z); // rlPushMatrix(); rlTranslatef(headPivot.x, headPivot.y, headPivot.z); rlRotatef(25.0f * armWave0, 1, 0, 0); rlRotatef(25.0f * headWave, 0, 0, 1); // Head DrawCubeTexture(playerTex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8); rlPopMatrix(); Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0}); Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0}); rlPushMatrix(); rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z); rlRotatef(45.0f * armWave0, 1, 0, 0); rlRotatef(45.0f * armWave1, 0, 0, 1); DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4); rlPopMatrix(); rlPushMatrix(); rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z); rlRotatef(-45.0f * armWave0, 1, 0, 0); rlRotatef(-45.0f * armWave1, 0, 0, 1); DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4); rlPopMatrix(); Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0}); rlPushMatrix(); rlTranslatef(body.x, body.y, body.z); DrawCubeTexture(playerTex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4); rlPopMatrix(); leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0}); rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0}); rlPushMatrix(); rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z); rlRotatef(-45.0f * armWave0, 1, 0, 0); DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4); rlPopMatrix(); rlPushMatrix(); rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z); rlRotatef(45.0f * armWave0, 1, 0, 0); DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4); rlPopMatrix(); rlPopMatrix(); Vector3 dir = Vector3Subtract(camera.position, ent.position); rlPushMatrix(); rlTranslatef(ent.position.x, ent.position.y + 1.5f, ent.position.z); rlRotatef(atan2f(dir.x, dir.z) * RAD2DEG, 0.0f, 1.0f, 0.0f); rlRotatef(90.0f, 1.0f, 0.0f, 0.0f); char name[12]; sprintf(name, "Player %d", (int)ent.data[0]); DrawText3D(fnt, name, {-MeasureTextEx(fnt, name, PIXUNIT * 4, 0).x * 1.5f, 0, 0}, PIXUNIT * 4, PIXUNIT, 1, true, WHITE); rlPopMatrix(); } if(ent.type == 3) { DrawCube(pos_lerped, 1, 1, 1, RED); } if(ent.type == 4) { DrawCubeBlock(terrain, pos_lerped, 1,1,1, GetBlockDefinition(ent.data[1]), WHITE); } } } #endif