+// Check for water/slime/lava and dangerous edges
+// (only when the bot is on the ground or jumping intentionally)
+// returns a number > 0 for danger
+int havocbot_checkdanger(entity this, vector dst_ahead)
+{
+ vector dst_down = dst_ahead - '0 0 3000';
+ traceline(this.origin + this.view_ofs, dst_ahead, true, NULL);
+
+ float s = CONTENT_SOLID;
+ if (trace_fraction == 1 && !this.jumppadcount
+ && !waypoint_is_hardwiredlink(this.goalcurrent_prev, this.goalcurrent)
+ && !(this.goalcurrent_prev && (this.goalcurrent_prev.wpflags & WAYPOINTFLAG_JUMP)))
+ if ((IS_ONGROUND(this)) || (this.aistatus & AI_STATUS_RUNNING) || (this.aistatus & AI_STATUS_ROAMING) || PHYS_INPUT_BUTTON_JUMP(this))
+ {
+ // Look downwards
+ traceline(dst_ahead , dst_down, true, NULL);
+ //te_lightning2(NULL, this.origin + this.view_ofs, dst_ahead); // Draw "ahead" look
+ //te_lightning2(NULL, dst_ahead, trace_endpos); // Draw "downwards" look
+ if (trace_endpos.z < this.origin.z + this.mins.z)
+ {
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ return 1;
+ else if (trace_endpos.z < min(this.origin.z + this.mins.z, this.goalcurrent.origin.z) - 100)
+ return 2;
+ else
+ {
+ s = pointcontents(trace_endpos + '0 0 1');
+ if (s != CONTENT_SOLID)
+ {
+ if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+ return 3;
+ else if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+ {
+ // the traceline check isn't enough but is good as optimization,
+ // when not true (most of the time) this tracebox call is avoided
+ tracebox(dst_ahead, this.mins, this.maxs, dst_down, true, this);
+ if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
+ {
+ return 4;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+