obj/proc/TowerAI()
spawn(src.delay) src.TowerAI()
for(var/obj/Enemy/E in oview(src.range))
var/obj/Bullet/B = new(src.loc)
B.Move(locate(src.loc))
B.dmg = src.damage
B.icon_state = "[src.icon_state]"
walk(B,get_dir(src,E))
Problem description:
The enemies come right within their range(5) and they sit there inactive. Why?
Maybe moving B to locate(src.loc) isn't good, because:
loc is the location of src.
locate() is returning the location of the location of src.
src's location is most likely a turf, and you're getting the area of which the turf is located.
Try B.loc=src.loc instead.
Also, for infinite loops I prefer using spawn while(1). But it doesn't matter.