diff --git a/game/client b/game/client index 7c659dd..673d436 100755 Binary files a/game/client and b/game/client differ diff --git a/game/client.c b/game/client.c index 162e224..eb6df46 100644 --- a/game/client.c +++ b/game/client.c @@ -179,6 +179,8 @@ float get_terrain_height(float x, float z) { #define TERRAIN_SIZE 256 #define TERRAIN_SCALE 1.0f +#define TERRAIN_MIN (-TERRAIN_SIZE * TERRAIN_SCALE / 2.0f) +#define TERRAIN_MAX (TERRAIN_SIZE * TERRAIN_SCALE / 2.0f) static Mesh generate_terrain_mesh(void) { int size = TERRAIN_SIZE; @@ -1005,6 +1007,10 @@ int main(void) { (Color){80, 140, 70, 255}; DrawModel(terrainModel, (Vector3){0, 0, 0}, 1.0f, WHITE); + // Draw border + float borderSize = TERRAIN_MAX - TERRAIN_MIN; + DrawCube((Vector3){0, 0, 0}, borderSize, 1000, borderSize, (Color){255, 0, 0, 100}); + // Items with basic lighting (no shader for now to keep it simple) for (int i = 0; i < MAX_ITEMS; i++) { if (!wi[i].present) diff --git a/game/server b/game/server index d390cbe..30f4f0b 100755 Binary files a/game/server and b/game/server differ diff --git a/game/server.c b/game/server.c index 7a029a7..2e5c2b1 100644 --- a/game/server.c +++ b/game/server.c @@ -153,6 +153,8 @@ float get_terrain_height(float x, float z) { #define TERRAIN_SIZE 256 #define TERRAIN_SCALE 1.0f +#define TERRAIN_MIN (-TERRAIN_SIZE * TERRAIN_SCALE / 2.0f) +#define TERRAIN_MAX (TERRAIN_SIZE * TERRAIN_SCALE / 2.0f) static dReal *gHeightData = NULL; static dGeomID gTerrainGeom = NULL; @@ -298,6 +300,7 @@ typedef struct Player { uint32_t rng; float reloadTimer; int reloadWeapon; + float borderDamageTimer; dBodyID body; dGeomID geom; } Player; @@ -466,6 +469,8 @@ static void player_ode_create(Player *p, int spawnIndex) { dGeomSetBody(p->geom, p->body); dGeomSetCategoryBits(p->geom, CAT_PLAYER); dGeomSetCollideBits(p->geom, CAT_WORLD | CAT_PLAYER); + + p->borderDamageTimer = 0.0f; } static void player_ode_destroy(Player *p) { @@ -988,27 +993,71 @@ int main(void) { } } - for (int i = 0; i < MAX_PLAYERS; i++) { - Player *p = &players[i]; - if (!p->inUse || !p->alive) - continue; + for (int i = 0; i < MAX_PLAYERS; i++) { + Player *p = &players[i]; + if (!p->inUse || !p->alive) + continue; - const dReal *lvel = dBodyGetLinearVel(p->body); - const dReal *avel = dBodyGetAngularVel(p->body); + const dReal *lvel = dBodyGetLinearVel(p->body); + const dReal *avel = dBodyGetAngularVel(p->body); - float dx = p->moveX, dz = p->moveZ; - float len = sqrtf(dx * dx + dz * dz); - if (len > 1e-6f) { - dx /= len; - dz /= len; - } + float dx = p->moveX, dz = p->moveZ; + float len = sqrtf(dx * dx + dz * dz); + if (len > 1e-6f) { + dx /= len; + dz /= len; + } - float speed = 10.0f; - float fx = sinf(p->yaw) * dz - cosf(p->yaw) * dx; - float fz = cosf(p->yaw) * dz + sinf(p->yaw) * dx; - dBodySetLinearVel(p->body, fx * speed, lvel[1], fz * speed); - dBodySetAngularVel(p->body, avel[0], 0, avel[2]); - } + float speed = 10.0f; + float fx = sinf(p->yaw) * dz - cosf(p->yaw) * dx; + float fz = cosf(p->yaw) * dz + sinf(p->yaw) * dx; + dBodySetLinearVel(p->body, fx * speed, lvel[1], fz * speed); + dBodySetAngularVel(p->body, avel[0], 0, avel[2]); + } + + // Border damage + for (int i = 0; i < MAX_PLAYERS; i++) { + Player *p = &players[i]; + if (!p->inUse || !p->alive) + continue; + const dReal *pos = dBodyGetPosition(p->body); + float px = (float)pos[0], pz = (float)pos[2]; + if (px < TERRAIN_MIN || px > TERRAIN_MAX || pz < TERRAIN_MIN || pz > TERRAIN_MAX) { + p->borderDamageTimer += DT; + if (p->borderDamageTimer >= 0.5f) { + p->borderDamageTimer -= 0.5f; + p->hp -= 1; + if (p->hp <= 0) { + p->hp = 0; + p->alive = 0; + // Drop loot as in shooting death + const dReal *pos2 = dBodyGetPosition(p->body); + float x = (float)pos2[0], z = (float)pos2[2]; + if (p->pistolAmmo > 0) { + int qty = p->pistolAmmo; + if (qty > 12) qty = 12; + item_spawn(ITEM_AMMO_PISTOL, qty, x + frand_signed(&p->rng) * 2.0f, z + frand_signed(&p->rng) * 2.0f); + p->pistolAmmo -= qty; + } + if (p->rifleAmmo > 0) { + int qty = p->rifleAmmo; + if (qty > 30) qty = 30; + item_spawn(ITEM_AMMO_RIFLE, qty, x + frand_signed(&p->rng) * 2.0f, z + frand_signed(&p->rng) * 2.0f); + p->rifleAmmo -= qty; + } + if (p->medkits > 0) { + int qty = p->medkits; + if (qty > 2) qty = 2; + item_spawn(ITEM_MEDKIT, qty, x + frand_signed(&p->rng) * 2.0f, z + frand_signed(&p->rng) * 2.0f); + p->medkits -= qty; + } + printf("Player %d died from border damage and dropped loot\n", i); + } + } + } else { + p->borderDamageTimer = 0.0f; + } + } MsgSnapshot snap = {0}; snap.type = MSG_SNAPSHOT;