mob spawner + friendly fire
parent
d864661e65
commit
213710e922
|
@ -260,6 +260,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t damage;
|
uint8_t damage;
|
||||||
float origin_x, origin_y;
|
float origin_x, origin_y;
|
||||||
|
ecs_entity_t owner;
|
||||||
} WeaponProjectile;
|
} WeaponProjectile;
|
||||||
|
|
||||||
#define _COMPS\
|
#define _COMPS\
|
||||||
|
|
|
@ -8,7 +8,12 @@
|
||||||
|
|
||||||
#include "gui/notifications.h"
|
#include "gui/notifications.h"
|
||||||
|
|
||||||
|
float get_rand_between(float min, float max) {
|
||||||
|
return ((float)rand() / (float)RAND_MAX) * (max - min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
static ecs_query_t *ecs_mobpos_query = NULL;
|
static ecs_query_t *ecs_mobpos_query = NULL;
|
||||||
|
static ecs_query_t *ecs_pawn_query = NULL;
|
||||||
|
|
||||||
// custom systems
|
// custom systems
|
||||||
#include "system_mob.c"
|
#include "system_mob.c"
|
||||||
|
@ -19,9 +24,11 @@ void mob_systems(ecs_world_t *ecs) {
|
||||||
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);
|
||||||
|
|
||||||
//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");
|
||||||
|
ecs_pawn_query = ecs_query_new(world_ecs(), "components.Position, components.Health, components.Velocity, !components.Dead");
|
||||||
ECS_SYSTEM_TICKED(ecs, WeaponKnifeMechanic, EcsPostUpdate, components.WeaponKnife, components.Position, components.Input, !components.Dead);
|
ECS_SYSTEM_TICKED(ecs, WeaponKnifeMechanic, EcsPostUpdate, components.WeaponKnife, components.Position, components.Input, !components.Dead);
|
||||||
ECS_SYSTEM_TICKED(ecs, WeaponProjectileHit, EcsPostUpdate, components.WeaponProjectile, components.Position, components.Rotation);
|
ECS_SYSTEM_TICKED(ecs, WeaponProjectileHit, EcsPostUpdate, components.WeaponProjectile, components.Position, components.Rotation);
|
||||||
ECS_SYSTEM_TICKED(ecs, WeaponProjectileExpire, EcsPostUpdate, components.WeaponProjectile, components.Position);
|
ECS_SYSTEM_TICKED(ecs, WeaponProjectileExpire, EcsPostUpdate, components.WeaponProjectile, components.Position);
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
#define MOB_SPAWN_DELAY (uint16_t)(20*1.5f)
|
||||||
|
#define MOB_SPAWN_PERCENTAGE_FROM_MAX 0.05f
|
||||||
|
#define MOB_INITIAL_MAX 50
|
||||||
|
#define MOB_GROWTH_FACTOR 5.0f
|
||||||
|
#define MOB_GROWTH_CONTROL 50.0f
|
||||||
|
#define MOB_SPAWN_DIST 12*WORLD_BLOCK_SIZE;
|
||||||
|
#define MOB_MAX_SPAWN_TRIES 5
|
||||||
|
|
||||||
|
static uint64_t max_mobs = MOB_INITIAL_MAX;
|
||||||
|
static uint64_t mob_kills = 0;
|
||||||
|
static uint16_t mob_spawn_timer = MOB_SPAWN_DELAY;
|
||||||
|
static int16_t player_spawn_counter = -1;
|
||||||
|
|
||||||
|
void recalc_max_mobs() {
|
||||||
|
max_mobs = (uint64_t)zpl_round(MOB_INITIAL_MAX + MOB_GROWTH_FACTOR * zpl_exp((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) {
|
||||||
Position *p = ecs_field(it, Position, 1);
|
Position *p = ecs_field(it, Position, 1);
|
||||||
|
|
||||||
|
@ -27,10 +45,6 @@ void MobDetectPlayers(ecs_iter_t *it) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MobDetectPlayers1(ecs_iter_t *it) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MOB_MOVEMENT_SPEED 300.0f
|
#define MOB_MOVEMENT_SPEED 300.0f
|
||||||
|
|
||||||
void MobMovement(ecs_iter_t *it) {
|
void MobMovement(ecs_iter_t *it) {
|
||||||
|
@ -93,6 +107,9 @@ void MobOnDead(ecs_iter_t *it) {
|
||||||
v[i] = (Velocity){0.0f, 0.0f};
|
v[i] = (Velocity){0.0f, 0.0f};
|
||||||
ecs_remove(it->world, it->entities[i], PhysicsBody);
|
ecs_remove(it->world, it->entities[i], PhysicsBody);
|
||||||
|
|
||||||
|
++mob_kills;
|
||||||
|
recalc_max_mobs();
|
||||||
|
|
||||||
pkt_code_send(0, 0, (pkt_send_code){
|
pkt_code_send(0, 0, (pkt_send_code){
|
||||||
.code = SURV_CODE_SHOW_NOTIF,
|
.code = SURV_CODE_SHOW_NOTIF,
|
||||||
.data = "mob died"
|
.data = "mob died"
|
||||||
|
@ -114,5 +131,65 @@ void MobDespawnDead(ecs_iter_t *it) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MobSpawner(ecs_iter_t *it) {
|
void MobSpawner(ecs_iter_t *it) {
|
||||||
|
Position *pos = ecs_field(it, Position, 2);
|
||||||
|
|
||||||
|
if (mob_spawn_timer > 0) {
|
||||||
|
TICK_VAR(mob_spawn_timer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecs_iter_t mob_it = ecs_query_iter(it->world, ecs_mobpos_query);
|
||||||
|
uint64_t curr_mobs = 0;
|
||||||
|
while (ecs_query_next(&mob_it)) {
|
||||||
|
curr_mobs += mob_it.count;
|
||||||
|
}
|
||||||
|
if (curr_mobs >= max_mobs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t mobs_to_spawn = zpl_max(1, (uint16_t)zpl_floor(MOB_SPAWN_PERCENTAGE_FROM_MAX*max_mobs));
|
||||||
|
player_spawn_counter = (player_spawn_counter+1)%it->count;
|
||||||
|
|
||||||
|
for (int i = player_spawn_counter; i < it->count; i++) {
|
||||||
|
const uint32_t radius = MOB_SPAWN_DIST;
|
||||||
|
uint32_t ox = (uint32_t)pos[i].x;
|
||||||
|
uint32_t oy = (uint32_t)pos[i].y;
|
||||||
|
|
||||||
|
uint8_t tries_done = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (mobs_to_spawn == 0) {
|
||||||
|
mob_spawn_timer = MOB_SPAWN_DELAY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tries_done == MOB_MAX_SPAWN_TRIES) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float angle = get_rand_between(0, 2*ZPL_PI);
|
||||||
|
float dist = get_rand_between((float)radius, radius*1.5f);
|
||||||
|
|
||||||
|
uint32_t cx = (uint32_t)(ox + dist * zpl_cos(angle));
|
||||||
|
uint32_t cy = (uint32_t)(oy + dist * zpl_sin(angle));
|
||||||
|
|
||||||
|
if (cx >= world_dim() || cy >= world_dim() || cx <= 0 || cy <= 0) {
|
||||||
|
tries_done++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
world_block_lookup l = world_block_from_realpos((float)cx, (float)cy);
|
||||||
|
uint32_t flags = blocks_get_flags(l.bid);
|
||||||
|
|
||||||
|
if (flags & BLOCK_FLAG_COLLISION) {
|
||||||
|
tries_done++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecs_entity_t e = entity_spawn_id(ASSET_MOB);
|
||||||
|
entity_set_position(e, (float)cx, (float)cy);
|
||||||
|
ecs_add(world_ecs(), e, MobMelee);
|
||||||
|
mobs_to_spawn--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,6 @@ ZPL_DIAGNOSTIC_POP
|
||||||
#define WEAPON_PROJECTILE_RANGE_LIFETIME 800.0f
|
#define WEAPON_PROJECTILE_RANGE_LIFETIME 800.0f
|
||||||
#define WEAPON_HIT_FORCE_PUSH 400.0f
|
#define WEAPON_HIT_FORCE_PUSH 400.0f
|
||||||
|
|
||||||
//TODO(DavoSK): move to helpers, add srand
|
|
||||||
float get_rand_between(float min, float max) {
|
|
||||||
return ((float)rand() / (float)RAND_MAX) * (max - min) + min;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WeaponKnifeMechanic(ecs_iter_t* it) {
|
void WeaponKnifeMechanic(ecs_iter_t* it) {
|
||||||
WeaponKnife* weapon = ecs_field(it, WeaponKnife, 1);
|
WeaponKnife* weapon = ecs_field(it, WeaponKnife, 1);
|
||||||
const Position* pos = ecs_field(it, Position, 2);
|
const Position* pos = ecs_field(it, Position, 2);
|
||||||
|
@ -31,7 +26,8 @@ void WeaponKnifeMechanic(ecs_iter_t* it) {
|
||||||
ecs_set(it->world, e, WeaponProjectile, {
|
ecs_set(it->world, e, WeaponProjectile, {
|
||||||
.damage = weapon[i].damage,
|
.damage = weapon[i].damage,
|
||||||
.origin_x = pos[i].x,
|
.origin_x = pos[i].x,
|
||||||
.origin_y = pos[i].y
|
.origin_y = pos[i].y,
|
||||||
|
.owner = it->entities[i]
|
||||||
});
|
});
|
||||||
ecs_set(it->world, e, StreamLayerOverride, { .layer = 0 });
|
ecs_set(it->world, e, StreamLayerOverride, { .layer = 0 });
|
||||||
|
|
||||||
|
@ -90,18 +86,20 @@ void WeaponProjectileHit(ecs_iter_t* it) {
|
||||||
const Rotation* rot = ecs_field(it, Rotation, 3);
|
const Rotation* rot = ecs_field(it, Rotation, 3);
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
ecs_iter_t it2 = ecs_query_iter(it->world, ecs_mobpos_query);
|
ecs_iter_t it2 = ecs_query_iter(it->world, ecs_pawn_query);
|
||||||
while (ecs_query_next(&it2)) {
|
while (ecs_query_next(&it2)) {
|
||||||
Mob* mob = ecs_field(&it2, Mob, 1);
|
Position* pawn_pos = ecs_field(&it2, Position, 1);
|
||||||
Position* mob_pos = ecs_field(&it2, Position, 2);
|
Health *pawn_health = ecs_field(&it2, Health, 2);
|
||||||
Health *mob_health = ecs_field(&it2, Health, 3);
|
Velocity *pawn_velocity = ecs_field(&it2, Velocity, 3);
|
||||||
Velocity *mob_velocity = ecs_field(&it2, Velocity, 4);
|
|
||||||
|
|
||||||
for (int j = 0; j < it2.count; j++) {
|
for (int j = 0; j < it2.count; j++) {
|
||||||
|
if (weapon[i].owner == it2.entities[j])
|
||||||
|
continue;
|
||||||
|
|
||||||
float p_x = pos[i].x;
|
float p_x = pos[i].x;
|
||||||
float p_y = pos[i].y;
|
float p_y = pos[i].y;
|
||||||
float p2_x = mob_pos[j].x /*+ v2[j].x*/;
|
float p2_x = pawn_pos[j].x /*+ v2[j].x*/;
|
||||||
float p2_y = mob_pos[j].y /*+ v2[j].y*/;
|
float p2_y = pawn_pos[j].y /*+ v2[j].y*/;
|
||||||
|
|
||||||
c2AABB box_a = {
|
c2AABB box_a = {
|
||||||
.min = { p_x - WORLD_BLOCK_SIZE / 4 , p_y - WORLD_BLOCK_SIZE / 4 },
|
.min = { p_x - WORLD_BLOCK_SIZE / 4 , p_y - WORLD_BLOCK_SIZE / 4 },
|
||||||
|
@ -133,10 +131,10 @@ void WeaponProjectileHit(ecs_iter_t* it) {
|
||||||
|
|
||||||
if (c2AABBtoAABB(box_a, box_b)) {
|
if (c2AABBtoAABB(box_a, box_b)) {
|
||||||
float dd = zpl_sqrt(d2);
|
float dd = zpl_sqrt(d2);
|
||||||
mob_health[j].dmg += weapon[i].damage;
|
pawn_health[j].dmg += weapon[i].damage;
|
||||||
|
|
||||||
mob_velocity[j].x += (dx/dd)*WEAPON_HIT_FORCE_PUSH;
|
pawn_velocity[j].x += (dx/dd)*WEAPON_HIT_FORCE_PUSH;
|
||||||
mob_velocity[j].y += (dy/dd)*WEAPON_HIT_FORCE_PUSH;
|
pawn_velocity[j].y += (dy/dd)*WEAPON_HIT_FORCE_PUSH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue