+ botframe_autowaypoints_createwp(trace_endpos, p, fld, WAYPOINTFLAG_PROTECTED);
+}
+
+void botframe_deleteuselesswaypoints()
+{
+ entity w, w1, w2;
+ float i, j, k;
+ for (w = world; (w = findfloat(w, bot_pickup, true)); )
+ {
+ // NOTE: this protects waypoints if they're the ONLY nearest
+ // waypoint. That's the intention.
+ navigation_findnearestwaypoint(w, false); // Walk TO item.
+ navigation_findnearestwaypoint(w, true); // Walk FROM item.
+ }
+ for (w = world; (w = find(w, classname, "waypoint")); )
+ {
+ w.wpflags |= WAYPOINTFLAG_DEAD_END;
+ w.wpflags &= ~WAYPOINTFLAG_USEFUL;
+ // WP is useful if:
+ if (w.wpflags & WAYPOINTFLAG_ITEM)
+ w.wpflags |= WAYPOINTFLAG_USEFUL;
+ if (w.wpflags & WAYPOINTFLAG_TELEPORT)
+ w.wpflags |= WAYPOINTFLAG_USEFUL;
+ if (w.wpflags & WAYPOINTFLAG_PROTECTED)
+ w.wpflags |= WAYPOINTFLAG_USEFUL;
+ // b) WP is closest WP for an item/spawnpoint/other entity
+ // This has been done above by protecting these WPs.
+ }
+ // c) There are w1, w, w2 so that w1 -> w, w -> w2 and not w1 -> w2.
+ for (w1 = world; (w1 = find(w1, classname, "waypoint")); )
+ {
+ if (w1.wpflags & WAYPOINTFLAG_PERSONAL)
+ continue;
+ for (i = 0; i < 32; ++i)
+ {
+ w = waypoint_get_link(w1, i);
+ if (!w)
+ break;
+ if (w.wpflags & WAYPOINTFLAG_PERSONAL)
+ continue;
+ if (w.wpflags & WAYPOINTFLAG_USEFUL)
+ continue;
+ for (j = 0; j < 32; ++j)
+ {
+ w2 = waypoint_get_link(w, j);
+ if (!w2)
+ break;
+ if (w1 == w2)
+ continue;
+ if (w2.wpflags & WAYPOINTFLAG_PERSONAL)
+ continue;
+ // If we got here, w1 != w2 exist with w1 -> w
+ // and w -> w2. That means the waypoint is not
+ // a dead end.
+ w.wpflags &= ~WAYPOINTFLAG_DEAD_END;
+ for (k = 0; k < 32; ++k)
+ {
+ if (waypoint_get_link(w1, k) == w2)
+ continue;
+ // IF WE GET HERE, w is proven useful
+ // to get from w1 to w2!
+ w.wpflags |= WAYPOINTFLAG_USEFUL;
+ goto next;
+ }
+ }
+:next
+ }
+ }
+ // d) The waypoint is a dead end. Dead end waypoints must be kept as
+ // they are needed to complete routes while autowaypointing.
+
+ for (w = world; (w = find(w, classname, "waypoint")); )
+ {
+ if (!(w.wpflags & (WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END)))
+ {
+ printf("Removed a waypoint at %v. Try again for more!\n", w.origin);
+ te_explosion(w.origin);
+ waypoint_remove(w);
+ break;
+ }
+ }
+ for (w = world; (w = find(w, classname, "waypoint")); )
+ w.wpflags &= ~(WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END); // temp flag