big chungus
parent
213710e922
commit
a9efa0f01c
|
@ -26,6 +26,7 @@ void game_update();
|
||||||
void game_render();
|
void game_render();
|
||||||
void game_player_joined(uint64_t ent);
|
void game_player_joined(uint64_t ent);
|
||||||
void game_player_departed(uint64_t ent);
|
void game_player_departed(uint64_t ent);
|
||||||
|
void game_player_died(uint64_t ent);
|
||||||
void game_client_receive_code(pkt_send_code data);
|
void game_client_receive_code(pkt_send_code data);
|
||||||
|
|
||||||
// base methods called from games
|
// base methods called from games
|
||||||
|
|
|
@ -106,6 +106,10 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct { char _unused; } Dead;
|
typedef struct { char _unused; } Dead;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t timer;
|
||||||
|
} Respawn;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float amt;
|
float amt;
|
||||||
} HealthRegen;
|
} HealthRegen;
|
||||||
|
@ -277,6 +281,7 @@ typedef struct {
|
||||||
X(ClientInfo)\
|
X(ClientInfo)\
|
||||||
X(Health)\
|
X(Health)\
|
||||||
X(Dead)\
|
X(Dead)\
|
||||||
|
X(Respawn)\
|
||||||
X(HealthRegen)\
|
X(HealthRegen)\
|
||||||
X(HealDelay)\
|
X(HealDelay)\
|
||||||
X(Mob)\
|
X(Mob)\
|
||||||
|
|
|
@ -121,9 +121,6 @@ uint64_t storage_spawn(void) {
|
||||||
uint64_t mob_spawn(void) {
|
uint64_t mob_spawn(void) {
|
||||||
ecs_entity_t e = entity_spawn(EKIND_MONSTER);
|
ecs_entity_t e = entity_spawn(EKIND_MONSTER);
|
||||||
|
|
||||||
Health *hp = ecs_get_mut(world_ecs(), e, Health);
|
|
||||||
hp->max_hp = hp->hp = 100.0f;
|
|
||||||
|
|
||||||
ecs_add(world_ecs(), e, Mob);
|
ecs_add(world_ecs(), e, Mob);
|
||||||
ecs_set(world_ecs(), e, Health, { 60, 60, 0 });
|
ecs_set(world_ecs(), e, Health, { 60, 60, 0 });
|
||||||
ecs_set(world_ecs(), e, PhysicsBody, { .kind = PHYS_AABB, .mass = 1.0f });
|
ecs_set(world_ecs(), e, PhysicsBody, { .kind = PHYS_AABB, .mass = 1.0f });
|
||||||
|
|
|
@ -50,6 +50,7 @@ void OnDead(ecs_iter_t *it) {
|
||||||
|
|
||||||
if (ci) {
|
if (ci) {
|
||||||
pkt_notification_send(0, 0, "Someone died!", zpl_bprintf("Player %d has died!", it->entities[i]));
|
pkt_notification_send(0, 0, "Someone died!", zpl_bprintf("Player %d has died!", it->entities[i]));
|
||||||
|
game_player_died(it->entities[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pi) {
|
if (pi) {
|
||||||
|
|
|
@ -110,6 +110,14 @@ void VehicleHandling(ecs_iter_t *it) {
|
||||||
car->steer = zpl_lerp(car->steer, 0.0f, safe_dt(it)*game_rules.vehicle_steer_revert);
|
car->steer = zpl_lerp(car->steer, 0.0f, safe_dt(it)*game_rules.vehicle_steer_revert);
|
||||||
car->steer += (in->x * game_rules.vehicle_steer * steer_mod)*safe_dt(it);
|
car->steer += (in->x * game_rules.vehicle_steer * steer_mod)*safe_dt(it);
|
||||||
car->steer = zpl_clamp(car->steer, -60.0f, 60.0f);
|
car->steer = zpl_clamp(car->steer, -60.0f, 60.0f);
|
||||||
|
|
||||||
|
// if (in->x != 0) {
|
||||||
|
// // Add a sideways velocity to the car. This will make the car move sideways,
|
||||||
|
// // giving the appearance of a drift. The actual amount of sideways velocity
|
||||||
|
// // will need to be fine-tuned.
|
||||||
|
// v[i].x += in->x * steer_mod * -zpl_sin(car->heading) * car->force;
|
||||||
|
// v[i].y += in->x * steer_mod * zpl_cos(car->heading) * car->force;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -320,6 +320,7 @@ void world_setup_ecs(void) {
|
||||||
ECS_IMPORT(world.ecs, Components);
|
ECS_IMPORT(world.ecs, Components);
|
||||||
ECS_IMPORT(world.ecs, Systems);
|
ECS_IMPORT(world.ecs, Systems);
|
||||||
world.ecs_update = ecs_query_new(world.ecs, "components.ClientInfo, components.Position");
|
world.ecs_update = ecs_query_new(world.ecs, "components.ClientInfo, components.Position");
|
||||||
|
world.ecs_alive_player = ecs_query_new(world.ecs, "components.ClientInfo, components.Position, !components.Dead");
|
||||||
world.ecs_clientinfo = ecs_query_new(world.ecs, "components.ClientInfo");
|
world.ecs_clientinfo = ecs_query_new(world.ecs, "components.ClientInfo");
|
||||||
world.ecs_layeroverriden = ecs_query_new(world.ecs, "components.StreamLayerOverride");
|
world.ecs_layeroverriden = ecs_query_new(world.ecs, "components.StreamLayerOverride");
|
||||||
}
|
}
|
||||||
|
@ -531,6 +532,10 @@ ecs_query_t* world_ecs_player(void) {
|
||||||
return world.ecs_update;
|
return world.ecs_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecs_query_t* world_ecs_alive_player(void) {
|
||||||
|
return world.ecs_alive_player;
|
||||||
|
}
|
||||||
|
|
||||||
ecs_query_t* world_ecs_clientinfo(void) {
|
ecs_query_t* world_ecs_clientinfo(void) {
|
||||||
return world.ecs_clientinfo;
|
return world.ecs_clientinfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ typedef struct {
|
||||||
ecs_world_t *ecs;
|
ecs_world_t *ecs;
|
||||||
ecs_world_t *ecs_stage;
|
ecs_world_t *ecs_stage;
|
||||||
ecs_query_t *ecs_update;
|
ecs_query_t *ecs_update;
|
||||||
|
ecs_query_t *ecs_alive_player;
|
||||||
ecs_query_t *ecs_clientinfo;
|
ecs_query_t *ecs_clientinfo;
|
||||||
ecs_query_t *ecs_layeroverriden;
|
ecs_query_t *ecs_layeroverriden;
|
||||||
ecs_entity_t *chunk_mapping;
|
ecs_entity_t *chunk_mapping;
|
||||||
|
@ -72,6 +73,7 @@ uint32_t world_buf(block_id const **ptr, uint32_t *width);
|
||||||
uint32_t world_seed(void);
|
uint32_t world_seed(void);
|
||||||
ecs_world_t *world_ecs(void);
|
ecs_world_t *world_ecs(void);
|
||||||
ecs_query_t *world_ecs_player(void);
|
ecs_query_t *world_ecs_player(void);
|
||||||
|
ecs_query_t *world_ecs_alive_player(void);
|
||||||
ecs_query_t *world_ecs_clientinfo(void);
|
ecs_query_t *world_ecs_clientinfo(void);
|
||||||
void world_set_stage(ecs_world_t *ecs);
|
void world_set_stage(ecs_world_t *ecs);
|
||||||
librg_world *world_tracker(void);
|
librg_world *world_tracker(void);
|
||||||
|
|
|
@ -21,6 +21,10 @@ void game_player_departed(uint64_t ent) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game_player_died(uint64_t ent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void game_client_receive_code(pkt_send_code data) {
|
void game_client_receive_code(pkt_send_code data) {
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,6 +22,10 @@ void game_player_departed(uint64_t ent) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game_player_died(uint64_t ent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void game_client_receive_code(pkt_send_code data) {
|
void game_client_receive_code(pkt_send_code data) {
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,12 +19,60 @@ static ecs_query_t *ecs_pawn_query = NULL;
|
||||||
#include "system_mob.c"
|
#include "system_mob.c"
|
||||||
#include "system_weapon.c"
|
#include "system_weapon.c"
|
||||||
|
|
||||||
|
#define PLAYER_RESPAWN_BLAST_FORCE 1200.0f
|
||||||
|
|
||||||
|
void PlayerRespawn(ecs_iter_t *it) {
|
||||||
|
Respawn *r = ecs_field(it, Respawn, 1);
|
||||||
|
Input *in = ecs_field(it, Input, 2);
|
||||||
|
Sprite *s = ecs_field(it, Sprite, 3);
|
||||||
|
Position *p = ecs_field(it, Position, 4);
|
||||||
|
Health *h = ecs_field(it, Health, 5);
|
||||||
|
|
||||||
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
if (r[i].timer > 0) {
|
||||||
|
TICK_VAR(r[i].timer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecs_remove(it->world, it->entities[i], Respawn);
|
||||||
|
ecs_remove(it->world, it->entities[i], Dead);
|
||||||
|
in[i].is_blocked = 0;
|
||||||
|
s[i].spritesheet = 0;
|
||||||
|
h[i].hp = h[i].max_hp;
|
||||||
|
|
||||||
|
size_t ents_count;
|
||||||
|
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < ents_count; j++) {
|
||||||
|
uint64_t ent_id = ents[j];
|
||||||
|
|
||||||
|
if (!ecs_get(it->world, ent_id, Mob) || ecs_get(it->world, ent_id, Dead)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Position *p2 = ecs_get(it->world, ent_id, Position);
|
||||||
|
Velocity *v = ecs_get_mut(it->world, ent_id, Velocity);
|
||||||
|
float dx = p2->x - p[i].x;
|
||||||
|
float dy = p2->y - p[i].y;
|
||||||
|
float range = zpl_sqrt(dx*dx + dy*dy);
|
||||||
|
if (range <= 5*WORLD_BLOCK_SIZE) {
|
||||||
|
Health *hp = ecs_get_mut(it->world, ent_id, Health);
|
||||||
|
hp->dmg += hp->max_hp/2.0f;
|
||||||
|
|
||||||
|
v->x += (dx/range)*PLAYER_RESPAWN_BLAST_FORCE;
|
||||||
|
v->y += (dy/range)*PLAYER_RESPAWN_BLAST_FORCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mob_systems(ecs_world_t *ecs) {
|
void mob_systems(ecs_world_t *ecs) {
|
||||||
ECS_SYSTEM_TICKED_EX(ecs, MobDetectPlayers, EcsPostUpdate, 100.0f, components.Position, components.Mob, !components.Dead);
|
ECS_SYSTEM_TICKED_EX(ecs, MobDetectPlayers, EcsPostUpdate, 100.0f, components.Position, components.Mob, !components.Dead);
|
||||||
ECS_SYSTEM(ecs, MobMovement, EcsPostUpdate, components.Velocity, components.Position, components.MobHuntPlayer, !components.Dead);
|
ECS_SYSTEM(ecs, MobMovement, EcsPostUpdate, components.Velocity, components.Position, components.MobHuntPlayer, !components.Dead);
|
||||||
ECS_SYSTEM_TICKED(ecs, MobMeleeAtk, EcsPostUpdate, components.Position, components.Mob, components.MobHuntPlayer, components.MobMelee, !components.Dead);
|
ECS_SYSTEM_TICKED(ecs, MobMeleeAtk, EcsPostUpdate, components.Position, components.Mob, components.MobHuntPlayer, components.MobMelee, !components.Dead);
|
||||||
ECS_SYSTEM_TICKED(ecs, MobDespawnDead, EcsPostUpdate, components.Mob, components.Dead);
|
ECS_SYSTEM_TICKED(ecs, MobDespawnDead, EcsPostUpdate, components.Mob, components.Dead);
|
||||||
ECS_SYSTEM_TICKED(ecs, MobSpawner, EcsPostUpdate, components.Input, components.Position);
|
ECS_SYSTEM_TICKED(ecs, MobSpawner, EcsPostUpdate, components.Input, components.Position, !components.Dead);
|
||||||
|
ECS_SYSTEM_TICKED(ecs, PlayerRespawn, EcsPostUpdate, components.Respawn, components.Input, components.Sprite, components.Position, components.Health);
|
||||||
|
|
||||||
//NOTE(DavoSK): weapons
|
//NOTE(DavoSK): weapons
|
||||||
ecs_mobpos_query = ecs_query_new(world_ecs(), "components.Mob, components.Position, components.Health, components.Velocity, !components.Dead");
|
ecs_mobpos_query = ecs_query_new(world_ecs(), "components.Mob, components.Position, components.Health, components.Velocity, !components.Dead");
|
||||||
|
@ -51,6 +99,10 @@ void game_setup_ecs() {
|
||||||
mob_systems(world_ecs());
|
mob_systems(world_ecs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void game_player_departed(uint64_t ent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void game_player_joined(uint64_t ent) {
|
void game_player_joined(uint64_t ent) {
|
||||||
notification_push("test1", "Hello World!");
|
notification_push("test1", "Hello World!");
|
||||||
|
|
||||||
|
@ -63,8 +115,14 @@ void game_player_joined(uint64_t ent) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_player_departed(uint64_t ent) {
|
void game_player_died(uint64_t ent) {
|
||||||
|
Sprite *spr = ecs_get_mut(world_ecs(), ent, Sprite);
|
||||||
|
Velocity *v = ecs_get_mut(world_ecs(), ent, Velocity);
|
||||||
|
spr->frame = 3 + (rand()%5);
|
||||||
|
spr->spritesheet = 69; /*special code*/
|
||||||
|
*v = (Velocity){0.0f, 0.0f};
|
||||||
|
ecs_remove(world_ecs(), ent, PhysicsBody);
|
||||||
|
ecs_set(world_ecs(), ent, Respawn, { 100 });
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_client_receive_code(pkt_send_code data) {
|
void game_client_receive_code(pkt_send_code data) {
|
||||||
|
|
|
@ -27,14 +27,14 @@ ZPL_DIAGNOSTIC_POP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO
|
TODO
|
||||||
- monster spawner
|
+ monster spawner
|
||||||
- the longer we survive, the more and stronger enemies we spawn
|
+ the longer we survive, the more and stronger enemies we spawn
|
||||||
- player grows HP by leveling up
|
- player grows HP by leveling up
|
||||||
- XP increases by killing mobs
|
- XP increases by killing mobs
|
||||||
- player can pick an "ability" upon reaching level milestones
|
- player can pick an "ability" upon reaching level milestones
|
||||||
- abilities: armor/shield, TODO ...
|
- abilities: armor/shield, TODO ...
|
||||||
- enemies damage player when close to him in ticks (damage effects, ...)
|
+ enemies damage player when close to him in ticks (damage effects, ...)
|
||||||
- basic projectile pooling (flecs)
|
+ basic projectile pooling (flecs)
|
||||||
- somewhat believable world gen, small hamlets with cols, etc
|
- somewhat believable world gen, small hamlets with cols, etc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,7 @@ void platform_render() {
|
||||||
|
|
||||||
debug_draw();
|
debug_draw();
|
||||||
|
|
||||||
|
#if defined(_DEBUG)
|
||||||
if (nk_begin(game_ui, "Spritesheet Viewer", nk_rect(460, 100, 800, 600),
|
if (nk_begin(game_ui, "Spritesheet Viewer", nk_rect(460, 100, 800, 600),
|
||||||
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|NK_WINDOW_TITLE))
|
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|NK_WINDOW_TITLE))
|
||||||
{
|
{
|
||||||
|
@ -117,6 +118,7 @@ void platform_render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
notification_draw();
|
notification_draw();
|
||||||
|
#endif
|
||||||
game_draw_ui();
|
game_draw_ui();
|
||||||
}
|
}
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|
|
@ -23,7 +23,9 @@ void DrawNametag(const char* name, uint64_t key, entity_view *data, float x, flo
|
||||||
const char *title = TextFormat("%s %llu", name, key);
|
const char *title = TextFormat("%s %llu", name, key);
|
||||||
float title_w = MeasureTextEco(title, font_size, font_spacing);
|
float title_w = MeasureTextEco(title, font_size, font_spacing);
|
||||||
DrawRectangleEco(x-title_w/2.f-title_bg_offset/2.f, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(BLACK, data->tran_time));
|
DrawRectangleEco(x-title_w/2.f-title_bg_offset/2.f, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(BLACK, data->tran_time));
|
||||||
|
if (health > 0.0f && health <= 1.0f) {
|
||||||
DrawRectangleEco(x-title_w/2.f-title_bg_offset/2.f, y-size-fixed_title_offset, title_w*health+title_bg_offset, font_size*0.2f, ColorAlpha(RED, data->tran_time));
|
DrawRectangleEco(x-title_w/2.f-title_bg_offset/2.f, y-size-fixed_title_offset, title_w*health+title_bg_offset, font_size*0.2f, ColorAlpha(RED, data->tran_time));
|
||||||
|
}
|
||||||
DrawTextEco(title, x-title_w/2.f, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
|
DrawTextEco(title, x-title_w/2.f, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +48,8 @@ void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entr
|
||||||
tex.texture.height *= (int32_t)scale;
|
tex.texture.height *= (int32_t)scale;
|
||||||
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
||||||
} else {
|
} else {
|
||||||
DrawTextureRec(GetBlockImage(entry->blk_id), ASSET_SRC_RECT(), (Vector2){entry->x-(WORLD_BLOCK_SIZE/2), entry->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
|
Texture2D tex = GetBlockImage(entry->blk_id);
|
||||||
|
DrawTextureRec(tex, ASSET_SRC_RECT_TEX(tex.width, tex.height), (Vector2){entry->x-tex.width/2.0f, entry->y-(tex.height-WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
case EKIND_VEHICLE: {
|
case EKIND_VEHICLE: {
|
||||||
|
@ -87,9 +90,7 @@ void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entr
|
||||||
case EKIND_MONSTER: {
|
case EKIND_MONSTER: {
|
||||||
float x = data->x;
|
float x = data->x;
|
||||||
float y = data->y;
|
float y = data->y;
|
||||||
//DrawCircleEco(x, y, size, ColorAlpha(PINK, data->tran_time));
|
DrawSpriteEco(&main_sprite_sheet, data->frame, x, y, 0.0f, 2.0f, ColorAlpha(WHITE, data->tran_time));
|
||||||
// DrawTextureRec(GetSpriteTexture2D(assets_find(data->frame)), ASSET_SRC_RECT(), (Vector2){data->x-(WORLD_BLOCK_SIZE/2), data->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
|
|
||||||
DrawSpriteEco(&main_sprite_sheet, data->frame, x, y, 0.0f, 2.0f, WHITE);
|
|
||||||
|
|
||||||
float health = (data->hp / data->max_hp);
|
float health = (data->hp / data->max_hp);
|
||||||
|
|
||||||
|
@ -105,6 +106,10 @@ void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entr
|
||||||
DrawNametag("Player", key, data, x, y-16);
|
DrawNametag("Player", key, data, x, y-16);
|
||||||
//DrawTextureRec(GetSpriteTexture2D(assets_find(ASSET_PLAYER)), ASSET_SRC_RECT(), (Vector2){data->x-(WORLD_BLOCK_SIZE/2), data->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
|
//DrawTextureRec(GetSpriteTexture2D(assets_find(ASSET_PLAYER)), ASSET_SRC_RECT(), (Vector2){data->x-(WORLD_BLOCK_SIZE/2), data->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
|
||||||
//DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
//DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
||||||
|
|
||||||
|
if (data->spritesheet == 69)
|
||||||
|
DrawSpriteEco(&main_sprite_sheet, data->frame, x, y, 0.0f, 2.0f, ColorAlpha(WHITE, data->tran_time));
|
||||||
|
else
|
||||||
DrawSpriteEco(test_player_anim.spritesheet, TickSpriteAnimation(&test_player_anim), x, y, 0.0f, 2.0f, WHITE);
|
DrawSpriteEco(test_player_anim.spritesheet, TickSpriteAnimation(&test_player_anim), x, y, 0.0f, 2.0f, WHITE);
|
||||||
|
|
||||||
//if (data->has_items && !data->inside_vehicle) {
|
//if (data->has_items && !data->inside_vehicle) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#define MOB_SPAWN_DELAY (uint16_t)(20*1.5f)
|
#define MOB_SPAWN_DELAY (uint16_t)(20*1.5f)
|
||||||
#define MOB_SPAWN_PERCENTAGE_FROM_MAX 0.05f
|
#define MOB_SPAWN_PERCENTAGE_FROM_MAX 0.05f
|
||||||
#define MOB_INITIAL_MAX 50
|
#define MOB_INITIAL_MAX 50
|
||||||
#define MOB_GROWTH_FACTOR 5.0f
|
#define MOB_GROWTH_FACTOR 0.65f
|
||||||
#define MOB_GROWTH_CONTROL 50.0f
|
#define MOB_GROWTH_CONTROL 1.17f
|
||||||
#define MOB_SPAWN_DIST 12*WORLD_BLOCK_SIZE;
|
#define MOB_SPAWN_DIST 12*WORLD_BLOCK_SIZE;
|
||||||
#define MOB_MAX_SPAWN_TRIES 5
|
#define MOB_MAX_SPAWN_TRIES 5
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@ static uint16_t mob_spawn_timer = MOB_SPAWN_DELAY;
|
||||||
static int16_t player_spawn_counter = -1;
|
static int16_t player_spawn_counter = -1;
|
||||||
|
|
||||||
void recalc_max_mobs() {
|
void recalc_max_mobs() {
|
||||||
max_mobs = (uint64_t)zpl_round(MOB_INITIAL_MAX + MOB_GROWTH_FACTOR * zpl_exp((float)mob_kills / MOB_GROWTH_CONTROL));
|
max_mobs = (uint64_t)(MOB_INITIAL_MAX + MOB_GROWTH_FACTOR * zpl_pow((float)mob_kills, MOB_GROWTH_CONTROL));
|
||||||
zpl_printf("Max mobs: %d\n", max_mobs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MobDetectPlayers(ecs_iter_t *it) {
|
void MobDetectPlayers(ecs_iter_t *it) {
|
||||||
|
@ -23,7 +22,7 @@ void MobDetectPlayers(ecs_iter_t *it) {
|
||||||
float closest_ent_dist = ZPL_F32_MAX;
|
float closest_ent_dist = ZPL_F32_MAX;
|
||||||
uint64_t closest_ent = 0;
|
uint64_t closest_ent = 0;
|
||||||
|
|
||||||
ecs_iter_t pit = ecs_query_iter(world_ecs(), world_ecs_player());
|
ecs_iter_t pit = ecs_query_iter(world_ecs(), world_ecs_alive_player());
|
||||||
|
|
||||||
while (ecs_query_next(&pit)) {
|
while (ecs_query_next(&pit)) {
|
||||||
Position *p2 = ecs_field(&pit, Position, 2);
|
Position *p2 = ecs_field(&pit, Position, 2);
|
||||||
|
@ -54,6 +53,10 @@ void MobMovement(ecs_iter_t *it) {
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
const Position *p2 = ecs_get(it->world, m->plr, Position);
|
const Position *p2 = ecs_get(it->world, m->plr, Position);
|
||||||
|
if (p2 == NULL) {
|
||||||
|
ecs_remove(it->world, it->entities[i], MobHuntPlayer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
zpl_vec2 pos1 = { .x = p[i].x, .y = p[i].y };
|
zpl_vec2 pos1 = { .x = p[i].x, .y = p[i].y };
|
||||||
zpl_vec2 pos2 = { .x = p2->x, .y = p2->y };
|
zpl_vec2 pos2 = { .x = p2->x, .y = p2->y };
|
||||||
zpl_vec2 dir;
|
zpl_vec2 dir;
|
||||||
|
@ -71,6 +74,7 @@ void MobMovement(ecs_iter_t *it) {
|
||||||
#define MOB_MELEE_DMG 8.5f
|
#define MOB_MELEE_DMG 8.5f
|
||||||
#define MOB_ATK_DELAY 10
|
#define MOB_ATK_DELAY 10
|
||||||
#define MOB_DESPAWN_TIMER 20*60*5
|
#define MOB_DESPAWN_TIMER 20*60*5
|
||||||
|
#define MOB_HIT_FORCE_PUSH 250.0f
|
||||||
|
|
||||||
void MobMeleeAtk(ecs_iter_t *it) {
|
void MobMeleeAtk(ecs_iter_t *it) {
|
||||||
Position *p = ecs_field(it, Position, 1);
|
Position *p = ecs_field(it, Position, 1);
|
||||||
|
@ -83,15 +87,25 @@ void MobMeleeAtk(ecs_iter_t *it) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ecs_get(it->world, m->plr, Dead)) {
|
||||||
|
ecs_remove(it->world, it->entities[i], MobHuntPlayer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const Position *p2 = ecs_get(it->world, m->plr, Position);
|
const Position *p2 = ecs_get(it->world, m->plr, Position);
|
||||||
|
Velocity *v2 = ecs_get_mut(it->world, m->plr, Velocity);
|
||||||
|
|
||||||
float dx = p2->x - p[i].x;
|
float dx = p2->x - p[i].x;
|
||||||
float dy = p2->y - p[i].y;
|
float dy = p2->y - p[i].y;
|
||||||
float range = (dx*dx + dy*dy);
|
float range = (dx*dx + dy*dy);
|
||||||
|
|
||||||
if (range < MOB_MELEE_DIST) {
|
if (range < MOB_MELEE_DIST) {
|
||||||
|
float dd = zpl_sqrt(range);
|
||||||
Health *health = ecs_get_mut(it->world, m->plr, Health);
|
Health *health = ecs_get_mut(it->world, m->plr, Health);
|
||||||
health->dmg += MOB_MELEE_DMG;
|
health->dmg += MOB_MELEE_DMG;
|
||||||
mob[i].atk_delay = MOB_ATK_DELAY;
|
mob[i].atk_delay = MOB_ATK_DELAY;
|
||||||
|
v2->x += (dx/dd)*MOB_HIT_FORCE_PUSH;
|
||||||
|
v2->y += (dy/dd)*MOB_HIT_FORCE_PUSH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ block_id worldgen_biome_find(uint32_t biome, uint32_t kind) {
|
||||||
return blocks_find(asset);
|
return blocks_find(asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
int32_t worldgen_build(world_data *wld) {
|
int32_t worldgen_build(world_data *wld) {
|
||||||
// TODO(zaklaus): pass world as an arg instead
|
// TODO(zaklaus): pass world as an arg instead
|
||||||
world = wld;
|
world = wld;
|
||||||
|
@ -67,3 +68,58 @@ int32_t worldgen_build(world_data *wld) {
|
||||||
|
|
||||||
return WORLD_ERROR_NONE;
|
return WORLD_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
int32_t worldgen_build(world_data *wld) {
|
||||||
|
// TODO(zaklaus): pass world as an arg instead
|
||||||
|
world = wld;
|
||||||
|
|
||||||
|
// TODO: perform world gen
|
||||||
|
// atm, we will fill the world with ground and surround it by walls
|
||||||
|
block_id wall_id = worldgen_biome_find(BLOCK_BIOME_DEV, BLOCK_KIND_WALL);
|
||||||
|
block_id grnd_id = worldgen_biome_find(BLOCK_BIOME_DEV, BLOCK_KIND_GROUND);
|
||||||
|
block_id dirt_id = worldgen_biome_find(BLOCK_BIOME_DEV, BLOCK_KIND_DIRT);
|
||||||
|
block_id watr_id = worldgen_biome_find(BLOCK_BIOME_DEV, BLOCK_KIND_WATER);
|
||||||
|
block_id lava_id = worldgen_biome_find(BLOCK_BIOME_DEV, BLOCK_KIND_LAVA);
|
||||||
|
block_id tree_id = blocks_find(ASSET_TREE);
|
||||||
|
|
||||||
|
srand(world->seed);
|
||||||
|
|
||||||
|
// walls
|
||||||
|
world_fill_rect(world->data, wall_id, 0, 0, world->dim, world->dim, NULL);
|
||||||
|
|
||||||
|
// ground
|
||||||
|
world_fill_rect(world->data, grnd_id, 1, 1, world->dim-2, world->dim-2, NULL);
|
||||||
|
world_fill_rect(world->data, dirt_id, 1, 1, world->dim-2, world->dim-2, shaper_noise05);
|
||||||
|
world_fill_rect(world->outer_data, tree_id, 1, 1, world->dim-2, world->dim-2, shaper_noise01b);
|
||||||
|
|
||||||
|
// water
|
||||||
|
#if 1
|
||||||
|
for (int i=0; i<RAND_RANGE(58, 92); i++) {
|
||||||
|
world_fill_rect_anchor(world->outer_data, watr_id, RAND_RANGE(0, world->dim), RAND_RANGE(0, world->dim), 4+RAND_RANGE(0,3), 4+RAND_RANGE(0,3), 0.5f, 0.5f, shaper_noise80);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ice rink
|
||||||
|
#if 0
|
||||||
|
world_fill_rect_anchor(world->data, watr_id, 450, 125, 10, 10, 0.0f, 0.0f, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// lava
|
||||||
|
#if 1
|
||||||
|
for (int i=0; i<RAND_RANGE(48, 62); i++) {
|
||||||
|
world_fill_rect_anchor(world->data, lava_id, RAND_RANGE(0, world->dim), RAND_RANGE(0, world->dim), 4+RAND_RANGE(0,3), 4+RAND_RANGE(0,3), 0.5f, 0.5f, shaper_noise80);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// hills
|
||||||
|
#if 1
|
||||||
|
const uint32_t HILLS_SIZE = 21;
|
||||||
|
for (int i=0; i<RAND_RANGE(8, 124); i++) {
|
||||||
|
world_fill_rect_anchor(world->data, wall_id, RAND_RANGE(0, world->dim), RAND_RANGE(0, world->dim), RAND_RANGE(0,HILLS_SIZE), RAND_RANGE(0,HILLS_SIZE), 0.5f, 0.5f, shaper_noise50);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return WORLD_ERROR_NONE;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,14 @@
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
rem build web first
|
||||||
|
call web.bat
|
||||||
|
|
||||||
|
if not %ERRORLEVEL% == 0 exit /B 1
|
||||||
|
@rd /S /Q pkg
|
||||||
|
mkdir pkg
|
||||||
|
copy ..\build_web\survival.* pkg
|
||||||
|
copy ..\build_web\survival.html pkg\index.html
|
||||||
|
|
||||||
|
IF NOT "%1"=="SKIP_DEPLOY" (
|
||||||
|
butler push pkg zaklaus/zplsurvival:html-latest
|
||||||
|
)
|
Loading…
Reference in New Issue