Improved spider web AI (#76637)

## About The Pull Request

The AI I coded for spiders deciding where to make webs when they aren't
otherwise occupied would do so by finding the _closest_ valid tile,
which seemed like a good idea at the time. The problem with that is that
the "closest" algorithm we use has a predictable search pattern which
meant that spiders would always predictably make a diagonal line of webs
pointing South West, which looked very silly.
I've rewritten how they pick targets to introduce some randomness, which
causes them to properly spread out and make a nicer-looking structure:
which serves purely to annoy spacemen who need to pass through this
area.


![image](https://github.com/tgstation/tgstation/assets/7483112/cb01828f-7653-4010-a4f5-2abc6e10b630)

I'll be honest I mostly did this while bored waiting for other PRs which
I require for my other branch to get merged.

## Why It's Good For The Game

This probably only annoyed me to be quite honest and if you left one
alone for long enough it would fill enough space that you couldn't tell
anyway, but it does look nicer now.

## Changelog

🆑
add: AI-controlled spiders will make more web-shaped webs.
/🆑
This commit is contained in:
Jacquerel
2023-07-10 10:14:13 +01:00
committed by GitHub
parent 8bcd385905
commit e80cf8f358
3 changed files with 22 additions and 6 deletions
@@ -27,22 +27,31 @@
finish_action(controller, succeeded = TRUE)
return
var/list/potential_turfs = list()
for(var/turf/turf_in_view in oview(scan_range, our_turf))
var/list/turfs_by_range = list()
for (var/i in 1 to scan_range)
turfs_by_range["[i]"] = list()
for (var/turf/turf_in_view in oview(scan_range, our_turf))
if (!is_valid_web_turf(turf_in_view))
continue
potential_turfs += turf_in_view
turfs_by_range["[get_dist(our_turf, turf_in_view)]"] += turf_in_view
if (!length(potential_turfs))
var/list/final_turfs
for (var/list/turf_list as anything in turfs_by_range)
if (length(turfs_by_range[turf_list]))
final_turfs = turfs_by_range[turf_list]
break
if (!length(final_turfs))
finish_action(controller, succeeded = FALSE)
return
controller.set_blackboard_key(target_key, get_closest_atom(/turf/, potential_turfs, our_turf))
controller.set_blackboard_key(target_key, pick(final_turfs))
finish_action(controller, succeeded = TRUE)
/datum/ai_behavior/find_unwebbed_turf/proc/is_valid_web_turf(turf/target_turf, mob/living/spider)
if (locate(/obj/structure/spider/stickyweb) in target_turf)
return FALSE
if (HAS_TRAIT(target_turf, TRAIT_SPINNING_WEB_TURF))
return FALSE
return !target_turf.is_blocked_turf(source_atom = spider)
/// Run the spin web behaviour if we have an ability to use for it
@@ -34,6 +34,10 @@
if (feedback)
owner.balloon_alert(owner, "invalid location!")
return FALSE
if(HAS_TRAIT(owner.loc, TRAIT_SPINNING_WEB_TURF))
if (feedback)
owner.balloon_alert(owner, "already being webbed!")
return FALSE
if(obstructed_by_other_web())
if (feedback)
owner.balloon_alert(owner, "already webbed!")
@@ -52,11 +56,12 @@
owner.balloon_alert_to_viewers("sealing web...")
else
owner.balloon_alert_to_viewers("spinning web...")
ADD_TRAIT(spider_turf, TRAIT_SPINNING_WEB_TURF, REF(src))
if(do_after(owner, webbing_time, target = spider_turf, interaction_key = DOAFTER_SOURCE_SPIDER) && owner.loc == spider_turf)
plant_web(spider_turf, web)
else
owner?.balloon_alert(owner, "interrupted!") // Null check because we might have been interrupted via being disintegrated
REMOVE_TRAIT(spider_turf, TRAIT_SPINNING_WEB_TURF, REF(src))
build_all_button_icons()
/// Creates a web in the current turf