diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 4c21191bc6f..176fd79b61b 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -115,5 +115,6 @@ /obj/item/weapon/weldingtool = 3, /obj/item/weapon/wirecutters = 1, /obj/item/weapon/wrench = 4, + /obj/item/weapon/relic = 3, "" = 11 ) diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 12573d44897..53b70b20478 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -6,12 +6,13 @@ #define SCANTYPE_HEAT 4 #define SCANTYPE_COLD 5 #define SCANTYPE_OBLITERATE 6 +#define SCANTYPE_DISCOVER 7 -#define EFFECT_PROB_VERYLOW 10 -#define EFFECT_PROB_LOW 20 -#define EFFECT_PROB_MEDIUM 45 -#define EFFECT_PROB_HIGH 65 -#define EFFECT_PROB_VERYHIGH 85 +#define EFFECT_PROB_VERYLOW 20 +#define EFFECT_PROB_LOW 35 +#define EFFECT_PROB_MEDIUM 50 +#define EFFECT_PROB_HIGH 75 +#define EFFECT_PROB_VERYHIGH 95 #define FAIL 7 /obj/machinery/r_n_d/experimentor @@ -63,7 +64,10 @@ /obj/machinery/r_n_d/experimentor/proc/SetTypeReactions() var/probWeight = 0 for(var/I in typesof(/obj/item)) - item_reactions["[I]"] = pick(SCANTYPE_POKE,SCANTYPE_IRRADIATE,SCANTYPE_GAS,SCANTYPE_HEAT,SCANTYPE_COLD,SCANTYPE_OBLITERATE) + if(istype(I,/obj/item/weapon/relic)) + item_reactions["[I]"] = SCANTYPE_DISCOVER + else + item_reactions["[I]"] = pick(SCANTYPE_POKE,SCANTYPE_IRRADIATE,SCANTYPE_GAS,SCANTYPE_HEAT,SCANTYPE_COLD,SCANTYPE_OBLITERATE) if(ispath(I,/obj/item/weapon/stock_parts) || ispath(I,/obj/item/weapon/grenade/chem_grenade) || ispath(I,/obj/item/weapon/kitchen)) var/obj/item/tempCheck = new I() if(tempCheck.icon_state != null) //check it's an actual usable item, in a hacky way @@ -186,6 +190,8 @@ dat += "
Burn" dat += "
Freeze" dat += "
Destroy
" + if(istype(loaded_item,/obj/item/weapon/relic)) + dat += "
Discover
" dat += "
Eject" else dat += "Nothing loaded." @@ -215,11 +221,11 @@ if(loaded_item) if(cloneMode && cloneCount > 0) visible_message("A duplicate [loaded_item] pops out!") - new loaded_item(pick(oview(1,src))) + new loaded_item(get_turf(pick(oview(1,src)))) --cloneCount if(cloneCount == 0) cloneMode = FALSE - loaded_item.loc = pick(oview(1,src)) + loaded_item.loc = get_turf(pick(oview(1,src))) if(delete) qdel(loaded_item) loaded_item = null @@ -242,13 +248,6 @@ else counter = 1 -/* -#define EFFECT_PROB_VERYLOW 10 -#define EFFECT_PROB_LOW 20 -#define EFFECT_PROB_MEDIUM 45 -#define EFFECT_PROB_HIGH 65 -#define EFFECT_PROB_VERYHIGH 85 -*/ /obj/machinery/r_n_d/experimentor/proc/experiment(var/exp,var/obj/item/exp_on) recentlyExperimented = 1 icon_state = "h_lathe_wloop" @@ -264,10 +263,10 @@ for(var/mob/living/m in oview(1)) m.apply_damage(15,"brute",pick("head","chest","groin")) ejectItem(TRUE) - else if(prob(EFFECT_PROB_LOW-badThingCoeff)) + if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src] malfunctions!.") exp = SCANTYPE_OBLITERATE - else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) + if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) visible_message("[src] malfunctions, throwing the [exp_on]!.") var/mob/living/target = locate(/mob/living) in oview(7,src) if(target) @@ -287,13 +286,13 @@ for(var/mob/living/m in oview(1)) m.apply_effect(25,IRRADIATE) ejectItem(TRUE) - else if(prob(EFFECT_PROB_LOW-badThingCoeff)) + if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src] malfunctions, spewing toxic waste!.") for(var/turf/T in oview(1)) if(!T.density) if(prob(EFFECT_PROB_VERYHIGH)) new /obj/effect/decal/cleanable/greenglow(T) - else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) + if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) var/savedName = "[exp_on]" ejectItem(TRUE) var/newPath = pickWeighted(valid_items) @@ -308,7 +307,7 @@ visible_message("[src] fills it's chamber with gas, [exp_on] included.") if(prob(EFFECT_PROB_LOW) && criticalReaction) visible_message("[exp_on] achieves the perfect mix!") - new /obj/item/stack/sheet/mineral/plasma(pick(oview(1,src))) + new /obj/item/stack/sheet/mineral/plasma(get_turf(pick(oview(1,src)))) if(prob(EFFECT_PROB_VERYLOW-badThingCoeff)) visible_message("[src] destroys [exp_on], leaking dangerous gas!.") var/list/chems = list("carbon","radium","toxin","condensedcapsaicin","mushroomhallucinogen","space_drugs","ethanol","beepskysmash") @@ -321,10 +320,22 @@ smoke.start() R.delete() ejectItem(TRUE) - else if(prob(EFFECT_PROB_LOW-badThingCoeff)) + if(prob(EFFECT_PROB_VERYLOW-badThingCoeff)) + visible_message("[src]'s chemical chamber has sprung a leak!.") + var/list/chems = list("mutationtoxin","amutationtoxin","nanites","xenomicrobes") + var/datum/reagents/R = new/datum/reagents(50) + R.my_atom = src + R.add_reagent(pick(chems), 50) + var/datum/effect/effect/system/chem_smoke_spread/smoke = new + smoke.set_up(R, 1, 0, src, 0, silent = 1) + playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3) + smoke.start() + R.delete() + ejectItem(TRUE) + if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src] malfunctions, spewing harmless gas!.") throwSmoke(src.loc) - else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) + if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) visible_message("[src] melts [exp_on], ionizing the air around it!.") empulse(src.loc, 8, 10) ejectItem(TRUE) @@ -333,17 +344,20 @@ visible_message("[src] raises [exp_on]'s temperature.") if(prob(EFFECT_PROB_LOW) && criticalReaction) visible_message("[src]'s emergency coolant system gives off a small beep!") - var/obj/item/weapon/reagent_containers/food/drinks/coffee/C = new /obj/item/weapon/reagent_containers/food/drinks/coffee(pick(oview(1,src))) + var/obj/item/weapon/reagent_containers/food/drinks/coffee/C = new /obj/item/weapon/reagent_containers/food/drinks/coffee(get_turf(pick(oview(1,src)))) var/list/chems = list("plasma","capsaicin","ethanol") C.reagents.remove_any(25) C.reagents.add_reagent(pick(chems),25) C.name = "Cup of Suspicious Liquid" C.desc = "It has a large hazard symbol printed on the side in fading ink." if(prob(EFFECT_PROB_VERYLOW-badThingCoeff)) + visible_message("[src] activates it's heat-seeking system!") + new/datum/round_event/meteor_wave() + if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src] malfunctions, melting [exp_on] and releasing a burst of flame!.") explosion(src.loc, -1, 0, 0, 0, 0, flame_range = 2) ejectItem(TRUE) - else if(prob(EFFECT_PROB_LOW-badThingCoeff)) + if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) visible_message("[src] malfunctions, melting [exp_on] and leaking hot air!.") var/datum/gas_mixture/env = src.loc.return_air() var/transfer_moles = 0.25 * env.total_moles() @@ -356,7 +370,7 @@ env.merge(removed) air_update_turf() ejectItem(TRUE) - else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) + if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) visible_message("[src] malfunctions, activating it's emergency coolant systems!.") throwSmoke(src.loc) for(var/mob/living/m in oview(1)) @@ -367,7 +381,7 @@ visible_message("[src] lowers [exp_on]'s temperature.") if(prob(EFFECT_PROB_LOW) && criticalReaction) visible_message("[src]'s emergency coolant system gives off a small ping!") - var/obj/machinery/vending/coffee/C = new /obj/machinery/vending/coffee(pick(oview(1,src))) + var/obj/machinery/vending/coffee/C = new /obj/machinery/vending/coffee(get_turf(pick(oview(1,src)))) var/list/chems = list("uranium","frostoil","hyperzine") C.reagents.remove_any(25) C.reagents.add_reagent(pick(chems),25) @@ -384,7 +398,7 @@ smoke.start() R.delete() ejectItem(TRUE) - else if(prob(EFFECT_PROB_LOW-badThingCoeff)) + if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src] malfunctions, shattering [exp_on] and leaking cold air!.") var/datum/gas_mixture/env = src.loc.return_air() var/transfer_moles = 0.25 * env.total_moles() @@ -397,7 +411,7 @@ env.merge(removed) air_update_turf() ejectItem(TRUE) - else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) + if(prob(EFFECT_PROB_MEDIUM-badThingCoeff)) visible_message("[src] malfunctions, releasing a flurry of chilly air as [exp_on] pops out!.") var/datum/effect/effect/system/harmless_smoke_spread/smoke = new smoke.set_up(1,0, src.loc, 0) @@ -408,7 +422,7 @@ visible_message("[exp_on] activates the crushing mechanism, [exp_on] is destroyed!") if(prob(EFFECT_PROB_LOW) && criticalReaction) visible_message("[src]'s crushing mechanism slowly and smoothly descends, flattening the [exp_on]!") - new /obj/item/stack/sheet/plasteel(pick(oview(1,src))) + new /obj/item/stack/sheet/plasteel(get_turf(pick(oview(1,src)))) if(linked_console.linked_lathe) linked_console.linked_lathe.m_amount += min((linked_console.linked_lathe.max_material_storage - linked_console.linked_lathe.TotalMaterials()), (exp_on.m_amt)) linked_console.linked_lathe.g_amount += min((linked_console.linked_lathe.max_material_storage - linked_console.linked_lathe.TotalMaterials()), (exp_on.g_amt)) @@ -423,7 +437,7 @@ for(counter = 1, counter < throwAt.len, ++counter) var/cast = throwAt[counter] cast:throw_at(src,10,1) - else if(prob(EFFECT_PROB_LOW-badThingCoeff)) + if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src]'s crusher goes one level too high, crushing right into space-time!.") playsound(src.loc, 'sound/effects/supermatter.ogg', 50, 1, -3) var/list/oViewStuff = oview(7,src) @@ -442,6 +456,12 @@ var/b = pick("crushes","spins","viscerates","smashes","insults") visible_message("[exp_on] [a], and [b], the experiment was a failiure!") + if(exp == SCANTYPE_DISCOVER) + visible_message("[src] scans the [exp_on], revealing it's true nature!.") + playsound(src.loc, 'sound/effects/supermatter.ogg', 50, 3, -1) + var/obj/item/weapon/relic/R = loaded_item + R.reveal() + ejectItem() //Global reactions if(prob(EFFECT_PROB_VERYLOW-badThingCoeff)) @@ -466,7 +486,7 @@ m.apply_damage(50,"brute","chest") var/list/reqs = ConvertReqString2List(exp_on.origin_tech) for(var/T in reqs) - T = T + 1 + reqs[T] = reqs[T] + 1 exp_on.origin_tech = ConvertReqList2String(reqs) if(globalMalf > 51 && globalMalf < 75) visible_message("[src] encounters a run-time error!") @@ -535,3 +555,109 @@ #undef EFFECT_PROB_VERYHIGH #undef FAIL + + +//////////////////////////////////SPECIAL ITEMS//////////////////////////////////////// + +/obj/item/weapon/relic + name = "strange object" + desc = "What mysteries could this hold?" + icon = 'icons/obj/assemblies.dmi' + origin_tech = "combat=1;plasmatech=1;powerstorage=1;materials=1" + var/realName = "defined object" + var/revealed = FALSE + var/realProc + var/cooldownMax = 60 + var/cooldown + +/obj/item/weapon/relic/New() + icon_state = pick("shock_kit","armor-igniter-analyzer","infra-igniter0","infra-igniter1","radio-multitool","prox-radio1","radio-radio","timer-multitool0","radio-igniter-tank") + realName = "[pick("broken","twisted","spun","improved","silly","regular","badly made")] [pick("device","object","toy","illegal tech","weapon")]" + + +/obj/item/weapon/relic/proc/reveal() + revealed = TRUE + name = realName + cooldownMax = rand(60,300) + realProc = pick("teleport","explode","rapidDupe","petSpray","flash","clean","corgicannon") + +/obj/item/weapon/relic/attack_self(mob/user as mob) + if(revealed) + if(cooldown) + user << "[src] does not react." + return + else if(src.loc == user) + call(src,realProc)(user) + cooldown = TRUE + spawn(cooldownMax) + cooldown = FALSE + else + user << "You aren't quite sure what to do with this, yet." + +//////////////// RELIC PROCS ///////////////////////////// + +/obj/item/weapon/relic/proc/throwSmoke(var/turf/where) + var/datum/effect/effect/system/harmless_smoke_spread/smoke = new + smoke.set_up(1,0, where, 0) + smoke.start() + +/obj/item/weapon/relic/proc/corgicannon(var/mob/user) + playsound(src.loc, "sparks", rand(25,50), 1) + var/mob/living/simple_animal/corgi/C = new/mob/living/simple_animal/corgi(get_turf(user)) + C.throw_at(pick(oview(10,user)),10,rand(3,8)) + throwSmoke(get_turf(C)) + +/obj/item/weapon/relic/proc/clean(var/mob/user) + playsound(src.loc, "sparks", rand(25,50), 1) + var/obj/item/weapon/grenade/chem_grenade/cleaner/CL = new/obj/item/weapon/grenade/chem_grenade/cleaner(get_turf(user)) + CL.prime() + +/obj/item/weapon/relic/proc/flash(var/mob/user) + playsound(src.loc, "sparks", rand(25,50), 1) + var/obj/item/weapon/grenade/flashbang/CB = new/obj/item/weapon/grenade/flashbang(get_turf(user)) + CB.prime() + +/obj/item/weapon/relic/proc/petSpray(var/mob/user) + visible_message("[src] begans to shake, and in the distance the sound of rampaging animals arises!") + var/animals = rand(1,25) + var/counter + var/list/valid_animals = list(/mob/living/simple_animal/parrot,/mob/living/simple_animal/butterfly,/mob/living/simple_animal/cat,/mob/living/simple_animal/corgi,/mob/living/simple_animal/crab,/mob/living/simple_animal/fox,/mob/living/simple_animal/lizard,/mob/living/simple_animal/mouse,/mob/living/simple_animal/pug,/mob/living/simple_animal/hostile/bear,/mob/living/simple_animal/hostile/poison/bees,/mob/living/simple_animal/hostile/carp) + for(counter = 1; counter < animals; counter++) + var/mobType = pick(valid_animals) + new mobType(get_turf(src)) + +/obj/item/weapon/relic/proc/rapidDupe(var/mob/user) + visible_message("[src] emits a loud pop!") + var/list/dupes = list() + var/counter + var/max = rand(5,45) + for(counter = 1; counter < max; counter++) + var/obj/item/weapon/relic/R = new src.type(get_turf(src)) + R.name = name + R.desc = desc + R.realName = realName + R.realProc = realProc + R.revealed = TRUE + dupes |= R + R.throw_at(pick(oview(7,src)),10,1) + counter = 0 + spawn(rand(10,100)) + for(counter = 1; counter < dupes.len; counter++) + var/obj/item/weapon/relic/R = dupes[counter] + qdel(R) + +/obj/item/weapon/relic/proc/explode(var/mob/user) + visible_message("[src] begins to heat up!") + spawn(rand(35,100)) + if(src.loc == user) + visible_message("The [src]'s top opens, releasing a powerful blast!") + explosion(user.loc, -1, rand(1,5), rand(1,5), rand(1,5), rand(1,5), flame_range = 2) + +/obj/item/weapon/relic/proc/teleport(var/mob/user) + visible_message("The [src] begins to vibrate!") + spawn(rand(10,30)) + if(src.loc == user) + visible_message("The [src] twists and bends, relocating itself!") + throwSmoke(get_turf(user)) + do_teleport(user, get_turf(user), 8, asoundin = 'sound/effects/phasein.ogg') + throwSmoke(get_turf(user)) \ No newline at end of file