Files
fulpstation/code/game/gamemodes/blob/theblob.dm
MrPerson 471d69fcf7 Change many ERROR() calls into thrown exceptions
This requires a 508 beta version to use. If Travis fails this he's a bitch

Exceptions will generate a stack trace, which is way easier to see and more helpful in actually solving this kind of crap. Also logs all the arguments, src, line, and file automatically.
Removed any dubiously helpful information in the exception names so the runtime condenser won't see each one as a different runtime. If the information is critical to solve these bugs (camera one maybe?), then I'll just make these warnings.
Thrown exceptions crash the currently running proc. Yes that means there's useless returns in a bunch of these, sue me. spawn()'s are to let the proc continue.

Almost all of these are difficult to trigger, but I did test playsound. And frankly even if they do cause bugs by crashing procs, big whoop
2015-07-23 08:19:08 -07:00

237 lines
6.2 KiB
Plaintext

//I will need to recode parts of this but I am way too tired atm
/obj/effect/blob
name = "blob"
icon = 'icons/mob/blob.dmi'
luminosity = 3
desc = "Some blob creature thingy"
density = 0
opacity = 0
anchored = 1
var/health = 30
var/health_timestamp = 0
var/brute_resist = 4
var/fire_resist = 1
/obj/effect/blob/New(loc)
blobs += src
src.dir = pick(1, 2, 4, 8)
src.update_icon()
..(loc)
for(var/atom/A in loc)
A.blob_act()
return
/obj/effect/blob/Destroy()
blobs -= src
if(isturf(loc)) //Necessary because Expand() is retarded and spawns a blob and then deletes it
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
..()
/obj/effect/blob/CanPass(atom/movable/mover, turf/target, height=0)
if(height==0) return 1
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
return 0
/obj/effect/blob/process()
Life()
return
/obj/effect/blob/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
var/damage = Clamp(0.01 * exposed_temperature, 0, 4)
take_damage(damage, BURN)
/obj/effect/blob/proc/Life()
return
/obj/effect/blob/proc/PulseAnimation()
if(!istype(src, /obj/effect/blob/core) || !istype(src, /obj/effect/blob/node))
flick("[icon_state]_glow", src)
return
/obj/effect/blob/proc/RegenHealth()
// All blobs heal over time when pulsed, but it has a cool down
if(health_timestamp > world.time)
return 0
if(health < initial(health))
health++
update_icon()
health_timestamp = world.time + 10 // 1 seconds
/obj/effect/blob/proc/Pulse(pulse = 0, origin_dir = 0, a_color)//Todo: Fix spaceblob expand
set background = BACKGROUND_ENABLED
PulseAnimation()
RegenHealth()
if(run_action())//If we can do something here then we dont need to pulse more
return
if(pulse > 30)
return//Inf loop check
//Looking for another blob to pulse
var/list/dirs = list(1,2,4,8)
dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us
for(var/i = 1 to 4)
if(!dirs.len) break
var/dirn = pick(dirs)
dirs.Remove(dirn)
var/turf/T = get_step(src, dirn)
var/obj/effect/blob/B = (locate(/obj/effect/blob) in T)
if(!B)
expand(T,1,a_color)//No blob here so try and expand
return
B.adjustcolors(a_color)
B.Pulse((pulse+1),get_dir(src.loc,T), a_color)
return
return
/obj/effect/blob/proc/run_action()
return 0
/obj/effect/blob/proc/expand(turf/T = null, prob = 1, a_color)
if(prob && !prob(health)) return
if(istype(T, /turf/space) && prob(75)) return
if(!T)
var/list/dirs = list(1,2,4,8)
for(var/i = 1 to 4)
var/dirn = pick(dirs)
dirs.Remove(dirn)
T = get_step(src, dirn)
if(!(locate(/obj/effect/blob) in T)) break
else T = null
if(!T) return 0
var/obj/effect/blob/normal/B = new /obj/effect/blob/normal(src.loc, min(src.health, 30))
B.color = a_color
B.density = 1
if(T.Enter(B,src))//Attempt to move into the tile
B.density = initial(B.density)
B.loc = T
else
T.blob_act()//If we cant move in hit the turf
B.loc = null //So we don't play the splat sound, see Destroy()
qdel(B)
for(var/atom/A in T)//Hit everything in the turf
A.blob_act()
return 1
/obj/effect/blob/ex_act(severity, target)
..()
var/damage = 150 - 20 * severity
take_damage(damage, BRUTE)
/obj/effect/blob/bullet_act(var/obj/item/projectile/Proj)
..()
take_damage(Proj.damage, Proj.damage_type)
return 0
/obj/effect/blob/Crossed(mob/living/L)
..()
L.blob_act()
/obj/effect/blob/attackby(obj/item/weapon/W, mob/living/user, params)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
visible_message("<span class='danger'>[user] has attacked the [src.name] with \the [W]!</span>")
if(W.damtype == BURN)
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
take_damage(W.force, W.damtype)
/obj/effect/blob/attack_animal(mob/living/simple_animal/M)
M.changeNext_move(CLICK_CD_MELEE)
M.do_attack_animation(src)
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
visible_message("<span class='danger'>\The [M] has attacked the [src.name]!</span>")
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
take_damage(damage, BRUTE)
return
/obj/effect/blob/attack_alien(mob/living/carbon/alien/humanoid/M)
M.changeNext_move(CLICK_CD_MELEE)
M.do_attack_animation(src)
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
visible_message("<span class='danger'>[M] has slashed the [src.name]!</span>")
var/damage = rand(15, 30)
take_damage(damage, BRUTE)
return
/obj/effect/blob/proc/take_damage(damage, damage_type)
if(!damage || damage_type == STAMINA) // Avoid divide by zero errors
return
switch(damage_type)
if(BRUTE)
damage /= max(brute_resist, 1)
if(BURN)
damage /= max(fire_resist, 1)
health -= damage
update_icon()
/obj/effect/blob/proc/change_to(type)
if(!ispath(type))
throw EXCEPTION("change_to(): invalid type for blob")
return
var/obj/effect/blob/B = new type(src.loc)
if(!istype(type, /obj/effect/blob/core) || !istype(type, /obj/effect/blob/node))
B.color = color
else
B.adjustcolors(color)
qdel(src)
/obj/effect/blob/proc/adjustcolors(a_color)
if(a_color)
color = a_color
return
/obj/effect/blob/examine(mob/user)
..()
user << "It looks like it's of a [get_chem_name()] kind."
return
/obj/effect/blob/proc/get_chem_name()
for(var/mob/camera/blob/B in mob_list)
if(lowertext(B.blob_reagent_datum.color) == lowertext(src.color)) // Goddamit why we use strings for these
return B.blob_reagent_datum.name
return "unknown"
/obj/effect/blob/normal
icon_state = "blob"
luminosity = 0
health = 21
/obj/effect/blob/normal/update_icon()
if(health <= 0)
qdel(src)
else if(health <= 15)
icon_state = "blob_damaged"
else
icon_state = "blob"
/* // Used to create the glow sprites. Remember to set the animate loop to 1, instead of infinite!
var/datum/blob_colour/B = new()
/datum/blob_colour/New()
..()
var/icon/I = 'icons/mob/blob.dmi'
I += rgb(35, 35, 0)
if(isfile("icons/mob/blob_result.dmi"))
fdel("icons/mob/blob_result.dmi")
fcopy(I, "icons/mob/blob_result.dmi")
*/