mirror of
https://github.com/nzp-team/quakec.git
synced 2025-04-22 09:40:54 +00:00
Adds nav_trav_auto_adjust
command
This command adjust a ledge traversal so its points are well-positioned. Adjusts short ledge climb traversal execution code.
This commit is contained in:
parent
5e8cd1e655
commit
69696eb0e3
3 changed files with 147 additions and 46 deletions
|
@ -235,12 +235,10 @@ void cl_navmesh_draw_poly(float poly_index) {
|
|||
face_color = [0.8,0.2,0.2];
|
||||
}
|
||||
|
||||
if(cl_navmesh_polies[poly_index].vert_count == 3)
|
||||
{
|
||||
if(cl_navmesh_polies[poly_index].vert_count == 3) {
|
||||
cl_navmesh_draw_tri(a,b,c,face_color,face_alpha,TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
vector d = cl_navmesh_verts[cl_navmesh_polies[poly_index].verts[3]].pos;
|
||||
cl_navmesh_draw_quad(a,b,c,d,face_color,face_alpha,TRUE);
|
||||
}
|
||||
|
@ -451,8 +449,7 @@ void cl_navmesh_editor_draw() {
|
|||
|
||||
|
||||
//The following code block is for detecting and placing waypoints at bsp map corners
|
||||
if(cl_navmesh_place_corner_state == NAVMESH_PLACE_CORNER_PLACING || cl_navmesh_place_corner_state == NAVMESH_PLACE_CORNER_CONFIRM)
|
||||
{
|
||||
if(cl_navmesh_place_corner_state == NAVMESH_PLACE_CORNER_PLACING || cl_navmesh_place_corner_state == NAVMESH_PLACE_CORNER_CONFIRM) {
|
||||
|
||||
//vector vorg = getentity(player_localentnum, GE_ORIGIN);
|
||||
//vector vorg = getviewprop(VF_ORIGIN) - VEC_VIEW_OFS;
|
||||
|
@ -2906,10 +2903,7 @@ void cl_navmesh_pathfind_draw_result_point_path() {
|
|||
}
|
||||
}
|
||||
|
||||
void cl_toggle_navmesh_editor()
|
||||
{
|
||||
|
||||
|
||||
void cl_toggle_navmesh_editor() {
|
||||
if(cvar("navmesh_edit_mode")) {
|
||||
cvar_set("navmesh_edit_mode", "0");
|
||||
print("cl_navmesh editor: 0\n");
|
||||
|
@ -2936,7 +2930,6 @@ void cl_toggle_navmesh_editor()
|
|||
cl_pathfind_clear_result_data();
|
||||
}
|
||||
|
||||
|
||||
cl_navmesh_deselect_all();
|
||||
cl_navmesh_selected_traversal = -1;
|
||||
cl_navmesh_traversal_edit_mode = false;
|
||||
|
@ -2945,8 +2938,7 @@ void cl_toggle_navmesh_editor()
|
|||
}
|
||||
|
||||
|
||||
void cl_register_navmesh_commands() =
|
||||
{
|
||||
void cl_register_navmesh_commands() {
|
||||
registercommand("nav_editor");
|
||||
registercommand("nav_place_vert");
|
||||
registercommand("nav_delete_verts");
|
||||
|
@ -2987,7 +2979,7 @@ void cl_register_navmesh_commands() =
|
|||
registercommand("nav_trav_set_point_pos");
|
||||
registercommand("nav_trav_get_angle");
|
||||
registercommand("nav_trav_set_angle");
|
||||
|
||||
registercommand("nav_trav_auto_adjust");
|
||||
}
|
||||
|
||||
float cl_confirm_clear_navmesh;
|
||||
|
@ -3087,15 +3079,18 @@ float cl_navmesh_get_nearest_traversal() {
|
|||
vector player_pos = getentity(player_localentnum, GE_ORIGIN);
|
||||
float closest_dist = vlen(player_pos - cl_navmesh_traversals[0].start_pos);
|
||||
float closest_index = 0;
|
||||
|
||||
float temp_dist;
|
||||
|
||||
for(float i = 1; i < cl_navmesh_traversal_count; i++)
|
||||
{
|
||||
for(float i = 1; i < cl_navmesh_traversal_count; i++) {
|
||||
// Check traversal start position
|
||||
temp_dist = vlen(player_pos - cl_navmesh_traversals[i].start_pos);
|
||||
|
||||
if(temp_dist < closest_dist)
|
||||
{
|
||||
if(temp_dist < closest_dist) {
|
||||
closest_dist = temp_dist;
|
||||
closest_index = i;
|
||||
}
|
||||
// Also check traversal end position
|
||||
temp_dist = vlen(player_pos - cl_navmesh_get_traversal_end_pos(i));
|
||||
if(temp_dist < closest_dist) {
|
||||
closest_dist = temp_dist;
|
||||
closest_index = i;
|
||||
}
|
||||
|
@ -3330,13 +3325,123 @@ void cl_navmesh_traversal_editor_set_angle(float angle) {
|
|||
print(".\n");
|
||||
};
|
||||
|
||||
void cl_navmesh_traversal_editor_auto_adjust_traversal() {
|
||||
if(cl_navmesh_selected_traversal == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
vector start_pos = cl_navmesh_traversals[cl_navmesh_selected_traversal].start_pos;
|
||||
vector midpoint_pos = cl_navmesh_get_traversal_midpoint_pos(cl_navmesh_selected_traversal);
|
||||
vector end_pos = cl_navmesh_get_traversal_end_pos(cl_navmesh_selected_traversal);
|
||||
|
||||
vector ofs = '0 0 16';
|
||||
tracebox(start_pos + ofs, VEC_HULL_MIN, VEC_HULL_MAX, start_pos - ofs, TRUE, player);
|
||||
cl_navmesh_traversals[cl_navmesh_selected_traversal].start_pos.z = trace_endpos.z;
|
||||
tracebox(end_pos + ofs, VEC_HULL_MIN, VEC_HULL_MAX, end_pos - ofs, TRUE, player);
|
||||
cl_navmesh_traversals[cl_navmesh_selected_traversal].end_pos.z = trace_endpos.z - start_pos.z;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// FIXME - Pull from traversal struct
|
||||
string traversal_type = "ledge";
|
||||
|
||||
|
||||
// If "ledge" traversal,
|
||||
if(traversal_type == "ledge") {
|
||||
start_pos = cl_navmesh_traversals[cl_navmesh_selected_traversal].start_pos;
|
||||
end_pos = cl_navmesh_get_traversal_end_pos(cl_navmesh_selected_traversal);
|
||||
|
||||
vector top_point;
|
||||
vector bottom_point;
|
||||
|
||||
if(start_pos.z < end_pos.z) {
|
||||
bottom_point = start_pos;
|
||||
top_point = end_pos;
|
||||
}
|
||||
else {
|
||||
top_point = start_pos;
|
||||
bottom_point = end_pos;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Binary search to find the ledge location
|
||||
// --------------------------------------------------------------------
|
||||
vector search_start = top_point;
|
||||
vector search_midpoint;
|
||||
vector search_end = bottom_point;
|
||||
search_end.z = search_start.z;
|
||||
// What if there's a wall above the bottom point?
|
||||
|
||||
for(float i = 0; i < 6; i++) {
|
||||
search_midpoint = (search_start + search_end) * 0.5;
|
||||
tracebox(search_midpoint + ofs, VEC_HULL_MIN, VEC_HULL_MAX, search_midpoint - ofs, TRUE, player);
|
||||
print("--------------------------------\n");
|
||||
print("iter: ", ftos(i), " start: ", vtos(search_start), " end: ", vtos(search_end), " mid: ");
|
||||
print(vtos(search_midpoint), " frac: ", ftos(trace_fraction), "\n");
|
||||
if(trace_fraction >= 1.0 || trace_startsolid) {
|
||||
search_end = search_midpoint;
|
||||
}
|
||||
else {
|
||||
search_start = search_midpoint;
|
||||
}
|
||||
}
|
||||
vector ledge_pos = (search_start + search_end) * 0.5;
|
||||
// ledge_pos is the center of the bbox, offset to find the corner near the ledge
|
||||
// https://stackoverflow.com/a/1343531
|
||||
// float angle = vectoangles(search_end - search_stard).y;
|
||||
// float abs_cos_angle = fabs(cos(angle));
|
||||
// float abs_sin_angle = fabs(sin(angle));
|
||||
// float bbox_width = (VEC_HULL_MAX.x - VEC_HULL_MIN.x) / 2;
|
||||
// float bbox_depth = (VEC_HULL_MAX.y - VEC_HULL_MIN.y) / 2;
|
||||
// float ofs_dist;
|
||||
// if(bbox_width * abs_sin_angle <= bbox_depth * abs_cos_angle) {
|
||||
// ofs_dist = bbox_width / abs_cos_angle;
|
||||
// }
|
||||
// else {
|
||||
// ofs_dist = bbox_depth / abs_sin_angle;
|
||||
// }
|
||||
// ledge_pos += normalize(top_point - [bottom_point.x, bottom_point.y, top_point.z]) * ofs_dist;
|
||||
// Push 16 qu towards the top point
|
||||
// NOTE: This won't be accurate for sloped ledges, but we're just
|
||||
// trying to get close-enough so the animations look half-decent
|
||||
ledge_pos += normalize(top_point - [bottom_point.x, bottom_point.y, top_point.z]) * 16;
|
||||
// Lower by the bbox height to the center
|
||||
ledge_pos.z += VEC_HULL_MIN.z;
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Offset the traversal such that the top point is 10qu away from the ledge
|
||||
// --------------------------------------------------------------------
|
||||
float traversal_length = 50; // qu
|
||||
float start_to_ledge = 10; // qu
|
||||
// First, make sure the end_pos is exactly 50qu away from the start
|
||||
cl_navmesh_traversals[cl_navmesh_selected_traversal].end_pos.x = 0;
|
||||
cl_navmesh_traversals[cl_navmesh_selected_traversal].end_pos.y = traversal_length;
|
||||
|
||||
// Compute vector pointing from start towards ledge:
|
||||
vector delta_pos = start_pos - ledge_pos;
|
||||
delta_pos.z = 0;
|
||||
float cur_dist = vlen(delta_pos);
|
||||
delta_pos = normalize(delta_pos);
|
||||
|
||||
// If traversal start is at the bottom, move traversal start 40qu away from ledge
|
||||
if(start_pos.z < end_pos.z) {
|
||||
cl_navmesh_traversals[cl_navmesh_selected_traversal].start_pos += delta_pos * ((traversal_length - start_to_ledge) - cur_dist);
|
||||
}
|
||||
// If traversal start is at the top, move traversal start 10qu away from ledge
|
||||
else {
|
||||
cl_navmesh_traversals[cl_navmesh_selected_traversal].start_pos += delta_pos * (start_to_ledge - cur_dist);
|
||||
}
|
||||
|
||||
// Next, adjust distance between the traversal start and the ledge
|
||||
// so that it's exactly 25 qu away.
|
||||
// --------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -3481,6 +3586,9 @@ float(string cmd) cl_navmesh_console_commands =
|
|||
case "nav_trav_set_angle":
|
||||
cl_navmesh_traversal_editor_set_angle(stof(argv(1)));
|
||||
return TRUE;
|
||||
case "nav_trav_auto_adjust":
|
||||
cl_navmesh_traversal_editor_auto_adjust_traversal();
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -153,7 +153,16 @@ void (float move_speed) AI_Chase::do_walk_to_goal = {
|
|||
|
||||
|
||||
this.ideal_yaw = vectoyaw(goal_pos - this.origin);
|
||||
ChangeYaw();
|
||||
|
||||
// ChangeYaw();
|
||||
// Apply smallest delta angle
|
||||
float delta_angle = this.ideal_yaw - this.angles.y;
|
||||
delta_angle = ((delta_angle + 180) % 360) - 180;
|
||||
this.angles.y += 0.3 * delta_angle;
|
||||
|
||||
|
||||
|
||||
|
||||
vector new_velocity;
|
||||
float walk_dist = move_speed * this.cur_anim_frametime;
|
||||
float dist_to_goal = vlen(goal_pos - this.origin);
|
||||
|
@ -329,8 +338,7 @@ void zombie_traversal_logic() {
|
|||
|
||||
|
||||
string traversal_type;
|
||||
traversal_type = "jump_up";
|
||||
// traversal_type = "jump_down";
|
||||
traversal_type = "ledge";
|
||||
// traversal_type = "jump_gap";
|
||||
// traversal_type = "hop_barricade";
|
||||
// traversal_type = "hop_fence";
|
||||
|
@ -338,25 +346,13 @@ void zombie_traversal_logic() {
|
|||
// traversal_type = "teleport";
|
||||
|
||||
// Jump up logic
|
||||
if(traversal_type == "jump_up") {
|
||||
// zombie_ent.angles.y = sv_navmesh_traversals[traversal_idx].angle;
|
||||
float delta_angle = sv_navmesh_traversals[traversal_idx].angle - zombie_ent.angles.y;
|
||||
if(traversal_type == "ledge") {
|
||||
// Adjust zombie angle to its smallest representation
|
||||
zombie_ent.angles.y = ((zombie_ent.angles.y + 180) % 360) - 180;
|
||||
// Apply smallest delta angle
|
||||
float delta_angle = sv_navmesh_traversals[traversal_idx].angle - zombie_ent.angles.y;
|
||||
delta_angle = ((delta_angle + 180) % 360) - 180;
|
||||
// zombie_ent.angles.y = sv_navmesh_traversals[traversal_idx].angle;
|
||||
float delta_angle = sv_navmesh_traversals[traversal_idx].angle - zombie_ent.angles.y;
|
||||
|
||||
// FIXME - Replace this with mods....
|
||||
// delta_angle = (((delta_angle - 180) % 180) + 180) % 180;
|
||||
// ((delta_angle - 180) % 360) + 180
|
||||
while(delta_angle < -180) {
|
||||
delta_angle += 360;
|
||||
}
|
||||
while(delta_angle > 180) {
|
||||
delta_angle -= 360;
|
||||
}
|
||||
|
||||
zombie_ent.angles.y += 0.5 * delta_angle; zombie_ent.angles.y += 0.5 * delta_angle;
|
||||
zombie_ent.angles.y += 0.5 * delta_angle;
|
||||
|
||||
// Jump up traversal consists of the following substates:
|
||||
// 0: Start traversal, play jump up anim
|
||||
|
@ -394,13 +390,10 @@ void zombie_traversal_logic() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Short ledge
|
||||
else if(traversal_height < 98) {
|
||||
if(zombie_ent.substate == 0) {
|
||||
zombie_ent.movetype = MOVETYPE_STEP;
|
||||
|
||||
// If short jump up, play short jump / short climb anim
|
||||
zombie_ent.play_anim(get_anim_frame_zombie_jump_low, get_anim_length_zombie_jump_low(), ANIM_STOP_TYPE_STOP);
|
||||
// zombie_ent.cur_anim_frametime = 0.08;
|
||||
|
@ -416,7 +409,7 @@ void zombie_traversal_logic() {
|
|||
if(zombie_ent.substate == 1) {
|
||||
lerp_frac = (time - zombie_ent.cur_traversal_start_time) / (zombie_ent.cur_traversal_end_time - zombie_ent.cur_traversal_start_time);
|
||||
makevectors([0, sv_navmesh_traversals[traversal_idx].angle, 0]);
|
||||
goal_pos = end_pos - '0 0 77' - v_forward * 21;
|
||||
goal_pos = end_pos - '0 0 72' - v_forward * 21;
|
||||
zombie_ent.origin = lerpVector(start_pos, goal_pos, lerp_frac);
|
||||
|
||||
if(lerp_frac >= 1) {
|
||||
|
@ -430,7 +423,7 @@ void zombie_traversal_logic() {
|
|||
}
|
||||
else if(zombie_ent.substate == 2) {
|
||||
lerp_frac = (time - zombie_ent.cur_traversal_start_time) / (zombie_ent.cur_traversal_end_time - zombie_ent.cur_traversal_start_time);
|
||||
start_pos = end_pos - '0 0 77' - v_forward * 21;
|
||||
start_pos = end_pos - '0 0 72' - v_forward * 21;
|
||||
zombie_ent.origin = lerpVector(start_pos, end_pos, lerp_frac);
|
||||
if(lerp_frac >= 1.0) {
|
||||
zombie_ent.state = AI_STATE_PATHING;
|
||||
|
|
|
@ -591,7 +591,7 @@ class AI_Chase : entity {
|
|||
this.frame = anim_frame_func(0);
|
||||
};
|
||||
|
||||
// Queue up another animation to play when the current one finishes
|
||||
// Queue up another animation to play when the current one finishes.
|
||||
virtual void(float(float) anim_frame_func, float anim_length, anim_stop_type stop_type) queue_anim {
|
||||
// This isn't allowed, we can't queue more than one animation.
|
||||
// Queued animation stop type must be: ANIM_STOP_TYPE_STOP, or ANIM_STOP_TYPE_LOOP
|
||||
|
|
Loading…
Reference in a new issue