chucker start

This commit is contained in:
jacob 2025-05-16 19:59:20 -05:00
parent 1943b2d81b
commit c432ca5b77
5 changed files with 181 additions and 205 deletions

View File

@ -135,15 +135,16 @@ enum sim_sync_flag {
enum sim_control_flag { enum sim_control_flag {
SIM_CONTROL_FLAG_FIRE = 1 << 0, SIM_CONTROL_FLAG_FIRE = 1 << 0,
SIM_CONTROL_FLAG_FIRE_ALT = 1 << 1,
/* Testing */ /* Testing */
SIM_CONTROL_FLAG_DRAG = 1 << 1, SIM_CONTROL_FLAG_DRAG = 1 << 2,
SIM_CONTROL_FLAG_CLEAR_ALL = 1 << 2, SIM_CONTROL_FLAG_CLEAR_ALL = 1 << 3,
SIM_CONTROL_FLAG_SPAWN1_TEST = 1 << 3, SIM_CONTROL_FLAG_SPAWN1_TEST = 1 << 4,
SIM_CONTROL_FLAG_SPAWN2_TEST = 1 << 4, SIM_CONTROL_FLAG_SPAWN2_TEST = 1 << 5,
SIM_CONTROL_FLAG_TILE_TEST = 1 << 5, SIM_CONTROL_FLAG_TILE_TEST = 1 << 6,
SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 6, SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 7,
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 7, SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 8,
}; };
struct sim_control { struct sim_control {

View File

@ -48,10 +48,7 @@ enum sim_ent_prop {
SEPROP_BULLET, SEPROP_BULLET,
SEPROP_WEAPON_SMG, SEPROP_WEAPON_SMG,
SEPROP_WEAPON_LAUNCHER, SEPROP_WEAPON_LAUNCHER,
SEPROP_WEAPON_CHUCKER,
SEPROP_TRIGGERING_EQUIPPED,
SEPROP_TRIGGERED_THIS_TICK,
SEPROP_TRIGGER_NEXT_TICK,
SEPROP_EXPLOSION, SEPROP_EXPLOSION,
@ -285,11 +282,26 @@ struct sim_ent {
struct sim_ent_id equipped; struct sim_ent_id equipped;
/* ====================================================================== */ /* ====================================================================== */
/* Triggers */ /* Triggerable */
/* SEPROP_TRIGGERED_THIS_TICK */ i32 num_primary_triggers;
f32 trigger_delay; /* Minimum time between triggers */ i32 num_secondary_triggers;
i64 last_triggered_ns;
f32 primary_fire_delay;
f32 secondary_fire_delay;
i64 last_primary_fire_ns;
i64 last_secondary_fire_ns;
/* ====================================================================== */
/* Trigger */
/* How many times has this trigger been triggered this tick */
i64 triggered_count;
/* Other triggers to activate when this entity has been triggered */
//struct sim_ent_id trigger_out_left;
//struct sim_ent_id trigger_out_right;
/* ====================================================================== */ /* ====================================================================== */
/* Bullet */ /* Bullet */

View File

@ -121,9 +121,9 @@ INTERNAL struct sim_ent *spawn_test_employee(struct sim_step_ctx *ctx)
e->attach_slice = LIT("attach.wep"); e->attach_slice = LIT("attach.wep");
e->layer = SIM_LAYER_RELATIVE_WEAPON; e->layer = SIM_LAYER_RELATIVE_WEAPON;
sim_ent_enable_prop(e, SEPROP_WEAPON_LAUNCHER); sim_ent_enable_prop(e, SEPROP_WEAPON_CHUCKER);
e->trigger_delay = 1.0f / 10.0f; e->primary_fire_delay = 1.0f / 10.0f;
//e->trigger_delay = 1.0f / 100.0f; e->secondary_fire_delay = 1.0f / 10.0f;
employee->equipped = e->id; employee->equipped = e->id;
} }
@ -515,23 +515,7 @@ void sim_step(struct sim_step_ctx *ctx)
} }
/* ========================== * /* ========================== *
* Reset triggered entities * Process player cmds
* ========================== */
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SEPROP_TRIGGER_NEXT_TICK)) {
sim_ent_disable_prop(ent, SEPROP_TRIGGER_NEXT_TICK);
sim_ent_enable_prop(ent, SEPROP_TRIGGERED_THIS_TICK);
} else if (sim_ent_has_prop(ent, SEPROP_TRIGGERED_THIS_TICK)) {
sim_ent_disable_prop(ent, SEPROP_TRIGGERED_THIS_TICK);
}
}
/* ========================== *
* Process client cmds
* ========================== */ * ========================== */
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
@ -554,7 +538,7 @@ void sim_step(struct sim_step_ctx *ctx)
/* Player's will send control cmds a lot, so keep it around to prevent re-creating it each time */ /* Player's will send control cmds a lot, so keep it around to prevent re-creating it each time */
persist_cmd = true; persist_cmd = true;
/* Process control cmd for client */ /* Process control cmd for player */
struct sim_control old_control = player->player_control; struct sim_control old_control = player->player_control;
struct sim_control *control = &player->player_control; struct sim_control *control = &player->player_control;
*control = cmd_ent->cmd_control; *control = cmd_ent->cmd_control;
@ -566,20 +550,12 @@ void sim_step(struct sim_step_ctx *ctx)
player->player_dbg_drag_start = false; player->player_dbg_drag_start = false;
player->player_dbg_drag_stop = false; player->player_dbg_drag_stop = false;
/* Cap movement vector magnitude at 1 */ /* Cap movement vector magnitude */
if (v2_len_sq(control->move) > 1) { if (v2_len_sq(control->move) > 1) {
control->move = v2_norm(control->move); control->move = v2_norm(control->move);
} }
if (flags & SIM_CONTROL_FLAG_TELEPORT_TEST) { /* Debug cmds */
logf_info("Teleport (test)");
struct sim_ent *ent = sim_ent_from_id(world, player->player_control_ent);
if (ent->valid) {
test_teleport(ent, player->player_cursor_pos);
}
}
/* Non-predicted cmds */
if (ctx->is_master) { if (ctx->is_master) {
if (flags & SIM_CONTROL_FLAG_DRAG) { if (flags & SIM_CONTROL_FLAG_DRAG) {
if (!(old_control.flags & SIM_CONTROL_FLAG_DRAG)) { if (!(old_control.flags & SIM_CONTROL_FLAG_DRAG)) {
@ -596,15 +572,13 @@ void sim_step(struct sim_step_ctx *ctx)
} }
} }
if (flags & SIM_CONTROL_FLAG_SPAWN1_TEST) { if (flags & SIM_CONTROL_FLAG_SPAWN1_TEST) {
if (!(old_control.flags & SIM_CONTROL_FLAG_SPAWN1_TEST)) { logf_info("Spawn1 (test)");
logf_info("Spawn1 (test)"); u32 count = 1;
u32 count = 1; f32 spread = 0;
f32 spread = 0; for (u32 j = 0; j < count; ++j) {
for (u32 j = 0; j < count; ++j) { struct v2 pos = player->player_cursor_pos;
struct v2 pos = player->player_cursor_pos; pos.y += (((f32)j / (f32)count) - 0.5) * spread;
pos.y += (((f32)j / (f32)count) - 0.5) * spread; spawn_test_entities1(ctx, pos);
spawn_test_entities1(ctx, pos);
}
} }
} }
if (flags & SIM_CONTROL_FLAG_SPAWN2_TEST) { if (flags & SIM_CONTROL_FLAG_SPAWN2_TEST) {
@ -691,7 +665,23 @@ void sim_step(struct sim_step_ctx *ctx)
} }
/* ========================== * /* ========================== *
* Create client player ents * Update entity control from player control
* ========================== */
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
struct sim_ent *player = sim_ent_from_id(world, ent->controlling_player);
if (player->valid) {
ent->control = player->player_control;
}
}
}
/* ========================== *
* Create employees
* ========================== */ * ========================== */
if (is_master) { if (is_master) {
@ -718,28 +708,6 @@ void sim_step(struct sim_step_ctx *ctx)
} }
} }
/* ========================== *
* Update entity control from client control
* ========================== */
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
struct sim_ent *player = sim_ent_from_id(world, ent->controlling_player);
if (player->valid) {
ent->control = player->player_control;
/* TODO: Move this */
if (ent->control.flags & SIM_CONTROL_FLAG_FIRE) {
sim_ent_enable_prop(ent, SEPROP_TRIGGERING_EQUIPPED);
} else {
sim_ent_disable_prop(ent, SEPROP_TRIGGERING_EQUIPPED);
}
}
}
}
/* ========================== * /* ========================== *
* Update entities from sprite * Update entities from sprite
* ========================== */ * ========================== */
@ -866,68 +834,30 @@ void sim_step(struct sim_step_ctx *ctx)
} }
/* ========================== * /* ========================== *
* Test * Process ent control
* ========================== */
#if 0
for (u64 ent_index = 0; ent_index < ss_blended->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &ss_blended->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_has_prop(ent, SEPROP_TEST)) continue;
#if 0
if (!ent->test_initialized) {
ent->test_initialized = true;
ent->test_start_local_xform = sim_ent_get_local_xform(ent);
ent->test_start_sprite_xform = ent->sprite_local_xform;
}
f32 t = (f32)time;
struct v2 og = v2_mul(V2(math_cos(t), math_sin(t)), 3);
f32 r = t * 3;
struct v2 s = V2(1 + (math_fabs(math_sin(t * 5)) * 3), 1);
(UNUSED)og;
(UNUSED)r;
(UNUSED)s;
og = v2_add(og, ent->test_start_local_xform.og);
r += xform_get_rotation(ent->test_start_local_xform);
s = v2_add(s, xform_get_scale(ent->test_start_local_xform));
struct xform xf = sim_ent_get_local_xform(ent);
xf.og = og;
xf = xform_rotated_to(xf, r);
xf = xform_scaled_to(xf, s);
sim_ent_set_local_xform(ent, xf);
#else
f32 t = (f32)time;
struct v2 og = v2_mul(V2(math_cos(t), math_sin(t)), 3);
f32 rot = t * PI / 3;
struct v2 scale = V2(1 + (math_fabs(math_sin(t * 5)) * 3), 1);
(UNUSED)og;
(UNUSED)rot;
(UNUSED)scale;
struct xform xf = sim_ent_get_local_xform(ent);
xf = xform_rotated_to(xf, rot);
xf = xform_scaled_to(xf, scale);
sim_ent_set_local_xform(ent, xf);
#endif
}
#endif
/* ========================== *
* Trigger equipped
* ========================== */ * ========================== */
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SEPROP_TRIGGERING_EQUIPPED)) { if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
struct sim_ent *eq = sim_ent_from_id(world, ent->equipped); struct sim_control *control = &ent->control;
if (sim_ent_should_simulate(eq)) { u32 flags = control->flags;
sim_ent_enable_prop(eq, SEPROP_TRIGGERED_THIS_TICK); if (flags & SIM_CONTROL_FLAG_FIRE) {
struct sim_ent *equipped = sim_ent_from_id(world, ent->equipped);
if (equipped->valid) {
++equipped->num_primary_triggers;
}
}
if (flags & SIM_CONTROL_FLAG_FIRE_ALT) {
struct sim_ent *equipped = sim_ent_from_id(world, ent->equipped);
if (equipped->valid) {
++equipped->num_secondary_triggers;
}
}
if (flags & SIM_CONTROL_FLAG_TELEPORT_TEST) {
test_teleport(ent, control->dbg_cursor);
} }
} }
} }
@ -939,97 +869,125 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SEPROP_TRIGGERED_THIS_TICK)) continue;
if ((world->sim_time_ns - ent->last_triggered_ns < NS_FROM_SECONDS(ent->trigger_delay)) && ent->last_triggered_ns != 0) continue;
ent->last_triggered_ns = world->sim_time_ns; b32 primary_triggered = ent->num_primary_triggers > 0;
b32 secondary_triggered = ent->num_secondary_triggers > 0;
ent->num_primary_triggers = 0;
ent->num_secondary_triggers = 0;
if (primary_triggered) {
i64 world_time_ns = world->sim_time_ns;
if ((world_time_ns - ent->last_primary_fire_ns >= NS_FROM_SECONDS(ent->primary_fire_delay)) || ent->last_primary_fire_ns == 0) {
ent->last_primary_fire_ns = world_time_ns;
} else {
primary_triggered = false;
}
}
if (secondary_triggered) {
i64 world_time_ns = world->sim_time_ns;
if ((world_time_ns - ent->last_secondary_fire_ns >= NS_FROM_SECONDS(ent->secondary_fire_delay)) || ent->last_secondary_fire_ns == 0) {
ent->last_secondary_fire_ns = world_time_ns;
} else {
secondary_triggered = false;
}
}
/* Fire smg */ /* Fire smg */
if (sim_ent_has_prop(ent, SEPROP_WEAPON_SMG)) { if (sim_ent_has_prop(ent, SEPROP_WEAPON_SMG)) {
struct sprite_tag sprite = ent->sprite; if (primary_triggered) {
u32 animation_frame = ent->animation_frame; struct sprite_tag sprite = ent->sprite;
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite); u32 animation_frame = ent->animation_frame;
struct xform sprite_local_xform = ent->sprite_local_xform; struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame); struct xform sprite_local_xform = ent->sprite_local_xform;
struct v2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center); struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
struct v2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir); struct v2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
struct v2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
/* Spawn bullet */ /* Spawn bullet */
struct sim_ent *bullet; struct sim_ent *bullet;
{ {
bullet = sim_ent_alloc_sync_src(root); bullet = sim_ent_alloc_sync_src(root);
sim_ent_enable_prop(bullet, SEPROP_BULLET); sim_ent_enable_prop(bullet, SEPROP_BULLET);
bullet->bullet_src = ent->id; bullet->bullet_src = ent->id;
bullet->bullet_src_pos = rel_pos; bullet->bullet_src_pos = rel_pos;
bullet->bullet_src_dir = rel_dir; bullet->bullet_src_dir = rel_dir;
//bullet->bullet_launch_velocity = 0.75f; //bullet->bullet_launch_velocity = 0.75f;
bullet->bullet_launch_velocity = 50.0f; bullet->bullet_launch_velocity = 50.0f;
bullet->bullet_knockback = 10; bullet->bullet_knockback = 10;
bullet->layer = SIM_LAYER_BULLETS; bullet->layer = SIM_LAYER_BULLETS;
#if 1 #if 1
/* Point collider */ /* Point collider */
bullet->local_collider.points[0] = V2(0, 0); bullet->local_collider.points[0] = V2(0, 0);
bullet->local_collider.count = 1; bullet->local_collider.count = 1;
#else #else
bullet->sprite = sprite_tag_from_path(LIT("res/graphics/bullet.ase")); bullet->sprite = sprite_tag_from_path(LIT("res/graphics/bullet.ase"));
bullet->sprite_collider_slice = LIT("shape"); bullet->sprite_collider_slice = LIT("shape");
#endif #endif
} }
/* Spawn tracer */ /* Spawn tracer */
{ {
struct sim_ent *tracer = sim_ent_alloc_sync_src(root); struct sim_ent *tracer = sim_ent_alloc_sync_src(root);
tracer->tracer_fade_duration = 0.025f; tracer->tracer_fade_duration = 0.025f;
tracer->layer = SIM_LAYER_TRACERS; tracer->layer = SIM_LAYER_TRACERS;
sim_ent_enable_prop(tracer, SEPROP_TRACER); sim_ent_enable_prop(tracer, SEPROP_TRACER);
bullet->bullet_tracer = tracer->id; bullet->bullet_tracer = tracer->id;
}
} }
} }
/* Fire launcher */ /* Fire launcher */
if (sim_ent_has_prop(ent, SEPROP_WEAPON_LAUNCHER)) { if (sim_ent_has_prop(ent, SEPROP_WEAPON_LAUNCHER)) {
struct sprite_tag sprite = ent->sprite; if (primary_triggered) {
u32 animation_frame = ent->animation_frame; struct sprite_tag sprite = ent->sprite;
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite); u32 animation_frame = ent->animation_frame;
struct xform sprite_local_xform = ent->sprite_local_xform; struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame); struct xform sprite_local_xform = ent->sprite_local_xform;
struct v2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center); struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
struct v2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir); struct v2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
struct v2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
/* Spawn bullet */ /* Spawn bullet */
struct sim_ent *bullet; struct sim_ent *bullet;
{ {
bullet = sim_ent_alloc_sync_src(root); bullet = sim_ent_alloc_sync_src(root);
sim_ent_enable_prop(bullet, SEPROP_BULLET); sim_ent_enable_prop(bullet, SEPROP_BULLET);
bullet->bullet_src = ent->id; bullet->bullet_src = ent->id;
bullet->bullet_src_pos = rel_pos; bullet->bullet_src_pos = rel_pos;
bullet->bullet_src_dir = rel_dir; bullet->bullet_src_dir = rel_dir;
//bullet->bullet_launch_velocity = 0.75f; //bullet->bullet_launch_velocity = 0.75f;
bullet->bullet_launch_velocity = 15; bullet->bullet_launch_velocity = 15;
bullet->bullet_knockback = 50; bullet->bullet_knockback = 50;
bullet->bullet_explosion_strength = 100; bullet->bullet_explosion_strength = 100;
bullet->bullet_explosion_radius = 4; bullet->bullet_explosion_radius = 4;
bullet->layer = SIM_LAYER_BULLETS; bullet->layer = SIM_LAYER_BULLETS;
/* Point collider */ /* Point collider */
bullet->local_collider.points[0] = V2(0, 0); bullet->local_collider.points[0] = V2(0, 0);
bullet->local_collider.count = 1; bullet->local_collider.count = 1;
bullet->local_collider.radius = 0.05; bullet->local_collider.radius = 0.05;
}
/* Spawn tracer */
{
struct sim_ent *tracer = sim_ent_alloc_sync_src(root);
tracer->tracer_fade_duration = 0.025f;
tracer->layer = SIM_LAYER_TRACERS;
sim_ent_enable_prop(tracer, SEPROP_TRACER);
bullet->bullet_tracer = tracer->id;
}
} }
}
/* Spawn tracer */ /* Fire chucker */
{ if (sim_ent_has_prop(ent, SEPROP_WEAPON_CHUCKER)) {
struct sim_ent *tracer = sim_ent_alloc_sync_src(root); if (primary_triggered) {
tracer->tracer_fade_duration = 0.025f;
tracer->layer = SIM_LAYER_TRACERS;
sim_ent_enable_prop(tracer, SEPROP_TRACER);
bullet->bullet_tracer = tracer->id;
} }
} }
} }

View File

@ -1591,6 +1591,7 @@ INTERNAL void user_update(void)
control.dbg_cursor = G.world_cursor; control.dbg_cursor = G.world_cursor;
struct bind_state fire_state = G.bind_states[USER_BIND_KIND_FIRE]; struct bind_state fire_state = G.bind_states[USER_BIND_KIND_FIRE];
struct bind_state fire_alt_state = G.bind_states[USER_BIND_KIND_FIRE_ALT];
struct bind_state drag_state = G.bind_states[USER_BIND_KIND_DEBUG_DRAG]; struct bind_state drag_state = G.bind_states[USER_BIND_KIND_DEBUG_DRAG];
struct bind_state clear_state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR]; struct bind_state clear_state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
struct bind_state spawn1_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN1]; struct bind_state spawn1_state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN1];
@ -1604,6 +1605,9 @@ INTERNAL void user_update(void)
if (fire_state.num_presses || fire_state.is_held) { if (fire_state.num_presses || fire_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_FIRE; control.flags |= SIM_CONTROL_FLAG_FIRE;
} }
if (fire_alt_state.num_presses || fire_alt_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_FIRE_ALT;
}
if (drag_state.num_presses || drag_state.is_held) { if (drag_state.num_presses || drag_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_DRAG; control.flags |= SIM_CONTROL_FLAG_DRAG;
} }

View File

@ -23,6 +23,7 @@ enum user_bind_kind {
USER_BIND_KIND_MOVE_RIGHT, USER_BIND_KIND_MOVE_RIGHT,
USER_BIND_KIND_WALK, USER_BIND_KIND_WALK,
USER_BIND_KIND_FIRE, USER_BIND_KIND_FIRE,
USER_BIND_KIND_FIRE_ALT,
/* Testing */ /* Testing */