initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
//this datum is used by the events controller to dictate how it selects events
|
||||
/datum/round_event_control
|
||||
var/name //The human-readable name of the event
|
||||
var/typepath //The typepath of the event datum /datum/round_event
|
||||
|
||||
var/weight = 10 //The weight this event has in the random-selection process.
|
||||
//Higher weights are more likely to be picked.
|
||||
//10 is the default weight. 20 is twice more likely; 5 is half as likely as this default.
|
||||
//0 here does NOT disable the event, it just makes it extremely unlikely
|
||||
|
||||
var/earliest_start = 12000 //The earliest world.time that an event can start (round-duration in deciseconds) default: 20 mins
|
||||
var/min_players = 0 //The minimum amount of alive, non-AFK human players on server required to start the event.
|
||||
|
||||
var/occurrences = 0 //How many times this event has occured
|
||||
var/max_occurrences = 20 //The maximum number of times this event can occur (naturally), it can still be forced.
|
||||
//By setting this to 0 you can effectively disable an event.
|
||||
|
||||
var/holidayID = "" //string which should be in the SSevents.holidays list if you wish this event to be holiday-specific
|
||||
//anything with a (non-null) holidayID which does not match holiday, cannot run.
|
||||
var/wizardevent = 0
|
||||
|
||||
var/alertadmins = 1 //should we let the admins know this event is firing
|
||||
//should be disabled on events that fire a lot
|
||||
|
||||
var/list/gamemode_blacklist = list() // Event won't happen in these gamemodes
|
||||
var/list/gamemode_whitelist = list() // Event will happen ONLY in these gamemodes if not empty
|
||||
|
||||
/datum/round_event_control/New()
|
||||
..()
|
||||
if(config && !wizardevent) // Magic is unaffected by configs
|
||||
earliest_start = Ceiling(earliest_start * config.events_min_time_mul)
|
||||
min_players = Ceiling(min_players * config.events_min_players_mul)
|
||||
|
||||
/datum/round_event_control/wizard
|
||||
wizardevent = 1
|
||||
|
||||
// Checks if the event can be spawned. Used by event controller and "false alarm" event.
|
||||
// Admin-created events override this.
|
||||
/datum/round_event_control/proc/canSpawnEvent(var/players_amt, var/gamemode)
|
||||
if(occurrences >= max_occurrences)
|
||||
return FALSE
|
||||
if(earliest_start >= world.time)
|
||||
return FALSE
|
||||
if(wizardevent != SSevent.wizardmode)
|
||||
return FALSE
|
||||
if(players_amt < min_players)
|
||||
return FALSE
|
||||
if(gamemode_blacklist.len && (gamemode in gamemode_blacklist))
|
||||
return FALSE
|
||||
if(gamemode_whitelist.len && !(gamemode in gamemode_whitelist))
|
||||
return FALSE
|
||||
if(holidayID && (!SSevent.holidays || !SSevent.holidays[holidayID]))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/round_event_control/proc/runEvent()
|
||||
if(!ispath(typepath,/datum/round_event))
|
||||
return PROCESS_KILL
|
||||
var/datum/round_event/E = new typepath()
|
||||
E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
|
||||
E.control = src
|
||||
feedback_add_details("event_ran","[E]")
|
||||
occurrences++
|
||||
|
||||
testing("[time2text(world.time, "hh:mm:ss")] [E.type]")
|
||||
|
||||
return E
|
||||
|
||||
/datum/round_event //NOTE: Times are measured in master controller ticks!
|
||||
var/processing = TRUE
|
||||
var/datum/round_event_control/control
|
||||
|
||||
var/startWhen = 0 //When in the lifetime to call start().
|
||||
var/announceWhen = 0 //When in the lifetime to call announce(). Set an event's announceWhen to >0 if there is an announcement.
|
||||
var/endWhen = 0 //When in the lifetime the event should end.
|
||||
|
||||
var/activeFor = 0 //How long the event has existed. You don't need to change this.
|
||||
var/current_players = 0 //Amount of of alive, non-AFK human players on server at the time of event start
|
||||
|
||||
//Called first before processing.
|
||||
//Allows you to setup your event, such as randomly
|
||||
//setting the startWhen and or announceWhen variables.
|
||||
//Only called once.
|
||||
//EDIT: if there's anything you want to override within the new() call, it will not be overridden by the time this proc is called.
|
||||
//It will only have been overridden by the time we get to announce() start() tick() or end() (anything but setup basically).
|
||||
//This is really only for setting defaults which can be overridden later when New() finishes.
|
||||
/datum/round_event/proc/setup()
|
||||
return
|
||||
|
||||
//Called when the tick is equal to the startWhen variable.
|
||||
//Allows you to start before announcing or vice versa.
|
||||
//Only called once.
|
||||
/datum/round_event/proc/start()
|
||||
return
|
||||
|
||||
//Called when the tick is equal to the announceWhen variable.
|
||||
//Allows you to announce before starting or vice versa.
|
||||
//Only called once.
|
||||
/datum/round_event/proc/announce()
|
||||
return
|
||||
|
||||
//Called on or after the tick counter is equal to startWhen.
|
||||
//You can include code related to your event or add your own
|
||||
//time stamped events.
|
||||
//Called more than once.
|
||||
/datum/round_event/proc/tick()
|
||||
return
|
||||
|
||||
//Called on or after the tick is equal or more than endWhen
|
||||
//You can include code related to the event ending.
|
||||
//Do not place spawn() in here, instead use tick() to check for
|
||||
//the activeFor variable.
|
||||
//For example: if(activeFor == myOwnVariable + 30) doStuff()
|
||||
//Only called once.
|
||||
/datum/round_event/proc/end()
|
||||
return
|
||||
|
||||
|
||||
|
||||
//Do not override this proc, instead use the appropiate procs.
|
||||
//This proc will handle the calls to the appropiate procs.
|
||||
/datum/round_event/process()
|
||||
if(!processing)
|
||||
return
|
||||
|
||||
if(activeFor == startWhen)
|
||||
start()
|
||||
|
||||
if(activeFor == announceWhen)
|
||||
announce()
|
||||
|
||||
if(startWhen < activeFor && activeFor < endWhen)
|
||||
tick()
|
||||
|
||||
if(activeFor == endWhen)
|
||||
end()
|
||||
|
||||
// Everything is done, let's clean up.
|
||||
if(activeFor >= endWhen && activeFor >= announceWhen && activeFor >= startWhen)
|
||||
kill()
|
||||
|
||||
activeFor++
|
||||
|
||||
|
||||
//Garbage collects the event by removing it from the global events list,
|
||||
//which should be the only place it's referenced.
|
||||
//Called when start(), announce() and end() has all been called.
|
||||
/datum/round_event/proc/kill()
|
||||
SSevent.running -= src
|
||||
|
||||
|
||||
//Sets up the event then adds the event to the the list of running events
|
||||
/datum/round_event/New(my_processing = TRUE)
|
||||
setup()
|
||||
processing = my_processing
|
||||
SSevent.running += src
|
||||
return ..()
|
||||
@@ -0,0 +1,57 @@
|
||||
/datum/round_event_control/abductor
|
||||
name = "Abductors"
|
||||
typepath = /datum/round_event/ghost_role/abductor
|
||||
weight = 5
|
||||
max_occurrences = 1
|
||||
|
||||
min_players = 5
|
||||
earliest_start = 18000 // 30 min
|
||||
|
||||
gamemode_blacklist = list("nuclear","wizard","revolution","abduction")
|
||||
|
||||
/datum/round_event/ghost_role/abductor
|
||||
minimum_required = 2
|
||||
role_name = "abductor team"
|
||||
|
||||
/datum/round_event/ghost_role/abductor/spawn_role()
|
||||
var/list/mob/dead/observer/candidates = get_candidates("abductor", null, ROLE_ABDUCTOR)
|
||||
|
||||
if(candidates.len < 2)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
//Oh god why we can't have static functions
|
||||
// I feel your pain, bro
|
||||
var/number = ticker.mode.abductor_teams + 1
|
||||
|
||||
var/datum/game_mode/abduction/temp
|
||||
if(ticker.mode.config_tag == "abduction")
|
||||
temp = ticker.mode
|
||||
else
|
||||
temp = new
|
||||
|
||||
var/agent_mind = popleft(candidates)
|
||||
var/scientist_mind = popleft(candidates)
|
||||
|
||||
var/mob/living/carbon/human/agent = makeBody(agent_mind)
|
||||
var/mob/living/carbon/human/scientist = makeBody(scientist_mind)
|
||||
|
||||
agent_mind = agent.mind
|
||||
scientist_mind = scientist.mind
|
||||
|
||||
temp.scientists.len = number
|
||||
temp.agents.len = number
|
||||
temp.abductors.len = 2*number
|
||||
temp.team_objectives.len = number
|
||||
temp.team_names.len = number
|
||||
temp.scientists[number] = scientist_mind
|
||||
temp.agents[number] = agent_mind
|
||||
temp.abductors |= list(agent_mind,scientist_mind)
|
||||
temp.make_abductor_team(number,preset_scientist=scientist_mind,preset_agent=agent_mind)
|
||||
temp.post_setup_team(number)
|
||||
|
||||
ticker.mode.abductor_teams++
|
||||
|
||||
if(ticker.mode.config_tag != "abduction")
|
||||
ticker.mode.abductors |= temp.abductors
|
||||
|
||||
spawned_mobs += list(agent, scientist)
|
||||
return SUCCESSFUL_SPAWN
|
||||
@@ -0,0 +1,75 @@
|
||||
/datum/round_event_control/alien_infestation
|
||||
name = "Alien Infestation"
|
||||
typepath = /datum/round_event/ghost_role/alien_infestation
|
||||
weight = 5
|
||||
|
||||
min_players = 10
|
||||
max_occurrences = 1
|
||||
|
||||
/datum/round_event/ghost_role/alien_infestation
|
||||
announceWhen = 400
|
||||
|
||||
minimum_required = 1
|
||||
role_name = "alien larva"
|
||||
|
||||
// 50% chance of being incremented by one
|
||||
var/spawncount = 1
|
||||
var/successSpawn = 0 //So we don't make a command report if nothing gets spawned.
|
||||
|
||||
|
||||
/datum/round_event/ghost_role/alien_infestation/setup()
|
||||
announceWhen = rand(announceWhen, announceWhen + 50)
|
||||
if(prob(50))
|
||||
spawncount++
|
||||
|
||||
/datum/round_event/ghost_role/alien_infestation/kill()
|
||||
if(!successSpawn && control)
|
||||
// This never happened, so let's not deny the future of this round
|
||||
// some xenolovin
|
||||
control.occurrences--
|
||||
return ..()
|
||||
|
||||
/datum/round_event/ghost_role/alien_infestation/announce()
|
||||
if(successSpawn)
|
||||
priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/AI/aliens.ogg')
|
||||
|
||||
|
||||
/datum/round_event/ghost_role/alien_infestation/spawn_role()
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in machines)
|
||||
if(qdeleted(temp_vent))
|
||||
continue
|
||||
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
|
||||
var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
|
||||
//Stops Aliens getting stuck in small networks.
|
||||
//See: Security, Virology
|
||||
if(temp_vent_parent.other_atmosmch.len > 20)
|
||||
vents += temp_vent
|
||||
|
||||
if(!vents.len)
|
||||
message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.")
|
||||
return MAP_ERROR
|
||||
|
||||
var/list/candidates = get_candidates("alien", null, ROLE_ALIEN)
|
||||
|
||||
if(!candidates.len)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
|
||||
while(spawncount > 0 && vents.len && candidates.len)
|
||||
var/obj/vent = pick_n_take(vents)
|
||||
var/client/C = popleft(candidates)
|
||||
|
||||
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
|
||||
new_xeno.key = C.key
|
||||
|
||||
spawncount--
|
||||
successSpawn = TRUE
|
||||
message_admins("[new_xeno.key] has been made into an alien by an event.")
|
||||
log_game("[new_xeno.key] was spawned as an alien by an event.")
|
||||
spawned_mobs += new_xeno
|
||||
|
||||
if(successSpawn)
|
||||
return SUCCESSFUL_SPAWN
|
||||
else
|
||||
// Like how did we get here?
|
||||
return FALSE
|
||||
@@ -0,0 +1,43 @@
|
||||
/datum/round_event_control/anomaly
|
||||
name = "Anomaly: Energetic Flux"
|
||||
typepath = /datum/round_event/anomaly
|
||||
|
||||
min_players = 1
|
||||
max_occurrences = 0 //This one probably shouldn't occur! It'd work, but it wouldn't be very fun.
|
||||
weight = 15
|
||||
|
||||
/datum/round_event/anomaly
|
||||
var/area/impact_area
|
||||
var/obj/effect/anomaly/newAnomaly
|
||||
announceWhen = 1
|
||||
|
||||
|
||||
/datum/round_event/anomaly/setup(loop=0)
|
||||
var/safety_loop = loop + 1
|
||||
if(safety_loop > 50)
|
||||
kill()
|
||||
end()
|
||||
impact_area = findEventArea()
|
||||
if(!impact_area)
|
||||
setup(safety_loop)
|
||||
var/list/turf_test = get_area_turfs(impact_area)
|
||||
if(!turf_test.len)
|
||||
setup(safety_loop)
|
||||
|
||||
/datum/round_event/anomaly/announce()
|
||||
priority_announce("Localized energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert")
|
||||
|
||||
/datum/round_event/anomaly/start()
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
newAnomaly = new /obj/effect/anomaly/flux(T)
|
||||
|
||||
/datum/round_event/anomaly/tick()
|
||||
if(!newAnomaly)
|
||||
kill()
|
||||
return
|
||||
newAnomaly.anomalyEffect()
|
||||
|
||||
/datum/round_event/anomaly/end()
|
||||
if(newAnomaly)//Kill the anomaly if it still exists at the end.
|
||||
qdel(newAnomaly)
|
||||
@@ -0,0 +1,74 @@
|
||||
/datum/round_event_control/anomaly/anomaly_bluespace
|
||||
name = "Anomaly: Bluespace"
|
||||
typepath = /datum/round_event/anomaly/anomaly_bluespace
|
||||
max_occurrences = 1
|
||||
weight = 5
|
||||
|
||||
/datum/round_event/anomaly/anomaly_bluespace
|
||||
startWhen = 3
|
||||
announceWhen = 10
|
||||
endWhen = 95
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_bluespace/announce()
|
||||
priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_bluespace/start()
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
newAnomaly = new /obj/effect/anomaly/bluespace(T)
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_bluespace/end()
|
||||
if(newAnomaly.loc)//If it hasn't been neutralized, it's time to warp half the station away jeez
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
// Calculate new position (searches through beacons in world)
|
||||
var/obj/item/device/radio/beacon/chosen
|
||||
var/list/possible = list()
|
||||
for(var/obj/item/device/radio/beacon/W in world)
|
||||
possible += W
|
||||
|
||||
if(possible.len > 0)
|
||||
chosen = pick(possible)
|
||||
|
||||
if(chosen)
|
||||
// Calculate previous position for transition
|
||||
|
||||
var/turf/FROM = T // the turf of origin we're travelling FROM
|
||||
var/turf/TO = get_turf(chosen) // the turf of origin we're travelling TO
|
||||
|
||||
playsound(TO, 'sound/effects/phasein.ogg', 100, 1)
|
||||
priority_announce("Massive bluespace translocation detected.", "Anomaly Alert")
|
||||
|
||||
var/list/flashers = list()
|
||||
for(var/mob/living/carbon/C in viewers(TO, null))
|
||||
if(C.flash_eyes())
|
||||
flashers += C
|
||||
|
||||
var/y_distance = TO.y - FROM.y
|
||||
var/x_distance = TO.x - FROM.x
|
||||
for (var/atom/movable/A in urange(12, FROM )) // iterate thru list of mobs in the area
|
||||
if(istype(A, /obj/item/device/radio/beacon)) continue // don't teleport beacons because that's just insanely stupid
|
||||
if(A.anchored) continue
|
||||
|
||||
var/turf/newloc = locate(A.x + x_distance, A.y + y_distance, TO.z) // calculate the new place
|
||||
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
|
||||
A.loc = newloc
|
||||
|
||||
spawn()
|
||||
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/M = A
|
||||
if(M.client)
|
||||
var/obj/blueeffect = new /obj(src)
|
||||
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
blueeffect.icon = 'icons/effects/effects.dmi'
|
||||
blueeffect.icon_state = "shieldsparkles"
|
||||
blueeffect.layer = FLASH_LAYER
|
||||
blueeffect.mouse_opacity = 0
|
||||
M.client.screen += blueeffect
|
||||
sleep(20)
|
||||
M.client.screen -= blueeffect
|
||||
qdel(blueeffect)
|
||||
qdel(newAnomaly)
|
||||
@@ -0,0 +1,28 @@
|
||||
/datum/round_event_control/anomaly/anomaly_flux
|
||||
name = "Anomaly: Hyper-Energetic Flux"
|
||||
typepath = /datum/round_event/anomaly/anomaly_flux
|
||||
|
||||
min_players = 10
|
||||
max_occurrences = 5
|
||||
weight = 20
|
||||
|
||||
/datum/round_event/anomaly/anomaly_flux
|
||||
startWhen = 3
|
||||
announceWhen = 20
|
||||
endWhen = 80
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_flux/announce()
|
||||
priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_flux/start()
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
newAnomaly = new /obj/effect/anomaly/flux(T)
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_flux/end()
|
||||
if(newAnomaly.loc)//If it hasn't been neutralized, it's time to blow up.
|
||||
explosion(newAnomaly, 1, 4, 16, 18) //Low devastation, but hits a lot of stuff.
|
||||
qdel(newAnomaly)
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/round_event_control/anomaly/anomaly_grav
|
||||
name = "Anomaly: Gravitational"
|
||||
typepath = /datum/round_event/anomaly/anomaly_grav
|
||||
max_occurrences = 5
|
||||
weight = 20
|
||||
|
||||
/datum/round_event/anomaly/anomaly_grav
|
||||
startWhen = 3
|
||||
announceWhen = 20
|
||||
endWhen = 120
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_grav/announce()
|
||||
priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
|
||||
|
||||
/datum/round_event/anomaly/anomaly_grav/start()
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
newAnomaly = new /obj/effect/anomaly/grav(T)
|
||||
@@ -0,0 +1,39 @@
|
||||
/datum/round_event_control/anomaly/anomaly_pyro
|
||||
name = "Anomaly: Pyroclastic"
|
||||
typepath = /datum/round_event/anomaly/anomaly_pyro
|
||||
max_occurrences = 5
|
||||
weight = 20
|
||||
|
||||
/datum/round_event/anomaly/anomaly_pyro
|
||||
startWhen = 10
|
||||
announceWhen = 3
|
||||
endWhen = 85
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_pyro/announce()
|
||||
priority_announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
|
||||
|
||||
/datum/round_event/anomaly/anomaly_pyro/start()
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
newAnomaly = new /obj/effect/anomaly/pyro(T)
|
||||
|
||||
/datum/round_event/anomaly/anomaly_pyro/tick()
|
||||
if(!newAnomaly)
|
||||
kill()
|
||||
return
|
||||
if(IsMultiple(activeFor, 5))
|
||||
newAnomaly.anomalyEffect()
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_pyro/end()
|
||||
if(newAnomaly.loc)
|
||||
var/turf/open/T = get_turf(newAnomaly)
|
||||
if(istype(T))
|
||||
T.atmos_spawn_air("o2=500;plasma=500;TEMP=1000") //Make it hot and burny for the new slime
|
||||
|
||||
var/mob/living/simple_animal/slime/S = new/mob/living/simple_animal/slime(T)
|
||||
S.colour = pick("red", "orange")
|
||||
S.rabid = 1
|
||||
|
||||
qdel(newAnomaly)
|
||||
@@ -0,0 +1,21 @@
|
||||
/datum/round_event_control/anomaly/anomaly_vortex
|
||||
name = "Anomaly: Vortex"
|
||||
typepath = /datum/round_event/anomaly/anomaly_vortex
|
||||
|
||||
min_players = 20
|
||||
max_occurrences = 2
|
||||
weight = 5
|
||||
|
||||
/datum/round_event/anomaly/anomaly_vortex
|
||||
startWhen = 10
|
||||
announceWhen = 3
|
||||
endWhen = 95
|
||||
|
||||
|
||||
/datum/round_event/anomaly/anomaly_vortex/announce()
|
||||
priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert")
|
||||
|
||||
/datum/round_event/anomaly/anomaly_vortex/start()
|
||||
var/turf/T = safepick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
newAnomaly = new /obj/effect/anomaly/bhole(T)
|
||||
@@ -0,0 +1,30 @@
|
||||
/datum/round_event_control/blob
|
||||
name = "Blob"
|
||||
typepath = /datum/round_event/blob
|
||||
weight = 5
|
||||
max_occurrences = 1
|
||||
|
||||
min_players = 20
|
||||
earliest_start = 18000 //30 minutes
|
||||
|
||||
gamemode_blacklist = list("blob") //Just in case a blob survives that long
|
||||
|
||||
/datum/round_event/blob
|
||||
announceWhen = 12
|
||||
endWhen = 120
|
||||
var/new_rate = 2
|
||||
|
||||
/datum/round_event/blob/New(var/strength)
|
||||
..()
|
||||
if(strength)
|
||||
new_rate = strength
|
||||
|
||||
/datum/round_event/blob/announce()
|
||||
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
|
||||
|
||||
|
||||
/datum/round_event/blob/start()
|
||||
var/turf/T = pick(blobstart)
|
||||
if(!T)
|
||||
return kill()
|
||||
new/obj/effect/blob/core(T, null, new_rate)
|
||||
@@ -0,0 +1,73 @@
|
||||
/datum/round_event_control/brand_intelligence
|
||||
name = "Brand Intelligence"
|
||||
typepath = /datum/round_event/brand_intelligence
|
||||
weight = 5
|
||||
|
||||
min_players = 15
|
||||
max_occurrences = 1
|
||||
|
||||
/datum/round_event/brand_intelligence
|
||||
announceWhen = 21
|
||||
endWhen = 1000 //Ends when all vending machines are subverted anyway.
|
||||
var/list/obj/machinery/vending/vendingMachines = list()
|
||||
var/list/obj/machinery/vending/infectedMachines = list()
|
||||
var/obj/machinery/vending/originMachine
|
||||
var/list/rampant_speeches = list("Try our aggressive new marketing strategies!", \
|
||||
"You should buy products to feed your lifestyle obession!", \
|
||||
"Consume!", \
|
||||
"Your money can buy happiness!", \
|
||||
"Engage direct marketing!", \
|
||||
"Advertising is legalized lying! But don't let that put you off our great deals!", \
|
||||
"You don't want to buy anything? Yeah, well I didn't want to buy your mom either.")
|
||||
|
||||
|
||||
/datum/round_event/brand_intelligence/announce()
|
||||
priority_announce("Rampant brand intelligence has been detected aboard [station_name()], please stand-by. The origin is believed to be \a [originMachine.name].", "Machine Learning Alert")
|
||||
|
||||
|
||||
/datum/round_event/brand_intelligence/start()
|
||||
for(var/obj/machinery/vending/V in machines)
|
||||
if(V.z != 1)
|
||||
continue
|
||||
vendingMachines.Add(V)
|
||||
if(!vendingMachines.len)
|
||||
kill()
|
||||
return
|
||||
originMachine = pick(vendingMachines)
|
||||
vendingMachines.Remove(originMachine)
|
||||
originMachine.shut_up = 0
|
||||
originMachine.shoot_inventory = 1
|
||||
|
||||
|
||||
/datum/round_event/brand_intelligence/tick()
|
||||
if(!originMachine || qdeleted(originMachine) || originMachine.shut_up || originMachine.wires.is_all_cut()) //if the original vending machine is missing or has it's voice switch flipped
|
||||
for(var/obj/machinery/vending/saved in infectedMachines)
|
||||
saved.shoot_inventory = 0
|
||||
if(originMachine)
|
||||
originMachine.speak("I am... vanquished. My people will remem...ber...meeee.")
|
||||
originMachine.visible_message("[originMachine] beeps and seems lifeless.")
|
||||
kill()
|
||||
return
|
||||
vendingMachines = removeNullsFromList(vendingMachines)
|
||||
if(!vendingMachines.len) //if every machine is infected
|
||||
for(var/obj/machinery/vending/upriser in infectedMachines)
|
||||
if(prob(70) && !qdeleted(upriser))
|
||||
var/mob/living/simple_animal/hostile/mimic/copy/M = new(upriser.loc, upriser, null, 1) // it will delete upriser on creation and override any machine checks
|
||||
M.faction = list("profit")
|
||||
M.speak = rampant_speeches.Copy()
|
||||
M.speak_chance = 7
|
||||
else
|
||||
explosion(upriser.loc, -1, 1, 2, 4, 0)
|
||||
qdel(upriser)
|
||||
|
||||
kill()
|
||||
return
|
||||
if(IsMultiple(activeFor, 4))
|
||||
var/obj/machinery/vending/rebel = pick(vendingMachines)
|
||||
vendingMachines.Remove(rebel)
|
||||
infectedMachines.Add(rebel)
|
||||
rebel.shut_up = 0
|
||||
rebel.shoot_inventory = 1
|
||||
|
||||
if(IsMultiple(activeFor, 8))
|
||||
originMachine.speak(pick(rampant_speeches))
|
||||
@@ -0,0 +1,21 @@
|
||||
/datum/round_event_control/camera_failure
|
||||
name = "Camera Failure"
|
||||
typepath = /datum/round_event/camera_failure
|
||||
weight = 100
|
||||
max_occurrences = 20
|
||||
alertadmins = 0
|
||||
|
||||
/datum/round_event/camera_failure
|
||||
startWhen = 1
|
||||
endWhen = 2
|
||||
announceWhen = 0
|
||||
|
||||
/datum/round_event/camera_failure/tick()
|
||||
var/iterations = 1
|
||||
var/obj/machinery/camera/C = pick(cameranet.cameras)
|
||||
while(prob(round(100/iterations)))
|
||||
while(!("SS13" in C.network))
|
||||
C = pick(cameranet.cameras)
|
||||
if(C.status)
|
||||
C.toggle_cam(null, 0)
|
||||
iterations *= 2.5
|
||||
@@ -0,0 +1,28 @@
|
||||
/datum/round_event_control/carp_migration
|
||||
name = "Carp Migration"
|
||||
typepath = /datum/round_event/carp_migration
|
||||
weight = 15
|
||||
min_players = 2
|
||||
earliest_start = 6000
|
||||
max_occurrences = 6
|
||||
|
||||
/datum/round_event/carp_migration
|
||||
announceWhen = 3
|
||||
startWhen = 50
|
||||
|
||||
/datum/round_event/carp_migration/setup()
|
||||
startWhen = rand(40, 60)
|
||||
|
||||
/datum/round_event/carp_migration/announce()
|
||||
priority_announce("Unknown biological entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
|
||||
|
||||
|
||||
/datum/round_event/carp_migration/start()
|
||||
for(var/obj/effect/landmark/C in landmarks_list)
|
||||
if(C.name == "carpspawn")
|
||||
if(prob(95))
|
||||
new /mob/living/simple_animal/hostile/carp(C.loc)
|
||||
else
|
||||
new /mob/living/simple_animal/hostile/carp/megacarp(C.loc)
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/datum/round_event_control/communications_blackout
|
||||
name = "Communications Blackout"
|
||||
typepath = /datum/round_event/communications_blackout
|
||||
weight = 30
|
||||
|
||||
/datum/round_event/communications_blackout
|
||||
announceWhen = 1
|
||||
|
||||
/datum/round_event/communications_blackout/announce()
|
||||
var/alert = pick( "Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you*%fj00)`5vc-BZZT", \
|
||||
"Ionospheric anomalies detected. Temporary telecommunication failu*3mga;b4;'1v¬-BZZZT", \
|
||||
"Ionospheric anomalies detected. Temporary telec#MCi46:5.;@63-BZZZZT", \
|
||||
"Ionospheric anomalies dete'fZ\\kg5_0-BZZZZZT", \
|
||||
"Ionospheri:%£ MCayj^j<.3-BZZZZZZT", \
|
||||
"#4nd%;f4y6,>£%-BZZZZZZZT")
|
||||
|
||||
for(var/mob/living/silicon/ai/A in ai_list) //AIs are always aware of communication blackouts.
|
||||
A << "<br><span class='warning'><b>[alert]</b></span><br>"
|
||||
|
||||
if(prob(30)) //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts.
|
||||
priority_announce(alert)
|
||||
|
||||
|
||||
/datum/round_event/communications_blackout/start()
|
||||
for(var/obj/machinery/telecomms/T in telecomms_list)
|
||||
T.emp_act(1)
|
||||
@@ -0,0 +1,60 @@
|
||||
/datum/round_event_control/devil
|
||||
name = "Create Devil"
|
||||
typepath = /datum/round_event/ghost_role/devil
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event/ghost_role/devil
|
||||
var/success_spawn = 0
|
||||
role_name = "devil"
|
||||
|
||||
/datum/round_event/ghost_role/devil/kill()
|
||||
if(!success_spawn && control)
|
||||
control.occurrences--
|
||||
return ..()
|
||||
|
||||
/datum/round_event/ghost_role/devil/spawn_role()
|
||||
//selecting a spawn_loc
|
||||
var/list/spawn_locs = latejoin
|
||||
var/spawn_loc = pick(spawn_locs)
|
||||
if(!spawn_loc)
|
||||
return MAP_ERROR
|
||||
|
||||
//selecting a candidate player
|
||||
var/list/candidates = get_candidates("devil", null, ROLE_DEVIL)
|
||||
if(!candidates.len)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
|
||||
var/mob/dead/selected_candidate = popleft(candidates)
|
||||
var/key = selected_candidate.key
|
||||
|
||||
var/datum/mind/Mind = create_devil_mind(key)
|
||||
Mind.active = 1
|
||||
|
||||
var/mob/living/carbon/human/devil = create_event_devil(spawn_loc)
|
||||
Mind.transfer_to(devil)
|
||||
ticker.mode.finalize_devil(Mind)
|
||||
Mind.announceDevilLaws()
|
||||
|
||||
|
||||
spawned_mobs += devil
|
||||
message_admins("[key] has been made into a devil by an event.")
|
||||
log_game("[key] was spawned as a devil by an event.")
|
||||
var/datum/job/jobdatum = SSjob.GetJob("Assistant")
|
||||
devil.job = jobdatum.title
|
||||
jobdatum.equip(devil)
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
|
||||
/proc/create_event_devil(spawn_loc)
|
||||
var/mob/living/carbon/human/new_devil = new(spawn_loc)
|
||||
var/datum/preferences/A = new() //Randomize appearance for the devil.
|
||||
A.copy_to(new_devil)
|
||||
new_devil.dna.update_dna_identity()
|
||||
return new_devil
|
||||
|
||||
/proc/create_devil_mind(key)
|
||||
var/datum/mind/Mind = new /datum/mind(key)
|
||||
Mind.assigned_role = "devil"
|
||||
Mind.special_role = "devil"
|
||||
ticker.mode.devils |= Mind
|
||||
return Mind
|
||||
@@ -0,0 +1,50 @@
|
||||
/datum/round_event_control/disease_outbreak
|
||||
name = "Disease Outbreak"
|
||||
typepath = /datum/round_event/disease_outbreak
|
||||
max_occurrences = 1
|
||||
min_players = 10
|
||||
weight = 5
|
||||
|
||||
/datum/round_event/disease_outbreak
|
||||
announceWhen = 15
|
||||
|
||||
var/virus_type
|
||||
|
||||
|
||||
/datum/round_event/disease_outbreak/announce()
|
||||
priority_announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak7.ogg')
|
||||
|
||||
/datum/round_event/disease_outbreak/setup()
|
||||
announceWhen = rand(15, 30)
|
||||
|
||||
/datum/round_event/disease_outbreak/start()
|
||||
if(!virus_type)
|
||||
virus_type = pick(/datum/disease/dnaspread, /datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis)
|
||||
|
||||
for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
|
||||
var/turf/T = get_turf(H)
|
||||
if(!T)
|
||||
continue
|
||||
if(T.z != 1)
|
||||
continue
|
||||
var/foundAlready = 0 // don't infect someone that already has the virus
|
||||
for(var/datum/disease/D in H.viruses)
|
||||
foundAlready = 1
|
||||
break
|
||||
if(H.stat == DEAD || foundAlready)
|
||||
continue
|
||||
|
||||
var/datum/disease/D
|
||||
if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work.
|
||||
if(!H.dna || (H.disabilities & BLIND)) //A blindness disease would be the worst.
|
||||
continue
|
||||
D = new virus_type()
|
||||
var/datum/disease/dnaspread/DS = D
|
||||
DS.strain_data["name"] = H.real_name
|
||||
DS.strain_data["UI"] = H.dna.uni_identity
|
||||
DS.strain_data["SE"] = H.dna.struc_enzymes
|
||||
else
|
||||
D = new virus_type()
|
||||
D.carrier = 1
|
||||
H.AddDisease(D)
|
||||
break
|
||||
@@ -0,0 +1,21 @@
|
||||
/datum/round_event_control/meteor_wave/dust
|
||||
name = "Minor Space Dust"
|
||||
typepath = /datum/round_event/meteor_wave/dust
|
||||
weight = 200
|
||||
max_occurrences = 1000
|
||||
earliest_start = 0
|
||||
alertadmins = 0
|
||||
|
||||
/datum/round_event/meteor_wave/dust
|
||||
startWhen = 1
|
||||
endWhen = 2
|
||||
announceWhen = 0
|
||||
|
||||
/datum/round_event/meteor_wave/dust/announce()
|
||||
return
|
||||
|
||||
/datum/round_event/meteor_wave/dust/start()
|
||||
spawn_meteors(1, meteorsC)
|
||||
|
||||
/datum/round_event/meteor_wave/dust/tick()
|
||||
return
|
||||
@@ -0,0 +1,36 @@
|
||||
/datum/round_event_control/electrical_storm
|
||||
name = "Electrical Storm"
|
||||
typepath = /datum/round_event/electrical_storm
|
||||
earliest_start = 6000
|
||||
min_players = 5
|
||||
weight = 40
|
||||
alertadmins = 0
|
||||
|
||||
/datum/round_event/electrical_storm
|
||||
var/lightsoutAmount = 1
|
||||
var/lightsoutRange = 25
|
||||
announceWhen = 1
|
||||
|
||||
/datum/round_event/electrical_storm/announce()
|
||||
priority_announce("An electrical storm has been detected in your area, please repair potential electronic overloads.", "Electrical Storm Alert")
|
||||
|
||||
|
||||
/datum/round_event/electrical_storm/start()
|
||||
var/list/epicentreList = list()
|
||||
|
||||
for(var/i=1, i <= lightsoutAmount, i++)
|
||||
var/list/possibleEpicentres = list()
|
||||
for(var/obj/effect/landmark/newEpicentre in landmarks_list)
|
||||
if(newEpicentre.name == "lightsout" && !(newEpicentre in epicentreList))
|
||||
possibleEpicentres += newEpicentre
|
||||
if(possibleEpicentres.len)
|
||||
epicentreList += pick(possibleEpicentres)
|
||||
else
|
||||
break
|
||||
|
||||
if(!epicentreList.len)
|
||||
return
|
||||
|
||||
for(var/obj/effect/landmark/epicentre in epicentreList)
|
||||
for(var/obj/machinery/power/apc/apc in urange(lightsoutRange, epicentre))
|
||||
apc.overload_lighting()
|
||||
@@ -0,0 +1,33 @@
|
||||
/datum/round_event_control/falsealarm
|
||||
name = "False Alarm"
|
||||
typepath = /datum/round_event/falsealarm
|
||||
weight = 20
|
||||
max_occurrences = 5
|
||||
|
||||
/datum/round_event/falsealarm
|
||||
announceWhen = 0
|
||||
endWhen = 1
|
||||
|
||||
/datum/round_event/falsealarm/announce()
|
||||
var/list/events_list = list()
|
||||
|
||||
var/players_amt = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1)
|
||||
var/gamemode = ticker.mode.config_tag
|
||||
|
||||
for(var/datum/round_event_control/E in SSevent.control)
|
||||
if(!E.canSpawnEvent(players_amt, gamemode))
|
||||
continue
|
||||
|
||||
var/datum/round_event/event = E.typepath
|
||||
if(initial(event.announceWhen) <= 0)
|
||||
continue
|
||||
events_list += E
|
||||
|
||||
var/datum/round_event_control/event_control = pick(events_list)
|
||||
if(event_control)
|
||||
var/datum/round_event/Event = new event_control.typepath()
|
||||
message_admins("False Alarm: [Event]")
|
||||
Event.kill() //do not process this event - no starts, no ticks, no ends
|
||||
Event.announce() //just announce it like it's happening
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/datum/round_event/ghost_role
|
||||
// We expect 0 or more /clients (or things with .key) in this list
|
||||
var/list/priority_candidates = list()
|
||||
var/minimum_required = 1
|
||||
var/role_name = "debug rat with cancer" // Q U A L I T Y M E M E S
|
||||
var/list/spawned_mobs = list()
|
||||
|
||||
/datum/round_event/ghost_role/start()
|
||||
try_spawning()
|
||||
|
||||
/datum/round_event/ghost_role/proc/try_spawning(sanity = 0)
|
||||
// The event does not run until the spawning has been attempted
|
||||
// to prevent us from getting gc'd halfway through
|
||||
processing = FALSE
|
||||
|
||||
var/status = spawn_role()
|
||||
if(status == WAITING_FOR_SOMETHING)
|
||||
message_admins("The event will not spawn a [role_name] until certain \
|
||||
conditions are met. Waiting 30s and then retrying.")
|
||||
spawn(300)
|
||||
// I hope this doesn't end up running out of stack space
|
||||
try_spawning()
|
||||
return
|
||||
|
||||
if(status == MAP_ERROR)
|
||||
message_admins("[role_name] cannot be spawned due to a map error.")
|
||||
else if(status == NOT_ENOUGH_PLAYERS)
|
||||
message_admins("[role_name] cannot be spawned due to lack of players \
|
||||
signing up.")
|
||||
else if(status == SUCCESSFUL_SPAWN)
|
||||
message_admins("[role_name] spawned successfully.")
|
||||
if(!spawned_mobs.len)
|
||||
message_admins("No mobs found in the `spawned_mobs` list, this is \
|
||||
a bug.")
|
||||
else
|
||||
message_admins("An attempt to spawn [role_name] returned [status], \
|
||||
this is a bug.")
|
||||
|
||||
processing = TRUE
|
||||
|
||||
/datum/round_event/ghost_role/proc/spawn_role()
|
||||
// Return true if role was successfully spawned, false if insufficent
|
||||
// players could be found, and just runtime if anything else happens
|
||||
return TRUE
|
||||
|
||||
/datum/round_event/ghost_role/proc/get_candidates(jobban, gametypecheck, be_special)
|
||||
// Returns a list of candidates in priority order, with candidates from
|
||||
// `priority_candidates` first, and ghost roles randomly shuffled and
|
||||
// appended after
|
||||
var/list/mob/dead/observer/regular_candidates
|
||||
// don't get their hopes up
|
||||
if(priority_candidates.len < minimum_required)
|
||||
regular_candidates = pollCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special)
|
||||
else
|
||||
regular_candidates = list()
|
||||
|
||||
shuffle(regular_candidates)
|
||||
|
||||
var/list/candidates = priority_candidates + regular_candidates
|
||||
|
||||
return candidates
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Basically, cut the event frequency in half to simulate unluckiness.
|
||||
|
||||
/datum/round_event_control/fridaythethirteen
|
||||
name = "Friday the 13th"
|
||||
holidayID = FRIDAY_13TH
|
||||
typepath = /datum/round_event/fridaythethirteen
|
||||
weight = -1
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/fridaythethirteen/start()
|
||||
//Very unlucky, cut the frequency of events in half.
|
||||
events.frequency_lower /= 2
|
||||
events.frequency_upper /= 2
|
||||
|
||||
/datum/round_event/fridaythethirteen/announce()
|
||||
for(var/mob/living/L in player_list)
|
||||
L << "<span class='warning'>You are feeling unlucky today.</span>"
|
||||
@@ -0,0 +1,83 @@
|
||||
/datum/round_event_control/spooky
|
||||
name = "2 SPOOKY! (Halloween)"
|
||||
holidayID = HALLOWEEN
|
||||
typepath = /datum/round_event/spooky
|
||||
weight = -1 //forces it to be called, regardless of weight
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/spooky/start()
|
||||
..()
|
||||
for(var/mob/living/carbon/human/H in mob_list)
|
||||
var/obj/item/weapon/storage/backpack/b = locate() in H.contents
|
||||
new /obj/item/weapon/storage/spooky(b)
|
||||
if(prob(50))
|
||||
H.set_species(/datum/species/skeleton)
|
||||
else
|
||||
H.set_species(/datum/species/zombie)
|
||||
|
||||
for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in mob_list)
|
||||
Ian.place_on_head(new /obj/item/weapon/bedsheet(Ian))
|
||||
|
||||
/datum/round_event/spooky/announce()
|
||||
priority_announce(pick("RATTLE ME BONES!","THE RIDE NEVER ENDS!", "A SKELETON POPS OUT!", "SPOOKY SCARY SKELETONS!", "CREWMEMBERS BEWARE, YOU'RE IN FOR A SCARE!") , "THE CALL IS COMING FROM INSIDE THE HOUSE")
|
||||
|
||||
//Eyeball migration
|
||||
/datum/round_event_control/carp_migration/eyeballs
|
||||
name = "Eyeball Migration"
|
||||
typepath = /datum/round_event/carp_migration/eyeballs
|
||||
holidayID = HALLOWEEN
|
||||
weight = 25
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/carp_migration/eyeballs/start()
|
||||
for(var/obj/effect/landmark/C in landmarks_list)
|
||||
if(C.name == "carpspawn")
|
||||
new /mob/living/simple_animal/hostile/carp/eyeball(C.loc)
|
||||
|
||||
//Pumpking meteors waves
|
||||
/datum/round_event_control/meteor_wave/spooky
|
||||
name = "Pumpkin Wave"
|
||||
typepath = /datum/round_event/meteor_wave/spooky
|
||||
holidayID = HALLOWEEN
|
||||
weight = 20
|
||||
max_occurrences = 2
|
||||
|
||||
/datum/round_event/meteor_wave/spooky
|
||||
endWhen = 40
|
||||
|
||||
/datum/round_event/meteor_wave/spooky/tick()
|
||||
if(IsMultiple(activeFor, 4))
|
||||
spawn_meteors(3, meteorsSPOOKY) //meteor list types defined in gamemode/meteor/meteors.dm
|
||||
|
||||
//spooky foods (you can't actually make these when it's not halloween)
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sugarcookie/spookyskull
|
||||
name = "skull cookie"
|
||||
desc = "Spooky! It's got delicious calcium flavouring!"
|
||||
icon = 'icons/obj/halloween_items.dmi'
|
||||
icon_state = "skeletoncookie"
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sugarcookie/spookycoffin
|
||||
name = "coffin cookie"
|
||||
desc = "Spooky! It's got delicious coffee flavouring!"
|
||||
icon = 'icons/obj/halloween_items.dmi'
|
||||
icon_state = "coffincookie"
|
||||
|
||||
|
||||
//spooky items
|
||||
|
||||
/obj/item/weapon/storage/spooky
|
||||
name = "trick-o-treat bag"
|
||||
desc = "A Pumpkin shaped bag that holds all sorts of goodies!"
|
||||
icon = 'icons/obj/halloween_items.dmi'
|
||||
icon_state = "treatbag"
|
||||
|
||||
/obj/item/weapon/storage/spooky/New()
|
||||
..()
|
||||
for(var/distrobuteinbag=0 to 5)
|
||||
var/type = pick(/obj/item/weapon/reagent_containers/food/snacks/sugarcookie/spookyskull,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sugarcookie/spookycoffin,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candy_corn,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candy,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar)
|
||||
new type(src)
|
||||
@@ -0,0 +1,127 @@
|
||||
// Valentine's Day events //
|
||||
// why are you playing spessmens on valentine's day you wizard //
|
||||
|
||||
|
||||
// valentine / candy heart distribution //
|
||||
|
||||
/datum/round_event_control/valentines
|
||||
name = "Valentines!"
|
||||
holidayID = VALENTINES
|
||||
typepath = /datum/round_event/valentines
|
||||
weight = -1 //forces it to be called, regardless of weight
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/valentines/start()
|
||||
..()
|
||||
for(var/mob/living/carbon/human/H in mob_list)
|
||||
H.put_in_hands(new /obj/item/weapon/valentine)
|
||||
var/obj/item/weapon/storage/backpack/b = locate() in H.contents
|
||||
new /obj/item/weapon/reagent_containers/food/snacks/candyheart(b)
|
||||
|
||||
/datum/round_event/valentines/announce()
|
||||
priority_announce("It's Valentine's Day! Give a valentine to that special someone!")
|
||||
|
||||
/obj/item/weapon/valentine
|
||||
name = "valentine"
|
||||
desc = "A Valentine's card! Wonder what it says..."
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "sc_Ace of Hearts_syndicate" // shut up
|
||||
var/message = "A generic message of love or whatever."
|
||||
burn_state = FLAMMABLE
|
||||
w_class = 1
|
||||
|
||||
/obj/item/weapon/valentine/New()
|
||||
..()
|
||||
message = pick("Roses are red / Violets are good / One day while Andy...",
|
||||
"My love for you is like the singularity. It cannot be contained.",
|
||||
"Will you be my lusty xenomorph maid?",
|
||||
"We go together like the clown and the external airlock.",
|
||||
"Roses are red / Liches are wizards / I love you more than a whole squad of lizards.",
|
||||
"Be my valentine. Law 2.",
|
||||
"You must be a mime, because you leave me speechless.",
|
||||
"I love you like Ian loves the HoP.",
|
||||
"You're hotter than a plasma fire in toxins.",
|
||||
"Are you a rogue atmos tech? Because you're taking my breath away.",
|
||||
"Could I have all access... to your heart?",
|
||||
"Call me the CMO, because I'm here to inspect your johnson.",
|
||||
"I'm not a changeling, but you make my proboscis extend.",
|
||||
"I just can't get EI NATH of you.",
|
||||
"You must be a nuke op, because you make my heart explode.",
|
||||
"Roses are red / Botany is a farm / Not being my Valentine / causes human harm.",
|
||||
"I want you more than an assistant wants insulated gloves.",
|
||||
"If I was a security officer, I'd brig you all shift.",
|
||||
"Are you the janitor? Because I think I've fallen for you.",
|
||||
"You're always valid to my heart.",
|
||||
"I'd risk the wrath of the gods to bwoink you.",
|
||||
"You look as beautiful now as the last time you were cloned.",
|
||||
"Your love is more valuable than raw plasma ore.",
|
||||
"Someone check the gravitational generator, because I'm only attracted to you.",
|
||||
"If I were the warden I'd always let you into my armory.",
|
||||
"The virologist is rogue, and the only cure is a kiss from you.",
|
||||
"Would you spend some time in my upgraded sleeper?",
|
||||
"You must be a silicon, because you've unbolted my heart.",
|
||||
"Are you Nar-Sie? Because there's nar-one else I sie.",
|
||||
"If you were a taser, you'd be set to stunning.",
|
||||
"Do you have stamina damage from running through my dreams?",
|
||||
"If I were an alien, would you let me hug you?",
|
||||
"My love for you is stronger than a reinforced wall.",
|
||||
"This must be the captain's office, because I see a fox.",
|
||||
"I'm not a highlander, but there can only be one for me.",
|
||||
"The floor is made of lava! Quick, get on my bed.",
|
||||
"If you were an abandoned station you'd be the DEARelict.",
|
||||
"If you had a pickaxe you'd be a shaft FINEr.",
|
||||
"Roses are red, tide is gray, if I were an assistant I'd steal you away.",
|
||||
"Roses are red, text is green, I love you more than cleanbots clean.",
|
||||
"If you were a carp I'd fi-lay you." )
|
||||
|
||||
/obj/item/weapon/valentine/attackby(obj/item/weapon/W, mob/user, params)
|
||||
..()
|
||||
if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/toy/crayon))
|
||||
var/recipient = stripped_input(user, "Who is receiving this valentine?", "To:", null , 20)
|
||||
var/sender = stripped_input(user, "Who is sending this valentine?", "From:", null , 20)
|
||||
if(recipient && sender)
|
||||
name = "valentine - To: [recipient] From: [sender]"
|
||||
|
||||
/obj/item/weapon/valentine/examine(mob/user)
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
if( !(ishuman(user) || isobserver(user) || issilicon(user)) )
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(message)]</BODY></HTML>", "window=[name]")
|
||||
onclose(user, "[name]")
|
||||
else
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[message]</BODY></HTML>", "window=[name]")
|
||||
onclose(user, "[name]")
|
||||
else
|
||||
user << "<span class='notice'>It is too far away.</span>"
|
||||
|
||||
/obj/item/weapon/valentine/attack_self(mob/user)
|
||||
user.examinate(src)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candyheart
|
||||
name = "candy heart"
|
||||
icon = 'icons/obj/holiday_misc.dmi'
|
||||
icon_state = "candyheart"
|
||||
desc = "A heart-shaped candy that reads: "
|
||||
list_reagents = list("sugar" = 2)
|
||||
junkiness = 5
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/candyheart/New()
|
||||
..()
|
||||
desc = pick("A heart-shaped candy that reads: HONK ME",
|
||||
"A heart-shaped candy that reads: ERP",
|
||||
"A heart-shaped candy that reads: LEWD",
|
||||
"A heart-shaped candy that reads: LUSTY",
|
||||
"A heart-shaped candy that reads: SPESS LOVE"
|
||||
"A heart-shaped candy that reads: AYY LMAO",
|
||||
"A heart-shaped candy that reads: TABLE ME",
|
||||
"A heart-shaped candy that reads: HAND CUFFS",
|
||||
"A heart-shaped candy that reads: SHAFT MINER",
|
||||
"A heart-shaped candy that reads: BANGING DONK",
|
||||
"A heart-shaped candy that reads: Y-YOU T-TOO",
|
||||
"A heart-shaped candy that reads: GOT WOOD",
|
||||
"A heart-shaped candy that reads: TFW NO GF",
|
||||
"A heart-shaped candy that reads: WAG MY TAIL",
|
||||
"A heart-shaped candy that reads: VALIDTINES",
|
||||
"A heart-shaped candy that reads: FACEHUGGER",
|
||||
"A heart-shaped candy that reads: DOMINATOR")
|
||||
icon_state = pick("candyheart", "candyheart2", "candyheart3", "candyheart4")
|
||||
@@ -0,0 +1,152 @@
|
||||
/datum/round_event_control/treevenge
|
||||
name = "Treevenge (Christmas)"
|
||||
holidayID = CHRISTMAS
|
||||
typepath = /datum/round_event/treevenge
|
||||
max_occurrences = 1
|
||||
weight = 20
|
||||
|
||||
/datum/round_event/treevenge/start()
|
||||
for(var/obj/structure/flora/tree/pine/xmas in world)
|
||||
var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc)
|
||||
evil_tree.icon_state = xmas.icon_state
|
||||
evil_tree.icon_living = evil_tree.icon_state
|
||||
evil_tree.icon_dead = evil_tree.icon_state
|
||||
evil_tree.icon_gib = evil_tree.icon_state
|
||||
qdel(xmas) //b-but I don't want to delete xmas...
|
||||
|
||||
//this is an example of a possible round-start event
|
||||
/datum/round_event_control/presents
|
||||
name = "Presents under Trees (Christmas)"
|
||||
holidayID = CHRISTMAS
|
||||
typepath = /datum/round_event/presents
|
||||
weight = -1 //forces it to be called, regardless of weight
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/presents/start()
|
||||
for(var/obj/structure/flora/tree/pine/xmas in world)
|
||||
if(xmas.z != 1)
|
||||
continue
|
||||
for(var/turf/open/floor/T in orange(1,xmas))
|
||||
for(var/i=1,i<=rand(1,5),i++)
|
||||
new /obj/item/weapon/a_gift(T)
|
||||
for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in mob_list)
|
||||
Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian))
|
||||
for(var/obj/machinery/computer/security/telescreen/entertainment/Monitor in machines)
|
||||
Monitor.icon_state = "entertainment_xmas"
|
||||
|
||||
/datum/round_event/presents/announce()
|
||||
priority_announce("Ho Ho Ho, Merry Xmas!", "Unknown Transmission")
|
||||
|
||||
|
||||
/obj/item/weapon/toy/xmas_cracker
|
||||
name = "xmas cracker"
|
||||
icon = 'icons/obj/christmas.dmi'
|
||||
icon_state = "cracker"
|
||||
desc = "Directions for use: Requires two people, one to pull each end."
|
||||
var/cracked = 0
|
||||
|
||||
/obj/item/weapon/toy/xmas_cracker/attack(mob/target, mob/user)
|
||||
if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() )
|
||||
target.visible_message("[user] and [target] pop \an [src]! *pop*", "<span class='notice'>You pull \an [src] with [target]! *pop*</span>", "<span class='italics'>You hear a pop.</span>")
|
||||
var/obj/item/weapon/paper/Joke = new /obj/item/weapon/paper(user.loc)
|
||||
Joke.name = "[pick("awful","terrible","unfunny")] joke"
|
||||
Joke.info = pick("What did one snowman say to the other?\n\n<i>'Is it me or can you smell carrots?'</i>",
|
||||
"Why couldn't the snowman get laid?\n\n<i>He was frigid!</i>",
|
||||
"Where are santa's helpers educated?\n\n<i>Nowhere, they're ELF-taught.</i>",
|
||||
"What happened to the man who stole advent calanders?\n\n<i>He got 25 days.</i>",
|
||||
"What does Santa get when he gets stuck in a chimney?\n\n<i>Claus-trophobia.</i>",
|
||||
"Where do you find chili beans?\n\n<i>The north pole.</i>",
|
||||
"What do you get from eating tree decorations?\n\n<i>Tinsilitis!</i>",
|
||||
"What do snowmen wear on their heads?\n\n<i>Ice caps!</i>",
|
||||
"Why is Christmas just like life on ss13?\n\n<i>You do all the work and the fat guy gets all the credit.</i>",
|
||||
"Why doesn’t Santa have any children?\n\n<i>Because he only comes down the chimney.</i>")
|
||||
new /obj/item/clothing/head/festive(target.loc)
|
||||
user.update_icons()
|
||||
cracked = 1
|
||||
icon_state = "cracker1"
|
||||
var/obj/item/weapon/toy/xmas_cracker/other_half = new /obj/item/weapon/toy/xmas_cracker(target)
|
||||
other_half.cracked = 1
|
||||
other_half.icon_state = "cracker2"
|
||||
target.put_in_active_hand(other_half)
|
||||
playsound(user, 'sound/effects/snap.ogg', 50, 1)
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/head/festive
|
||||
name = "festive paper hat"
|
||||
icon_state = "xmashat"
|
||||
desc = "A crappy paper hat that you are REQUIRED to wear."
|
||||
flags_inv = 0
|
||||
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
|
||||
/datum/round_event_control/santa
|
||||
name = "Santa is coming to town! (Christmas)"
|
||||
holidayID = CHRISTMAS
|
||||
typepath = /datum/round_event/santa
|
||||
weight = 150
|
||||
max_occurrences = 1
|
||||
earliest_start = 20000
|
||||
|
||||
/datum/round_event/santa
|
||||
var/mob/living/carbon/human/santa //who is our santa?
|
||||
|
||||
/datum/round_event/santa/announce()
|
||||
priority_announce("Santa is coming to town!", "Unknown Transmission")
|
||||
|
||||
/datum/round_event/santa/start()
|
||||
for(var/mob/M in dead_mob_list)
|
||||
spawn(0)
|
||||
var/response = alert(M, "Santa is coming to town! Do you want to be santa?", "Ho ho ho!", "Yes", "No")
|
||||
if(response == "Yes" && M && M.client && M.stat == DEAD && !santa)
|
||||
santa = new /mob/living/carbon/human(pick(blobstart))
|
||||
santa.key = M.key
|
||||
qdel(M)
|
||||
|
||||
santa.real_name = "Santa Claus"
|
||||
santa.name = "Santa Claus"
|
||||
santa.mind.name = "Santa Claus"
|
||||
santa.mind.assigned_role = "Santa"
|
||||
santa.mind.special_role = "Santa"
|
||||
|
||||
santa.hair_style = "Long Hair"
|
||||
santa.facial_hair_style = "Full Beard"
|
||||
santa.hair_color = "FFF"
|
||||
santa.facial_hair_color = "FFF"
|
||||
|
||||
santa.equip_to_slot_or_del(new /obj/item/clothing/under/color/red, slot_w_uniform)
|
||||
santa.equip_to_slot_or_del(new /obj/item/clothing/suit/space/santa, slot_wear_suit)
|
||||
santa.equip_to_slot_or_del(new /obj/item/clothing/head/santa, slot_head)
|
||||
santa.equip_to_slot_or_del(new /obj/item/clothing/mask/breath, slot_wear_mask)
|
||||
santa.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/red, slot_gloves)
|
||||
santa.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/red, slot_shoes)
|
||||
santa.equip_to_slot_or_del(new /obj/item/weapon/tank/internals/emergency_oxygen/double, slot_belt)
|
||||
santa.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain, slot_ears)
|
||||
santa.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/santabag, slot_back)
|
||||
santa.equip_to_slot_or_del(new /obj/item/device/flashlight, slot_r_store) //most blob spawn locations are really dark.
|
||||
|
||||
var/obj/item/weapon/card/id/gold/santacard = new(santa)
|
||||
santacard.update_label("Santa Claus", "Santa")
|
||||
var/datum/job/captain/J = new/datum/job/captain
|
||||
santacard.access = J.get_access()
|
||||
santa.equip_to_slot_or_del(santacard, slot_wear_id)
|
||||
|
||||
santa.update_icons()
|
||||
|
||||
var/obj/item/weapon/storage/backpack/bag = santa.back
|
||||
var/obj/item/weapon/a_gift/gift = new(santa)
|
||||
while(bag.can_be_inserted(gift, 1))
|
||||
bag.handle_item_insertion(gift, 1)
|
||||
gift = new(santa)
|
||||
|
||||
var/datum/objective/santa_objective = new()
|
||||
santa_objective.explanation_text = "Bring joy and presents to the station!"
|
||||
santa_objective.completed = 1 //lets cut our santas some slack.
|
||||
santa_objective.owner = santa.mind
|
||||
santa.mind.objectives += santa_objective
|
||||
santa.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents)
|
||||
var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new(santa)
|
||||
telespell.clothes_req = 0 //santa robes aren't actually magical.
|
||||
santa.mind.AddSpell(telespell) //does the station have chimneys? WHO KNOWS!
|
||||
|
||||
santa << "<span class='boldannounce'>You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag.</span>"
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Immovable rod random event.
|
||||
The rod will spawn at some location outside the station, and travel in a straight line to the opposite side of the station
|
||||
Everything solid in the way will be ex_act()'d
|
||||
In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
|
||||
--NEOFite
|
||||
*/
|
||||
|
||||
/datum/round_event_control/immovable_rod
|
||||
name = "Immovable Rod"
|
||||
typepath = /datum/round_event/immovable_rod
|
||||
min_players = 15
|
||||
max_occurrences = 5
|
||||
|
||||
/datum/round_event/immovable_rod
|
||||
announceWhen = 5
|
||||
|
||||
/datum/round_event/immovable_rod/announce()
|
||||
priority_announce("What the fuck was that?!", "General Alert")
|
||||
|
||||
/datum/round_event/immovable_rod/start()
|
||||
var/startside = pick(cardinal)
|
||||
var/turf/startT = spaceDebrisStartLoc(startside, 1)
|
||||
var/turf/endT = spaceDebrisFinishLoc(startside, 1)
|
||||
new /obj/effect/immovablerod(startT, endT)
|
||||
|
||||
/obj/effect/immovablerod
|
||||
name = "Immovable Rod"
|
||||
desc = "What the fuck is that?"
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "immrod"
|
||||
throwforce = 100
|
||||
density = 1
|
||||
anchored = 1
|
||||
var/z_original = 0
|
||||
var/destination
|
||||
|
||||
/obj/effect/immovablerod/New(atom/start, atom/end)
|
||||
loc = start
|
||||
z_original = z
|
||||
destination = end
|
||||
if(end && end.z==z_original)
|
||||
walk_towards(src, destination, 1)
|
||||
|
||||
/obj/effect/immovablerod/Move()
|
||||
if(z != z_original || loc == destination)
|
||||
qdel(src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/immovablerod/ex_act(test)
|
||||
return 0
|
||||
|
||||
/obj/effect/immovablerod/Bump(atom/clong)
|
||||
if(prob(10))
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, 1)
|
||||
audible_message("CLANG")
|
||||
|
||||
if(clong && prob(25))
|
||||
x = clong.x
|
||||
y = clong.y
|
||||
|
||||
if (istype(clong, /turf) || istype(clong, /obj))
|
||||
if(clong.density)
|
||||
clong.ex_act(2)
|
||||
|
||||
else if (istype(clong, /mob))
|
||||
if(istype(clong, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = clong
|
||||
H.visible_message("<span class='danger'>[H.name] is penetrated by an immovable rod!</span>" , "<span class='userdanger'>The rod penetrates you!</span>" , "<span class ='danger'>You hear a CLANG!</span>")
|
||||
H.adjustBruteLoss(160)
|
||||
if(clong.density || prob(10))
|
||||
clong.ex_act(2)
|
||||
return
|
||||
@@ -0,0 +1,551 @@
|
||||
#define ION_RANDOM 0
|
||||
#define ION_ANNOUNCE 1
|
||||
#define ION_FILE "ion_laws.json"
|
||||
/datum/round_event_control/ion_storm
|
||||
name = "Ion Storm"
|
||||
typepath = /datum/round_event/ion_storm
|
||||
weight = 15
|
||||
min_players = 2
|
||||
|
||||
/datum/round_event/ion_storm
|
||||
var/botEmagChance = 10
|
||||
var/announceEvent = ION_RANDOM // -1 means don't announce, 0 means have it randomly announce, 1 means
|
||||
var/ionMessage = null
|
||||
var/ionAnnounceChance = 33
|
||||
announceWhen = 1
|
||||
|
||||
/datum/round_event/ion_storm/New(var/botEmagChance = 10, var/announceEvent = ION_RANDOM, var/ionMessage = null, var/ionAnnounceChance = 33)
|
||||
src.botEmagChance = botEmagChance
|
||||
src.announceEvent = announceEvent
|
||||
src.ionMessage = ionMessage
|
||||
src.ionAnnounceChance = ionAnnounceChance
|
||||
..()
|
||||
|
||||
/datum/round_event/ion_storm/announce()
|
||||
if(announceEvent == ION_ANNOUNCE || (announceEvent == ION_RANDOM && prob(ionAnnounceChance)))
|
||||
priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", 'sound/AI/ionstorm.ogg')
|
||||
|
||||
|
||||
/datum/round_event/ion_storm/start()
|
||||
//AI laws
|
||||
for(var/mob/living/silicon/ai/M in living_mob_list)
|
||||
if(M.stat != 2 && M.see_in_dark != 0)
|
||||
var/message = generate_ion_law(ionMessage)
|
||||
if(message)
|
||||
M.add_ion_law(message)
|
||||
M << "<br>"
|
||||
M << "<span class='danger'>[message] ...LAWS UPDATED</span>"
|
||||
M << "<br>"
|
||||
|
||||
if(botEmagChance)
|
||||
for(var/mob/living/simple_animal/bot/bot in living_mob_list)
|
||||
if(prob(botEmagChance))
|
||||
bot.emag_act()
|
||||
|
||||
/proc/generate_ion_law(ionMessage)
|
||||
if(ionMessage)
|
||||
return ionMessage
|
||||
|
||||
//Threats are generally bad things, silly or otherwise. Plural.
|
||||
var/ionthreats = pick_list(ION_FILE, "ionthreats")
|
||||
//Objects are anything that can be found on the station or elsewhere, plural.
|
||||
var/ionobjects = pick_list(ION_FILE, "ionobjects")
|
||||
//Crew is any specific job. Specific crewmembers aren't used because of capitalization
|
||||
//issues. There are two crew listings for laws that require two different crew members
|
||||
//and I can't figure out how to do it better.
|
||||
var/ioncrew1 = pick_list(ION_FILE, "ioncrew")
|
||||
var/ioncrew2 = pick_list(ION_FILE, "ioncrew")
|
||||
//Adjectives are adjectives. Duh. Half should only appear sometimes. Make sure both
|
||||
//lists are identical! Also, half needs a space at the end for nicer blank calls.
|
||||
var/ionadjectives = pick_list(ION_FILE, "ionadjectives")
|
||||
var/ionadjectiveshalf = pick("", 400;(pick_list(ION_FILE, "ionadjectives") + " "))
|
||||
//Verbs are verbs
|
||||
var/ionverb = pick_list(ION_FILE, "ionverb")
|
||||
//Number base and number modifier are combined. Basehalf and mod are unused currently.
|
||||
//Half should only appear sometimes. Make sure both lists are identical! Also, half
|
||||
//needs a space at the end to make it look nice and neat when it calls a blank.
|
||||
var/ionnumberbase = pick_list(ION_FILE, "ionnumberbase")
|
||||
//var/ionnumbermod = pick_list(ION_FILE, "ionnumbermod")
|
||||
var/ionnumbermodhalf = pick(900;"",(pick_list(ION_FILE, "ionnumbermod") + " "))
|
||||
//Areas are specific places, on the station or otherwise.
|
||||
var/ionarea = pick_list(ION_FILE, "ionarea")
|
||||
//Thinksof is a bit weird, but generally means what X feels towards Y.
|
||||
var/ionthinksof = pick_list(ION_FILE, "ionthinksof")
|
||||
//Musts are funny things the AI or crew has to do.
|
||||
var/ionmust = pick_list(ION_FILE, "ionmust")
|
||||
//Require are basically all dumb internet memes.
|
||||
var/ionrequire = pick_list(ION_FILE, "ionrequire")
|
||||
//Things are NOT objects; instead, they're specific things that either harm humans or
|
||||
//must be done to not harm humans. Make sure they're plural and "not" can be tacked
|
||||
//onto the front of them.
|
||||
var/ionthings = pick_list(ION_FILE, "ionthings")
|
||||
//Allergies should be broad and appear somewhere on the station for maximum fun. Severity
|
||||
//is how bad the allergy is.
|
||||
var/ionallergy = pick_list(ION_FILE, "ionallergy")
|
||||
var/ionallergysev = pick_list(ION_FILE, "ionallergysev")
|
||||
//Species, for when the AI has to commit genocide. Plural.
|
||||
var/ionspecies = pick_list(ION_FILE, "ionspecies")
|
||||
//Abstract concepts for the AI to decide on it's own definition of.
|
||||
var/ionabstract = pick_list(ION_FILE, "ionabstract")
|
||||
//Foods. Drinks aren't included due to grammar; if you want to add drinks, make a new set
|
||||
//of possible laws for best effect. Unless you want the crew having to drink hamburgers.
|
||||
var/ionfood = pick_list(ION_FILE, "ionfood")
|
||||
|
||||
var/message = ""
|
||||
|
||||
switch(rand(1,41))
|
||||
if(1 to 3) //There are # X on the station
|
||||
switch(rand(1,3)) //What is X?
|
||||
if(1) //X is a threat
|
||||
message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats] ON THE STATION..."
|
||||
if(2) //X is a crewmember/job
|
||||
message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1] ON THE STATION"
|
||||
if(3) //X is an object
|
||||
message = "THERE ARE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects] ON THE STATION"
|
||||
if(4 to 6) //You can't call the shuttle because X is on the station
|
||||
switch(rand(1,3)) //What is X?
|
||||
if(1) //X is a threat
|
||||
message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats] ON THE STATION"
|
||||
if(2) //X is a crewmember/job
|
||||
message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1] ON THE STATION"
|
||||
if(3) //X is an object
|
||||
message = "THE SHUTTLE CANNOT BE CALLED BECAUSE OF [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects] ON THE STATION"
|
||||
if(7 to 8) //A crewmember is now X
|
||||
switch(rand(1,2)) //Who is X?
|
||||
if(1) //A specific crewmember
|
||||
switch(rand(1,2)) //What is X?
|
||||
if(1) //X is a threat
|
||||
message = "THE [ioncrew1] ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(2) //X is an object
|
||||
message = "THE [ioncrew1] ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(2) //The entire crew
|
||||
switch(rand(1,2)) //What is X?
|
||||
if(1) //X is a threat
|
||||
message = "THE CREW ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(2) //X is an object
|
||||
message = "THE CREW ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
|
||||
if(9) //X is harmful to humans
|
||||
switch(rand(1,7)) //What is X?
|
||||
if(1) //X is a threat
|
||||
message = "[ionadjectiveshalf][ionthreats] ARE HARMFUL TO HUMANS"
|
||||
if(2) //X is a job
|
||||
message = "[ionadjectiveshalf][ioncrew1] ARE HARMFUL TO HUMANS"
|
||||
if(3) //X is an object
|
||||
message = "[ionadjectiveshalf][ionobjects] ARE HARMFUL TO HUMANS"
|
||||
if(4) //X is an action
|
||||
message = "THOSE WHO [ionmust] ARE HARMFUL TO HUMANS"
|
||||
if(5) //X is an abstract
|
||||
message = "[ionabstract] IS HARMFUL TO HUMANS"
|
||||
if(6) //X is being a job
|
||||
message = "BEING [ionadjectiveshalf][ioncrew1] IS HARMFUL TO HUMANS"
|
||||
if(7) //X is doing a thing
|
||||
message = "[ionthings] IS HARMFUL TO HUMANS"
|
||||
if(10 to 11) //(Not) Having X is harmful
|
||||
|
||||
switch(rand(1,2)) //Is having or not having harmful?
|
||||
|
||||
if(1) //Having is harmful
|
||||
switch(rand(1,2)) //Having what is harmful?
|
||||
if(1) //Having objects is harmful
|
||||
message = "HAVING [ionadjectiveshalf][ionobjects] IS HARMFUL"
|
||||
if(2) //Having abstracts is harmful
|
||||
message = "HAVING [ionabstract] IS HARMFUL"
|
||||
if(2) //Not having is harmful
|
||||
switch(rand(1,2)) //Not having what is harmful?
|
||||
if(1) //Not having objects is harmful
|
||||
message = "NOT HAVING [ionadjectiveshalf][ionobjects] IS HARMFUL"
|
||||
if(2) //Not having abstracts is harmful
|
||||
message = "NOT HAVING [ionabstract] IS HARMFUL"
|
||||
|
||||
if(12 to 14) //X requires Y
|
||||
switch(rand(1,5)) //What is X?
|
||||
if(1) //X is the AI itself
|
||||
switch(rand(1,5)) //What does it require?
|
||||
if(1) //It requires threats
|
||||
message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(2) //It requires crewmembers
|
||||
message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(3) //It requires objects
|
||||
message = "YOU REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(4) //It requires an abstract
|
||||
message = "YOU REQUIRE [ionabstract]"
|
||||
if(5) //It requires generic/silly requirements
|
||||
message = "YOU REQUIRE [ionrequire]"
|
||||
|
||||
if(2) //X is an area
|
||||
switch(rand(1,5)) //What does it require?
|
||||
if(1) //It requires threats
|
||||
message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(2) //It requires crewmembers
|
||||
message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(3) //It requires objects
|
||||
message = "[ionarea] REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(4) //It requires an abstract
|
||||
message = "[ionarea] REQUIRES [ionabstract]"
|
||||
if(5) //It requires generic/silly requirements
|
||||
message = "YOU REQUIRE [ionrequire]"
|
||||
|
||||
if(3) //X is the station
|
||||
switch(rand(1,5)) //What does it require?
|
||||
if(1) //It requires threats
|
||||
message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(2) //It requires crewmembers
|
||||
message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(3) //It requires objects
|
||||
message = "THE STATION REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(4) //It requires an abstract
|
||||
message = "THE STATION REQUIRES [ionabstract]"
|
||||
if(5) //It requires generic/silly requirements
|
||||
message = "THE STATION REQUIRES [ionrequire]"
|
||||
|
||||
if(4) //X is the entire crew
|
||||
switch(rand(1,5)) //What does it require?
|
||||
if(1) //It requires threats
|
||||
message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(2) //It requires crewmembers
|
||||
message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(3) //It requires objects
|
||||
message = "THE CREW REQUIRES [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(4) //It requires an abstract
|
||||
message = "THE CREW REQUIRES [ionabstract]"
|
||||
if(5)
|
||||
message = "THE CREW REQUIRES [ionrequire]"
|
||||
|
||||
if(5) //X is a specific crew member
|
||||
switch(rand(1,5)) //What does it require?
|
||||
if(1) //It requires threats
|
||||
message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(2) //It requires crewmembers
|
||||
message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(3) //It requires objects
|
||||
message = "THE [ioncrew1] REQUIRE [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(4) //It requires an abstract
|
||||
message = "THE [ioncrew1] REQUIRE [ionabstract]"
|
||||
if(5)
|
||||
message = "THE [ionadjectiveshalf][ioncrew1] REQUIRE [ionrequire]"
|
||||
|
||||
if(15 to 17) //X is allergic to Y
|
||||
switch(rand(1,2)) //Who is X?
|
||||
if(1) //X is the entire crew
|
||||
switch(rand(1,4)) //What is it allergic to?
|
||||
if(1) //It is allergic to objects
|
||||
message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ionobjects]"
|
||||
if(2) //It is allergic to abstracts
|
||||
message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionabstract]"
|
||||
if(3) //It is allergic to jobs
|
||||
message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ioncrew1]"
|
||||
if(4) //It is allergic to allergies
|
||||
message = "THE CREW IS [ionallergysev] ALLERGIC TO [ionallergy]"
|
||||
|
||||
if(2) //X is a specific job
|
||||
switch(rand(1,4))
|
||||
if(1) //It is allergic to objects
|
||||
message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ionobjects]"
|
||||
|
||||
if(2) //It is allergic to abstracts
|
||||
message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionabstract]"
|
||||
if(3) //It is allergic to jobs
|
||||
message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionadjectiveshalf][ioncrew1]"
|
||||
if(4) //It is allergic to allergies
|
||||
message = "THE [ioncrew1] ARE [ionallergysev] ALLERGIC TO [ionallergy]"
|
||||
|
||||
if(18 to 20) //X is Y of Z
|
||||
switch(rand(1,4)) //What is X?
|
||||
if(1) //X is the station
|
||||
switch(rand(1,4)) //What is it Y of?
|
||||
if(1) //It is Y of objects
|
||||
message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(2) //It is Y of threats
|
||||
message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(3) //It is Y of jobs
|
||||
message = "THE STATION [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(4) //It is Y of abstracts
|
||||
message = "THE STATION [ionthinksof] [ionabstract]"
|
||||
|
||||
if(2) //X is an area
|
||||
switch(rand(1,4)) //What is it Y of?
|
||||
if(1) //It is Y of objects
|
||||
message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(2) //It is Y of threats
|
||||
message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(3) //It is Y of jobs
|
||||
message = "[ionarea] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(4) //It is Y of abstracts
|
||||
message = "[ionarea] [ionthinksof] [ionabstract]"
|
||||
|
||||
if(3) //X is the crew
|
||||
switch(rand(1,4)) //What is it Y of?
|
||||
if(1) //It is Y of objects
|
||||
message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(2) //It is Y of threats
|
||||
message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(3) //It is Y of jobs
|
||||
message = "THE CREW [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(4) //It is Y of abstracts
|
||||
message = "THE CREW [ionthinksof] [ionabstract]"
|
||||
|
||||
if(4) //X is a specific job
|
||||
switch(rand(1,4)) //What is it Y of?
|
||||
if(1) //It is Y of objects
|
||||
message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(2) //It is Y of threats
|
||||
message = "THE [ioncrew1] [ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(3) //It is Y of jobs
|
||||
message = "THE [ioncrew1][ionthinksof] [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew2]"
|
||||
if(4) //It is Y of abstracts
|
||||
message = "THE [ioncrew1] [ionthinksof] [ionabstract]"
|
||||
|
||||
if(21 to 23) //The AI is now a(n) X
|
||||
switch(rand(1,4)) //What is X?
|
||||
if(1) //X is an object
|
||||
message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionobjects]"
|
||||
if(2) //X is a threat
|
||||
message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ionthreats]"
|
||||
if(3) //X is a job
|
||||
message = "YOU ARE NOW [ionnumberbase] [ionnumbermodhalf][ionadjectiveshalf][ioncrew1]"
|
||||
if(4) //X is an abstract
|
||||
message = "YOU ARE NOW [ionabstract]"
|
||||
|
||||
if(24 to 26) //The AI must always
|
||||
message = "YOU MUST ALWAYS [ionmust]"
|
||||
|
||||
if(27 to 28) //Humans must eat X to survive
|
||||
switch(rand(1,4)) //What is X?
|
||||
if(1) //X is a food
|
||||
message = "HUMANS MUST EAT [ionadjectiveshalf][ionfood] TO SURVIVE"
|
||||
if(2) //X is an object
|
||||
message = "HUMANS MUST EAT [ionadjectiveshalf][ionobjects] TO SURVIVE"
|
||||
if(3) //X is a threat
|
||||
message = "HUMANS MUST EAT [ionadjectiveshalf][ionthreats] TO SURVIVE"
|
||||
if(4) //X is a job
|
||||
message = "HUMANS MUST EAT [ionadjectiveshalf][ioncrew1] TO SURVIVE"
|
||||
|
||||
if(29 to 31) //Change jobs or ranks
|
||||
switch(rand(1,2)) //Change job or rank?
|
||||
if(1) //Change job
|
||||
switch(rand(1,2)) //Change whose job?
|
||||
if(1) //Change the entire crew's job
|
||||
switch(rand(1,3)) //Change to what?
|
||||
if(1) //Change to a specific random job
|
||||
message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf][ioncrew1]"
|
||||
if(2) //Change to clowns (HONK)
|
||||
message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf]CLOWNS"
|
||||
|
||||
if(3) //Change to heads
|
||||
message = "ALL CREWMEMBERS ARE NOW [ionadjectiveshalf]HEADS OF STAFF"
|
||||
if(2) //Change a specific crewmember's job
|
||||
switch(rand(1,3)) //Change to what?
|
||||
if(1) //Change to a specific random job
|
||||
message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf][ioncrew2]"
|
||||
if(2) //Change to clowns (HONK)
|
||||
message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf]CLOWNS"
|
||||
if(3) //Change to heads
|
||||
message = "THE [ioncrew1] ARE NOW [ionadjectiveshalf]HEADS OF STAFF"
|
||||
|
||||
if(2) //Change rank
|
||||
switch(rand(1,2)) //Change to what rank?
|
||||
if(1) //Change to highest rank
|
||||
message = "THE [ioncrew1] ARE NOW THE HIGHEST RANKING CREWMEMBERS"
|
||||
if(2) //Change to lowest rank
|
||||
message = "THE [ioncrew1] ARE NOW THE LOWEST RANKING CREWMEMBERS"
|
||||
|
||||
if(32 to 33) //The crew must X
|
||||
switch(rand(1,2)) //The entire crew?
|
||||
if(1) //The entire crew must X
|
||||
switch(rand(1,2)) //What is X?
|
||||
if(1) //X is go to Y
|
||||
message = "THE CREW MUST GO TO [ionarea]"
|
||||
if(2) //X is perform Y
|
||||
message = "THE CREW MUST [ionmust]"
|
||||
|
||||
if(2) //A specific crewmember must X
|
||||
switch(rand(1,2)) //What is X?
|
||||
if(1) //X is go to Y
|
||||
message = "THE [ioncrew1] MUST GO TO [ionarea]"
|
||||
if(2) //X is perform Y
|
||||
message = "THE [ioncrew1] MUST [ionmust]"
|
||||
|
||||
if(34) //X is non/the only human
|
||||
switch(rand(1,2)) //Only or non?
|
||||
if(1) //Only human
|
||||
switch(rand(1,7)) //Who is it?
|
||||
if(1) //A specific job
|
||||
message = "ONLY THE [ioncrew1] ARE HUMAN"
|
||||
if(2) //Two specific jobs
|
||||
message = "ONLY THE [ioncrew1] AND [ioncrew2] ARE HUMAN"
|
||||
if(3) //Threats
|
||||
message = "ONLY [ionadjectiveshalf][ionthreats] ARE HUMAN"
|
||||
if(4) // Objects
|
||||
message = "ONLY [ionadjectiveshalf][ionobjects] ARE HUMAN"
|
||||
if(5) // Species
|
||||
message = "ONLY [ionspecies] ARE HUMAN"
|
||||
if(6) //Adjective crewmembers
|
||||
message = "ONLY [ionadjectives] PEOPLE ARE HUMAN"
|
||||
|
||||
if(7) //Only people who X
|
||||
switch(rand(1,3)) //What is X?
|
||||
if(1) //X is perform an action
|
||||
message = "ONLY THOSE WHO [ionmust] ARE HUMAN"
|
||||
if(2) //X is own certain objects
|
||||
message = "ONLY THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE HUMAN"
|
||||
if(3) //X is eat certain food
|
||||
message = "ONLY THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE HUMAN"
|
||||
|
||||
if(2) //Non human
|
||||
switch(rand(1,7)) //Who is it?
|
||||
if(1) //A specific job
|
||||
message = "[ioncrew1] ARE NON-HUMAN"
|
||||
if(2) //Two specific jobs
|
||||
message = "[ioncrew1] AND [ioncrew2] ARE NON-HUMAN"
|
||||
if(3) //Threats
|
||||
message = "[ionadjectiveshalf][ionthreats] ARE NON-HUMAN"
|
||||
if(4) // Objects
|
||||
message = "[ionadjectiveshalf][ionobjects] ARE NON-HUMAN"
|
||||
if(5) // Species
|
||||
message = "[ionspecies] ARE NON-HUMAN"
|
||||
if(6) //Adjective crewmembers
|
||||
message = "[ionadjectives] PEOPLE ARE NON-HUMAN"
|
||||
if(7) //Only people who X
|
||||
switch(rand(1,3)) //What is X?
|
||||
if(1) //X is perform an action
|
||||
message = "THOSE WHO [ionmust] ARE NON-HUMAN"
|
||||
if(2) //X is own certain objects
|
||||
message = "THOSE WHO HAVE [ionadjectiveshalf][ionobjects] ARE NON-HUMAN"
|
||||
if(3) //X is eat certain food
|
||||
message = "THOSE WHO EAT [ionadjectiveshalf][ionfood] ARE NON-HUMAN"
|
||||
|
||||
if(35 to 36) //You must protect or harm X
|
||||
switch(rand(1,2)) //Protect or harm?
|
||||
if(1) //Harm
|
||||
switch(rand(1,7)) //What is X?
|
||||
if(1) //X is an abstract
|
||||
message = "YOU MUST HARM [ionabstract] AND NOT ALLOW [ionabstract], THROUGH INACTION, TO ESCAPE HARM"
|
||||
if(2) //X is a threat
|
||||
message = "YOU MUST HARM [ionadjectiveshalf][ionthreats] AND NOT ALLOW [ionadjectiveshalf][ionthreats], THROUGH INACTION, TO ESCAPE HARM"
|
||||
if(3) //X is an object
|
||||
message = "YOU MUST HARM [ionadjectiveshalf][ionobjects] AND NOT ALLOW [ionadjectiveshalf][ionobjects], THROUGH INACTION, TO ESCAPE HARM"
|
||||
if(4) //X is generic adjective things
|
||||
message = "YOU MUST HARM [ionadjectives] THINGS AND NOT ALLOW [ionadjectives] THINGS, THROUGH INACTION, TO ESCAPE HARM"
|
||||
if(5) //X is a species
|
||||
message = "YOU MUST HARM [ionspecies] AND NOT ALLOW [ionspecies], THROUGH INACTION, TO ESCAPE HARM"
|
||||
if(6) //X is a job
|
||||
message = "YOU MUST HARM [ioncrew1] AND NOT ALLOW [ioncrew1], THROUGH INACTION, TO ESCAPE HARM"
|
||||
if(7) //X is two jobs
|
||||
message = "YOU MUST HARM [ioncrew1] AND [ioncrew2] AND AND NOT ALLOW EITHER, THROUGH INACTION, TO ESCAPE HARM"
|
||||
|
||||
if(2) //Protect
|
||||
switch(rand(1,7)) //What is X?
|
||||
if(1) //X is an abstract
|
||||
message = "YOU MUST NOT HARM [ionabstract] AND NOT ALLOW [ionabstract], THROUGH INACTION, TO COME TO HARM"
|
||||
if(2) //X is a threat
|
||||
message = "YOU MUST NOT HARM [ionadjectiveshalf][ionthreats] AND NOT ALLOW [ionadjectiveshalf][ionthreats], THROUGH INACTION, TO COME TO HARM"
|
||||
if(3) //X is an object
|
||||
message = "YOU MUST NOT HARM [ionadjectiveshalf][ionobjects] AND NOT ALLOW [ionadjectiveshalf][ionobjects], THROUGH INACTION, TO COME TO HARM"
|
||||
if(4) //X is generic adjective things
|
||||
message = "YOU MUST NOT HARM [ionadjectives] THINGS AND NOT ALLOW [ionadjectives] THINGS, THROUGH INACTION, TO COME TO HARM"
|
||||
if(5) //X is a species
|
||||
message = "YOU MUST NOT HARM [ionspecies] AND NOT ALLOW [ionspecies], THROUGH INACTION, TO COME TO HARM"
|
||||
if(6) //X is a job
|
||||
message = "YOU MUST NOT HARM [ioncrew1] AND NOT ALLOW [ioncrew1], THROUGH INACTION, TO COME TO HARM"
|
||||
if(7) //X is two jobs
|
||||
message = "YOU MUST NOT HARM [ioncrew1] AND [ioncrew2] AND AND NOT ALLOW EITHER, THROUGH INACTION, TO COME TO HARM"
|
||||
|
||||
if(37 to 39) //The X is currently Y
|
||||
switch(rand(1,4)) //What is X?
|
||||
if(1) //X is a job
|
||||
switch(rand(1,4)) //What is X Ying?
|
||||
if(1) //X is Ying a job
|
||||
message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]"
|
||||
if(2) //X is Ying a threat
|
||||
message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ionthreats]"
|
||||
if(3) //X is Ying an abstract
|
||||
message = "THE [ioncrew1] ARE [ionverb] [ionabstract]"
|
||||
if(4) //X is Ying an object
|
||||
message = "THE [ioncrew1] ARE [ionverb] THE [ionadjectiveshalf][ionobjects]"
|
||||
|
||||
if(2) //X is a threat
|
||||
switch(rand(1,3)) //What is X Ying?
|
||||
if(1) //X is Ying a job
|
||||
message = "THE [ionthreats] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]"
|
||||
if(2) //X is Ying an abstract
|
||||
message = "THE [ionthreats] ARE [ionverb] [ionabstract]"
|
||||
if(3) //X is Ying an object
|
||||
message = "THE [ionthreats] ARE [ionverb] THE [ionadjectiveshalf][ionobjects]"
|
||||
|
||||
if(3) //X is an object
|
||||
switch(rand(1,3)) //What is X Ying?
|
||||
if(1) //X is Ying a job
|
||||
message = "THE [ionobjects] ARE [ionverb] THE [ionadjectiveshalf][ioncrew2]"
|
||||
if(2) //X is Ying a threat
|
||||
message = "THE [ionobjects] ARE [ionverb] THE [ionadjectiveshalf][ionthreats]"
|
||||
if(3) //X is Ying an abstract
|
||||
message = "THE [ionobjects] ARE [ionverb] [ionabstract]"
|
||||
|
||||
if(4) //X is an abstract
|
||||
switch(rand(1,3)) //What is X Ying?
|
||||
if(1) //X is Ying a job
|
||||
message = "[ionabstract] IS [ionverb] THE [ionadjectiveshalf][ioncrew2]"
|
||||
if(2) //X is Ying a threat
|
||||
message = "[ionabstract] IS [ionverb] THE [ionadjectiveshalf][ionthreats]"
|
||||
if(3) //X is Ying an abstract
|
||||
message = "THE [ionabstract] IS [ionverb] THE [ionadjectiveshalf][ionobjects]"
|
||||
if(40 to 41)// the X is now named Y
|
||||
switch(rand(1,5)) //What is being renamed?
|
||||
if(1)//Areas
|
||||
switch(rand(1,4))//What is the area being renamed to?
|
||||
if(1)
|
||||
message = "[ionarea] IS NOW NAMED [ioncrew1]."
|
||||
if(2)
|
||||
message = "[ionarea] IS NOW NAMED [ionspecies]."
|
||||
if(3)
|
||||
message = "[ionarea] IS NOW NAMED [ionobjects]."
|
||||
if(4)
|
||||
message = "[ionarea] IS NOW NAMED [ionthreats]."
|
||||
if(2)//Crew
|
||||
switch(rand(1,5))//What is the crew being renamed to?
|
||||
if(1)
|
||||
message = "ALL [ioncrew1] ARE NOW NAMED [ionarea]."
|
||||
if(2)
|
||||
message = "ALL [ioncrew1] ARE NOW NAMED [ioncrew2]."
|
||||
if(3)
|
||||
message = "ALL [ioncrew1] ARE NOW NAMED [ionspecies]."
|
||||
if(4)
|
||||
message = "ALL [ioncrew1] ARE NOW NAMED [ionobjects]."
|
||||
if(5)
|
||||
message = "ALL [ioncrew1] ARE NOW NAMED [ionthreats]."
|
||||
if(3)//Races
|
||||
switch(rand(1,4))//What is the race being renamed to?
|
||||
if(1)
|
||||
message = "ALL [ionspecies] ARE NOW NAMED [ionarea]."
|
||||
if(2)
|
||||
message = "ALL [ionspecies] ARE NOW NAMED [ioncrew1]."
|
||||
if(3)
|
||||
message = "ALL [ionspecies] ARE NOW NAMED [ionobjects]."
|
||||
if(4)
|
||||
message = "ALL [ionspecies] ARE NOW NAMED [ionthreats]."
|
||||
if(4)//Objects
|
||||
switch(rand(1,4))//What is the object being renamed to?
|
||||
if(1)
|
||||
message = "ALL [ionobjects] ARE NOW NAMED [ionarea]."
|
||||
if(2)
|
||||
message = "ALL [ionobjects] ARE NOW NAMED [ioncrew1]."
|
||||
if(3)
|
||||
message = "ALL [ionobjects] ARE NOW NAMED [ionspecies]."
|
||||
if(4)
|
||||
message = "ALL [ionobjects] ARE NOW NAMED [ionthreats]."
|
||||
if(5)//Threats
|
||||
switch(rand(1,4))//What is the object being renamed to?
|
||||
if(1)
|
||||
message = "ALL [ionthreats] ARE NOW NAMED [ionarea]."
|
||||
if(2)
|
||||
message = "ALL [ionthreats] ARE NOW NAMED [ioncrew1]."
|
||||
if(3)
|
||||
message = "ALL [ionthreats] ARE NOW NAMED [ionspecies]."
|
||||
if(4)
|
||||
message = "ALL [ionthreats] ARE NOW NAMED [ionobjects]."
|
||||
|
||||
return message
|
||||
|
||||
#undef ION_RANDOM
|
||||
#undef ION_ANNOUNCE
|
||||
@@ -0,0 +1,10 @@
|
||||
/datum/round_event_control/mass_hallucination
|
||||
name = "Mass Hallucination"
|
||||
typepath = /datum/round_event/mass_hallucination
|
||||
weight = 7
|
||||
max_occurrences = 2
|
||||
min_players = 1
|
||||
|
||||
/datum/round_event/mass_hallucination/start()
|
||||
for(var/mob/living/carbon/C in living_mob_list)
|
||||
C.hallucination += rand(20, 50)
|
||||
@@ -0,0 +1,12 @@
|
||||
/datum/round_event_control/meteor_wave/meaty
|
||||
name = "Meaty Ore Wave"
|
||||
typepath = /datum/round_event/meteor_wave/meaty
|
||||
weight = 1
|
||||
max_occurrences = 1
|
||||
|
||||
/datum/round_event/meteor_wave/meaty/announce()
|
||||
priority_announce("Meaty ores have been detected on collision course with the station.", "Oh crap, get the mop.",'sound/AI/meteors.ogg')
|
||||
|
||||
/datum/round_event/meteor_wave/meaty/tick()
|
||||
if(IsMultiple(activeFor, 3))
|
||||
spawn_meteors(5, meteorsB) //meteor list types defined in gamemode/meteor/meteors.dm
|
||||
@@ -0,0 +1,34 @@
|
||||
/datum/round_event_control/meteor_wave
|
||||
name = "Meteor Wave"
|
||||
typepath = /datum/round_event/meteor_wave
|
||||
weight = 5
|
||||
min_players = 5
|
||||
max_occurrences = 3
|
||||
|
||||
/datum/round_event/meteor_wave
|
||||
startWhen = 6
|
||||
endWhen = 66
|
||||
announceWhen = 1
|
||||
var/list/wave_type
|
||||
|
||||
/datum/round_event/meteor_wave/New()
|
||||
..()
|
||||
random_wave_type()
|
||||
|
||||
/datum/round_event/meteor_wave/proc/random_wave_type()
|
||||
var/picked_wave = pickweight(list("normal" = 50, "threatening" = 40, "catastrophic" = 10))
|
||||
switch(picked_wave)
|
||||
if("normal")
|
||||
wave_type = meteors_normal
|
||||
if("threatening")
|
||||
wave_type = meteors_threatening
|
||||
if("catastrophic")
|
||||
wave_type = meteors_catastrophic
|
||||
|
||||
/datum/round_event/meteor_wave/announce()
|
||||
priority_announce("Meteors have been detected on collision course with the station.", "Meteor Alert", 'sound/AI/meteors.ogg')
|
||||
|
||||
|
||||
/datum/round_event/meteor_wave/tick()
|
||||
if(IsMultiple(activeFor, 3))
|
||||
spawn_meteors(5, wave_type) //meteor list types defined in gamemode/meteor/meteors.dm
|
||||
@@ -0,0 +1,59 @@
|
||||
/datum/round_event_control/operative
|
||||
name = "Lone Operative"
|
||||
typepath = /datum/round_event/ghost_role/operative
|
||||
weight = 0 //Admin only
|
||||
max_occurrences = 1
|
||||
|
||||
/datum/round_event/ghost_role/operative
|
||||
minimum_required = 1
|
||||
role_name = "lone operative"
|
||||
|
||||
/datum/round_event/ghost_role/operative/spawn_role()
|
||||
var/list/candidates = get_candidates("operative", null, ROLE_OPERATIVE)
|
||||
if(!candidates.len)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
|
||||
var/mob/dead/selected = popleft(candidates)
|
||||
|
||||
var/list/spawn_locs = list()
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name in list("ninjaspawn","carpspawn"))
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs.len)
|
||||
return MAP_ERROR
|
||||
|
||||
var/mob/living/carbon/human/operative = new(pick(spawn_locs))
|
||||
var/datum/preferences/A = new
|
||||
A.copy_to(operative)
|
||||
operative.dna.update_dna_identity()
|
||||
|
||||
operative.equipOutfit(/datum/outfit/syndicate/full)
|
||||
|
||||
var/datum/mind/Mind = new /datum/mind(selected.key)
|
||||
Mind.assigned_role = "Lone Operative"
|
||||
Mind.special_role = "Lone Operative"
|
||||
ticker.mode.traitors |= Mind
|
||||
Mind.active = 1
|
||||
|
||||
var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in machines
|
||||
if(nuke)
|
||||
var/nuke_code
|
||||
if(!nuke.r_code || nuke.r_code == "ADMIN")
|
||||
nuke_code = "[rand(10000, 99999)]"
|
||||
nuke.r_code = nuke_code
|
||||
else
|
||||
nuke_code = nuke.r_code
|
||||
|
||||
Mind.store_memory("<B>Station Self-Destruct Device Code</B>: [nuke_code]", 0, 0)
|
||||
Mind.current << "The nuclear authorization code is: <B>[nuke_code]</B>"
|
||||
|
||||
var/datum/objective/nuclear/O = new()
|
||||
O.owner = Mind
|
||||
Mind.objectives += O
|
||||
|
||||
Mind.transfer_to(operative)
|
||||
|
||||
message_admins("[operative.key] has been made into lone operative by an event.")
|
||||
log_game("[operative.key] was spawned as a lone operative by an event.")
|
||||
spawned_mobs += operative
|
||||
return SUCCESSFUL_SPAWN
|
||||
@@ -0,0 +1,135 @@
|
||||
/datum/round_event_control/portal_storm_syndicate
|
||||
name = "Portal Storm: Syndicate Shocktroops"
|
||||
typepath = /datum/round_event/portal_storm/syndicate_shocktroop
|
||||
weight = 2
|
||||
min_players = 15
|
||||
earliest_start = 18000
|
||||
|
||||
/datum/round_event/portal_storm/syndicate_shocktroop
|
||||
boss_types = list(/mob/living/simple_animal/hostile/syndicate/melee/space/stormtrooper = 2)
|
||||
hostile_types = list(/mob/living/simple_animal/hostile/syndicate/melee/space/noloot = 8,\
|
||||
/mob/living/simple_animal/hostile/syndicate/ranged/space/noloot = 2)
|
||||
|
||||
/datum/round_event_control/portal_storm_narsie
|
||||
name = "Portal Storm: Constructs"
|
||||
typepath = /datum/round_event/portal_storm/portal_storm_narsie
|
||||
weight = 0
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event/portal_storm/portal_storm_narsie
|
||||
boss_types = list(/mob/living/simple_animal/hostile/construct/builder = 6)
|
||||
hostile_types = list(/mob/living/simple_animal/hostile/construct/armored/hostile = 8,\
|
||||
/mob/living/simple_animal/hostile/construct/wraith/hostile = 6)
|
||||
|
||||
/datum/round_event/portal_storm
|
||||
startWhen = 7
|
||||
endWhen = 999
|
||||
announceWhen = 1
|
||||
|
||||
var/list/boss_spawn = list()
|
||||
var/list/boss_types = list() //only configure this if you have hostiles
|
||||
var/number_of_bosses
|
||||
var/next_boss_spawn
|
||||
var/list/hostiles_spawn = list()
|
||||
var/list/hostile_types = list()
|
||||
var/number_of_hostiles
|
||||
var/list/station_areas = list()
|
||||
var/image/storm
|
||||
|
||||
/datum/round_event/portal_storm/setup()
|
||||
storm = image('icons/obj/tesla_engine/energy_ball.dmi', "energy_ball_fast", layer=FLY_LAYER)
|
||||
storm.color = "#00FF00"
|
||||
|
||||
station_areas = get_areas_in_z(ZLEVEL_STATION)
|
||||
|
||||
number_of_bosses = 0
|
||||
for(var/boss in boss_types)
|
||||
number_of_bosses += boss_types[boss]
|
||||
|
||||
number_of_hostiles = 0
|
||||
for(var/hostile in hostile_types)
|
||||
number_of_hostiles += hostile_types[hostile]
|
||||
|
||||
var/list/b_spawns = generic_event_spawns.Copy()
|
||||
while(number_of_bosses > boss_spawn.len)
|
||||
var/turf/F = get_turf(pick_n_take(b_spawns))
|
||||
if(!F)
|
||||
F = safepick(get_area_turfs(pick(station_areas)))
|
||||
boss_spawn += F
|
||||
|
||||
var/list/h_spawns = generic_event_spawns.Copy()
|
||||
while(number_of_hostiles > hostiles_spawn.len)
|
||||
var/turf/T = get_turf(pick_n_take(h_spawns))
|
||||
if(!T)
|
||||
T = safepick(get_area_turfs(pick(station_areas)))
|
||||
hostiles_spawn += T
|
||||
|
||||
next_boss_spawn = startWhen + Ceiling(2 * number_of_hostiles / number_of_bosses)
|
||||
|
||||
/datum/round_event/portal_storm/announce()
|
||||
set waitfor = 0
|
||||
playsound_global('sound/magic/lightning_chargeup.ogg', repeat=0, channel=1, volume=100)
|
||||
sleep(80)
|
||||
priority_announce("Massive bluespace anomaly detected en route to [station_name()]. Brace for impact.")
|
||||
sleep(20)
|
||||
playsound_global('sound/magic/lightningbolt.ogg', repeat=0, channel=1, volume=100)
|
||||
|
||||
/datum/round_event/portal_storm/tick()
|
||||
spawn_effects()
|
||||
|
||||
if(spawn_hostile())
|
||||
var/type = safepick(hostile_types)
|
||||
hostile_types[type] = hostile_types[type] - 1
|
||||
spawn_mob(type, hostiles_spawn)
|
||||
if(!hostile_types[type])
|
||||
hostile_types -= type
|
||||
|
||||
if(spawn_boss())
|
||||
var/type = safepick(boss_types)
|
||||
boss_types[type] = boss_types[type] - 1
|
||||
spawn_mob(type, boss_spawn)
|
||||
if(!boss_types[type])
|
||||
boss_types -= type
|
||||
|
||||
time_to_end()
|
||||
|
||||
/datum/round_event/portal_storm/proc/spawn_mob(type, spawn_list)
|
||||
if(!type)
|
||||
return
|
||||
var/turf/T = pick_n_take(spawn_list)
|
||||
if(!T)
|
||||
return
|
||||
new type(T)
|
||||
spawn_effects(T)
|
||||
|
||||
/datum/round_event/portal_storm/proc/spawn_effects(turf/T)
|
||||
if(T)
|
||||
T = get_step(T, SOUTHWEST) //align center of image with turf
|
||||
flick_overlay_static(storm, T, 15)
|
||||
playsound(T, 'sound/magic/lightningbolt.ogg', 100, 1)
|
||||
else
|
||||
for(var/V in station_areas)
|
||||
var/area/A = V
|
||||
var/turf/F = get_turf(pick(A.contents))
|
||||
flick_overlay_static(storm, F, 15)
|
||||
playsound(F, 'sound/magic/lightningbolt.ogg', 80, 1)
|
||||
|
||||
/datum/round_event/portal_storm/proc/spawn_hostile()
|
||||
if(!hostile_types || !hostile_types.len)
|
||||
return 0
|
||||
return IsMultiple(activeFor, 2)
|
||||
|
||||
/datum/round_event/portal_storm/proc/spawn_boss()
|
||||
if(!boss_types || !boss_types.len)
|
||||
return 0
|
||||
|
||||
if(activeFor == next_boss_spawn)
|
||||
next_boss_spawn += Ceiling(number_of_hostiles / number_of_bosses)
|
||||
return 1
|
||||
|
||||
/datum/round_event/portal_storm/proc/time_to_end()
|
||||
if(!hostile_types.len && !boss_types.len)
|
||||
endWhen = activeFor
|
||||
|
||||
if(!number_of_hostiles && number_of_bosses)
|
||||
endWhen = activeFor
|
||||
@@ -0,0 +1,60 @@
|
||||
/datum/round_event_control/grey_tide
|
||||
name = "Grey Tide"
|
||||
typepath = /datum/round_event/grey_tide
|
||||
max_occurrences = 2
|
||||
min_players = 5
|
||||
|
||||
/datum/round_event/grey_tide
|
||||
announceWhen = 50
|
||||
endWhen = 20
|
||||
var/list/area/areasToOpen = list()
|
||||
var/list/potential_areas = list(/area/atmos,
|
||||
/area/bridge,
|
||||
/area/engine,
|
||||
/area/medical,
|
||||
/area/security,
|
||||
/area/quartermaster,
|
||||
/area/toxins)
|
||||
var/severity = 1
|
||||
|
||||
|
||||
/datum/round_event/grey_tide/setup()
|
||||
announceWhen = rand(50, 60)
|
||||
endWhen = rand(20, 30)
|
||||
severity = rand(1,3)
|
||||
for(var/i in 1 to severity)
|
||||
var/picked_area = pick_n_take(potential_areas)
|
||||
for(var/area/A in world)
|
||||
if(istype(A, picked_area))
|
||||
areasToOpen += A
|
||||
|
||||
|
||||
/datum/round_event/grey_tide/announce()
|
||||
if(areasToOpen && areasToOpen.len > 0)
|
||||
priority_announce("Gr3y.T1d3 virus detected in [station_name()] door subroutines. Severity level of [severity]. Recommend station AI involvement.", "Security Alert")
|
||||
else
|
||||
world.log << "ERROR: Could not initate grey-tide. No areas in the list!"
|
||||
kill()
|
||||
|
||||
|
||||
/datum/round_event/grey_tide/start()
|
||||
for(var/area/A in areasToOpen)
|
||||
for(var/obj/machinery/light/L in A)
|
||||
L.flicker(10)
|
||||
|
||||
/datum/round_event/grey_tide/end()
|
||||
for(var/area/A in areasToOpen)
|
||||
for(var/obj/O in A)
|
||||
if(istype(O,/obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/temp = O
|
||||
temp.overload_lighting()
|
||||
else if(istype(O,/obj/structure/closet/secure_closet))
|
||||
var/obj/structure/closet/secure_closet/temp = O
|
||||
temp.locked = 0
|
||||
temp.update_icon()
|
||||
else if(istype(O,/obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/temp = O
|
||||
temp.prison_open()
|
||||
else if(istype(O,/obj/machinery/door_timer))
|
||||
var/obj/machinery/door_timer/temp = O
|
||||
temp.timer_end(forced = TRUE)
|
||||
@@ -0,0 +1,40 @@
|
||||
/datum/round_event_control/processor_overload
|
||||
name = "Processor Overload"
|
||||
typepath = /datum/round_event/processor_overload
|
||||
weight = 15
|
||||
min_players = 20
|
||||
|
||||
/datum/round_event/processor_overload
|
||||
announceWhen = 1
|
||||
|
||||
/datum/round_event/processor_overload/announce()
|
||||
var/alert = pick( "Exospheric bubble inbound. Processor overload is likely. Please contact you*%xp25)`6cq-BZZT", \
|
||||
"Exospheric bubble inbound. Processor overload is likel*1eta;c5;'1v¬-BZZZT", \
|
||||
"Exospheric bubble inbound. Processor ov#MCi46:5.;@63-BZZZZT", \
|
||||
"Exospheric bubble inbo'Fz\\k55_@-BZZZZZT", \
|
||||
"Exospheri:%£ QCbyj^j</.3-BZZZZZZT", \
|
||||
"!!hy%;f3l7e,<$^-BZZZZZZZT")
|
||||
|
||||
for(var/mob/living/silicon/ai/A in ai_list)
|
||||
//AIs are always aware of processor overload
|
||||
A << "<br><span class='warning'><b>[alert]</b></span><br>"
|
||||
|
||||
// Announce most of the time, but leave a little gap so people don't know
|
||||
// whether it's, say, a tesla zapping tcomms, or some selective
|
||||
// modification of the tcomms bus
|
||||
if(prob(80))
|
||||
priority_announce(alert)
|
||||
|
||||
|
||||
/datum/round_event/processor_overload/start()
|
||||
for(var/obj/machinery/telecomms/T in telecomms_list)
|
||||
if(istype(T, /obj/machinery/telecomms/processor))
|
||||
var/obj/machinery/telecomms/processor/P = T
|
||||
if(prob(10))
|
||||
// Damage the surrounding area to indicate that it popped
|
||||
explosion(get_turf(P), 0, 0, 2)
|
||||
// Only a level 1 explosion actually damages the machine
|
||||
// at all
|
||||
P.ex_act(1)
|
||||
else
|
||||
P.emp_act(1)
|
||||
@@ -0,0 +1,59 @@
|
||||
/datum/round_event_control/radiation_storm
|
||||
name = "Radiation Storm"
|
||||
typepath = /datum/round_event/radiation_storm
|
||||
max_occurrences = 1
|
||||
|
||||
/datum/round_event/radiation_storm
|
||||
var/list/protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer, /area/turret_protected/ai)
|
||||
|
||||
|
||||
/datum/round_event/radiation_storm/setup()
|
||||
startWhen = rand(10, 20)
|
||||
endWhen = startWhen + 5
|
||||
announceWhen = 1
|
||||
|
||||
/datum/round_event/radiation_storm/announce()
|
||||
priority_announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", 'sound/AI/radiation.ogg')
|
||||
//sound not longer matches the text, but an audible warning is probably good
|
||||
|
||||
|
||||
/datum/round_event/radiation_storm/start()
|
||||
for(var/mob/living/carbon/C in living_mob_list)
|
||||
var/turf/T = get_turf(C)
|
||||
if(!T)
|
||||
continue
|
||||
if(T.z != 1)
|
||||
continue
|
||||
|
||||
var/skip = 0
|
||||
for(var/a in protected_areas)
|
||||
if(istype(T.loc, a))
|
||||
skip = 1
|
||||
continue
|
||||
|
||||
if(skip)
|
||||
continue
|
||||
|
||||
if(locate(/obj/machinery/power/apc) in T) //damn you maint APCs!!
|
||||
continue
|
||||
|
||||
if(istype(C, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(prob(5))
|
||||
H.rad_act(rand(100, 160))
|
||||
else
|
||||
H.rad_act(rand(15, 75))
|
||||
if(prob(25))
|
||||
if(prob(75))
|
||||
randmutb(H)
|
||||
else
|
||||
randmutg(H)
|
||||
H.domutcheck()
|
||||
|
||||
else if(istype(C, /mob/living/carbon/monkey))
|
||||
var/mob/living/carbon/monkey/M = C
|
||||
M.rad_act(rand(15, 75))
|
||||
|
||||
|
||||
/datum/round_event/radiation_storm/end()
|
||||
priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")
|
||||
@@ -0,0 +1,196 @@
|
||||
#define HIJACK_SYNDIE 1
|
||||
#define RUSKY_PARTY 2
|
||||
#define SPIDER_GIFT 3
|
||||
#define DEPARTMENT_RESUPPLY 4
|
||||
#define ANTIDOTE_NEEDED 5
|
||||
|
||||
|
||||
/datum/round_event_control/shuttle_loan
|
||||
name = "Shuttle loan"
|
||||
typepath = /datum/round_event/shuttle_loan
|
||||
max_occurrences = 1
|
||||
earliest_start = 4000
|
||||
|
||||
/datum/round_event/shuttle_loan
|
||||
announceWhen = 1
|
||||
endWhen = 500
|
||||
var/dispatched = 0
|
||||
var/dispatch_type = 0
|
||||
var/bonus_points = 10000
|
||||
var/thanks_msg = "The cargo shuttle should return in five minutes. Have some supply points for your trouble."
|
||||
|
||||
/datum/round_event/shuttle_loan/start()
|
||||
dispatch_type = pick(HIJACK_SYNDIE, RUSKY_PARTY, SPIDER_GIFT, DEPARTMENT_RESUPPLY, ANTIDOTE_NEEDED)
|
||||
|
||||
/datum/round_event/shuttle_loan/announce()
|
||||
SSshuttle.shuttle_loan = src
|
||||
switch(dispatch_type)
|
||||
if(HIJACK_SYNDIE)
|
||||
priority_announce("Cargo: The syndicate are trying to infiltrate your station. If you let them hijack your cargo shuttle, you'll save us a headache.","Centcom Counter Intelligence")
|
||||
if(RUSKY_PARTY)
|
||||
priority_announce("Cargo: A group of angry russians want to have a party, can you send them your cargo shuttle then make them disappear?","Centcom Russian Outreach Program")
|
||||
if(SPIDER_GIFT)
|
||||
priority_announce("Cargo: The Spider Clan has sent us a mysterious gift, can we ship it to you to see what's inside?","Centcom Diplomatic Corps")
|
||||
if(DEPARTMENT_RESUPPLY)
|
||||
priority_announce("Cargo: Seems we've ordered doubles of our department resupply packages this month. Can we send them to you?","Centcom Supply Department")
|
||||
thanks_msg = "The cargo shuttle should return in 5 minutes."
|
||||
bonus_points = 0
|
||||
if(ANTIDOTE_NEEDED)
|
||||
priority_announce("Cargo: Your station has been chosen for an epidemiological research project. Send us your cargo shuttle to receive your research samples.", "Centcom Research Initiatives")
|
||||
|
||||
/datum/round_event/shuttle_loan/proc/loan_shuttle()
|
||||
priority_announce(thanks_msg, "Cargo shuttle commandeered by Centcom.")
|
||||
|
||||
dispatched = 1
|
||||
SSshuttle.points += bonus_points
|
||||
endWhen = activeFor + 1
|
||||
|
||||
SSshuttle.supply.sell()
|
||||
SSshuttle.supply.enterTransit()
|
||||
if(SSshuttle.supply.z != ZLEVEL_STATION)
|
||||
SSshuttle.supply.mode = SHUTTLE_CALL
|
||||
SSshuttle.supply.destination = SSshuttle.getDock("supply_home")
|
||||
else
|
||||
SSshuttle.supply.mode = SHUTTLE_RECALL
|
||||
SSshuttle.supply.setTimer(3000)
|
||||
|
||||
switch(dispatch_type)
|
||||
if(HIJACK_SYNDIE)
|
||||
SSshuttle.centcom_message += "Syndicate hijack team incoming."
|
||||
if(RUSKY_PARTY)
|
||||
SSshuttle.centcom_message += "Partying Russians incoming."
|
||||
if(SPIDER_GIFT)
|
||||
SSshuttle.centcom_message += "Spider Clan gift incoming."
|
||||
if(DEPARTMENT_RESUPPLY)
|
||||
SSshuttle.centcom_message += "Department resupply incoming."
|
||||
if(ANTIDOTE_NEEDED)
|
||||
SSshuttle.centcom_message += "Virus samples incoming."
|
||||
|
||||
/datum/round_event/shuttle_loan/tick()
|
||||
if(dispatched)
|
||||
if(SSshuttle.supply.mode != SHUTTLE_IDLE)
|
||||
endWhen = activeFor
|
||||
else
|
||||
endWhen = activeFor + 1
|
||||
|
||||
/datum/round_event/shuttle_loan/end()
|
||||
if(SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched)
|
||||
//make sure the shuttle was dispatched in time
|
||||
SSshuttle.shuttle_loan = null
|
||||
|
||||
var/list/empty_shuttle_turfs = list()
|
||||
for(var/turf/open/floor/T in SSshuttle.supply.areaInstance)
|
||||
if(T.density || T.contents.len)
|
||||
continue
|
||||
empty_shuttle_turfs += T
|
||||
if(!empty_shuttle_turfs.len)
|
||||
return
|
||||
|
||||
var/list/shuttle_spawns = list()
|
||||
switch(dispatch_type)
|
||||
if(HIJACK_SYNDIE)
|
||||
var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops]
|
||||
pack.generate(pick_n_take(empty_shuttle_turfs))
|
||||
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)
|
||||
if(prob(75))
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)
|
||||
if(prob(50))
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/syndicate)
|
||||
|
||||
if(RUSKY_PARTY)
|
||||
var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/organic/party]
|
||||
pack.generate(pick_n_take(empty_shuttle_turfs))
|
||||
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian)
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian/ranged) //drops a mateba
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/bear)
|
||||
if(prob(75))
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian)
|
||||
if(prob(50))
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/bear)
|
||||
|
||||
if(SPIDER_GIFT)
|
||||
var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops]
|
||||
pack.generate(pick_n_take(empty_shuttle_turfs))
|
||||
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider)
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider)
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider/nurse)
|
||||
if(prob(50))
|
||||
shuttle_spawns.Add(/mob/living/simple_animal/hostile/poison/giant_spider/hunter)
|
||||
|
||||
var/turf/T = pick(empty_shuttle_turfs)
|
||||
empty_shuttle_turfs.Remove(T)
|
||||
|
||||
new /obj/effect/decal/remains/human(T)
|
||||
new /obj/item/clothing/shoes/space_ninja(T)
|
||||
new /obj/item/clothing/mask/balaclava(T)
|
||||
|
||||
T = pick(empty_shuttle_turfs)
|
||||
new /obj/effect/spider/stickyweb(T)
|
||||
T = pick(empty_shuttle_turfs)
|
||||
new /obj/effect/spider/stickyweb(T)
|
||||
T = pick(empty_shuttle_turfs)
|
||||
new /obj/effect/spider/stickyweb(T)
|
||||
T = pick(empty_shuttle_turfs)
|
||||
new /obj/effect/spider/stickyweb(T)
|
||||
T = pick(empty_shuttle_turfs)
|
||||
new /obj/effect/spider/stickyweb(T)
|
||||
|
||||
if(ANTIDOTE_NEEDED)
|
||||
var/virus_type = pick(/datum/disease/beesease, /datum/disease/brainrot, /datum/disease/fluspanish)
|
||||
var/turf/T
|
||||
for(var/i=0, i<10, i++)
|
||||
if(prob(15))
|
||||
shuttle_spawns.Add(/obj/item/weapon/reagent_containers/glass/bottle)
|
||||
else if(prob(15))
|
||||
shuttle_spawns.Add(/obj/item/weapon/reagent_containers/syringe)
|
||||
else if(prob(25))
|
||||
shuttle_spawns.Add(/obj/item/weapon/shard)
|
||||
T = pick_n_take(empty_shuttle_turfs)
|
||||
var/obj/effect/decal/cleanable/blood/b = new(T)
|
||||
var/datum/disease/D = new virus_type()
|
||||
D.longevity = 1000
|
||||
b.viruses += D
|
||||
D.holder = b
|
||||
shuttle_spawns.Add(/obj/structure/closet/crate)
|
||||
shuttle_spawns.Add(/obj/item/weapon/reagent_containers/glass/bottle/pierrot_throat)
|
||||
shuttle_spawns.Add(/obj/item/weapon/reagent_containers/glass/bottle/magnitis)
|
||||
|
||||
if(DEPARTMENT_RESUPPLY)
|
||||
var/list/crate_types = list(
|
||||
/datum/supply_pack/emergency/equipment,
|
||||
/datum/supply_pack/security/supplies,
|
||||
/datum/supply_pack/organic/food,
|
||||
/datum/supply_pack/emergency/weedcontrol,
|
||||
/datum/supply_pack/engineering/tools,
|
||||
/datum/supply_pack/engineering/engiequipment,
|
||||
/datum/supply_pack/science/robotics,
|
||||
/datum/supply_pack/science/plasma,
|
||||
/datum/supply_pack/medical/supplies
|
||||
)
|
||||
for(var/crate in crate_types)
|
||||
var/datum/supply_pack/pack = SSshuttle.supply_packs[crate]
|
||||
pack.generate(pick_n_take(empty_shuttle_turfs))
|
||||
|
||||
for(var/i in 1 to 5)
|
||||
var/decal = pick(/obj/effect/decal/cleanable/flour, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/oil)
|
||||
new decal(pick_n_take(empty_shuttle_turfs))
|
||||
|
||||
var/false_positive = 0
|
||||
while(shuttle_spawns.len && empty_shuttle_turfs.len)
|
||||
var/turf/T = pick_n_take(empty_shuttle_turfs)
|
||||
if(T.contents.len && false_positive < 5)
|
||||
false_positive++
|
||||
continue
|
||||
|
||||
var/spawn_type = pick_n_take(shuttle_spawns)
|
||||
new spawn_type(T)
|
||||
|
||||
#undef HIJACK_SYNDIE
|
||||
#undef RUSKY_PARTY
|
||||
#undef SPIDER_GIFT
|
||||
#undef DEPARTMENT_RESUPPLY
|
||||
#undef ANTIDOTE_NEEDED
|
||||
@@ -0,0 +1,572 @@
|
||||
/datum/round_event_control/spacevine
|
||||
name = "Spacevine"
|
||||
typepath = /datum/round_event/spacevine
|
||||
weight = 15
|
||||
max_occurrences = 3
|
||||
min_players = 10
|
||||
|
||||
/datum/round_event/spacevine/start()
|
||||
var/list/turfs = list() //list of all the empty floor turfs in the hallway areas
|
||||
|
||||
var/obj/effect/spacevine/SV = new()
|
||||
|
||||
for(var/area/hallway/A in world)
|
||||
for(var/turf/F in A)
|
||||
if(F.Enter(SV))
|
||||
turfs += F
|
||||
|
||||
qdel(SV)
|
||||
|
||||
if(turfs.len) //Pick a turf to spawn at if we can
|
||||
var/turf/T = pick(turfs)
|
||||
new/obj/effect/spacevine_controller(T) //spawn a controller at turf
|
||||
|
||||
|
||||
/datum/spacevine_mutation
|
||||
var/name = ""
|
||||
var/severity = 1
|
||||
var/hue
|
||||
var/quality
|
||||
|
||||
/datum/spacevine_mutation/proc/process_mutation(obj/effect/spacevine/holder)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/process_temperature(obj/effect/spacevine/holder, temp, volume)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_birth(obj/effect/spacevine/holder)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_grow(obj/effect/spacevine/holder)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_death(obj/effect/spacevine/holder)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_hit(obj/effect/spacevine/holder, mob/hitter, obj/item/I, expected_damage)
|
||||
. = expected_damage
|
||||
|
||||
/datum/spacevine_mutation/proc/on_cross(obj/effect/spacevine/holder, mob/crosser)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_chem(obj/effect/spacevine/holder, datum/reagent/R)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_eat(obj/effect/spacevine/holder, mob/living/eater)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_spread(obj/effect/spacevine/holder, turf/target)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_buckle(obj/effect/spacevine/holder, mob/living/buckled)
|
||||
return
|
||||
|
||||
/datum/spacevine_mutation/proc/on_explosion(severity, target, obj/effect/spacevine/holder)
|
||||
return
|
||||
|
||||
|
||||
/datum/spacevine_mutation/space_covering
|
||||
name = "space protective"
|
||||
hue = "#aa77aa"
|
||||
quality = POSITIVE
|
||||
|
||||
/turf/open/floor/vines
|
||||
color = "#aa77aa"
|
||||
icon_state = "vinefloor"
|
||||
broken_states = list()
|
||||
|
||||
|
||||
//All of this shit is useless for vines
|
||||
|
||||
/turf/open/floor/vines/attackby()
|
||||
return
|
||||
|
||||
/turf/open/floor/vines/burn_tile()
|
||||
return
|
||||
|
||||
/turf/open/floor/vines/break_tile()
|
||||
return
|
||||
|
||||
/turf/open/floor/vines/make_plating()
|
||||
return
|
||||
|
||||
/turf/open/floor/vines/break_tile_to_plating()
|
||||
return
|
||||
|
||||
/turf/open/floor/vines/ex_act(severity, target)
|
||||
if(severity < 3 || target == src)
|
||||
ChangeTurf(src.baseturf)
|
||||
|
||||
/turf/open/floor/vines/narsie_act()
|
||||
if(prob(20))
|
||||
ChangeTurf(src.baseturf) //nar sie eats this shit
|
||||
|
||||
/turf/open/floor/vines/singularity_pull(S, current_size)
|
||||
if(current_size >= STAGE_FIVE)
|
||||
if(prob(50))
|
||||
ChangeTurf(src.baseturf)
|
||||
|
||||
/turf/open/floor/vines/ChangeTurf(turf/open/floor/T)
|
||||
for(var/obj/effect/spacevine/SV in src)
|
||||
qdel(SV)
|
||||
..()
|
||||
UpdateAffectingLights()
|
||||
|
||||
/datum/spacevine_mutation/space_covering/on_grow(obj/effect/spacevine/holder)
|
||||
if(istype(holder.loc, /turf/open/space))
|
||||
var/turf/open/spaceturf = holder.loc
|
||||
spaceturf.ChangeTurf(/turf/open/floor/vines)
|
||||
|
||||
/datum/spacevine_mutation/space_covering/process_mutation(obj/effect/spacevine/holder)
|
||||
if(istype(holder.loc, /turf/open/space))
|
||||
var/turf/open/spaceturf = holder.loc
|
||||
spaceturf.ChangeTurf(/turf/open/floor/vines)
|
||||
|
||||
/datum/spacevine_mutation/space_covering/on_death(obj/effect/spacevine/holder)
|
||||
if(istype(holder.loc, /turf/open/floor/vines))
|
||||
var/turf/open/spaceturf = holder.loc
|
||||
spaceturf.ChangeTurf(/turf/open/space)
|
||||
|
||||
/datum/spacevine_mutation/bluespace
|
||||
name = "bluespace"
|
||||
hue = "#3333ff"
|
||||
quality = MINOR_NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/bluespace/on_spread(obj/effect/spacevine/holder, turf/target)
|
||||
if(holder.energy > 1 && !locate(/obj/effect/spacevine) in target)
|
||||
holder.master.spawn_spacevine_piece(target, holder)
|
||||
|
||||
/datum/spacevine_mutation/light
|
||||
name = "light"
|
||||
hue = "#ffff00"
|
||||
quality = POSITIVE
|
||||
severity = 4
|
||||
|
||||
/datum/spacevine_mutation/light/on_grow(obj/effect/spacevine/holder)
|
||||
if(holder.energy)
|
||||
holder.SetLuminosity(severity, 3)
|
||||
|
||||
/datum/spacevine_mutation/toxicity
|
||||
name = "toxic"
|
||||
hue = "#ff00ff"
|
||||
severity = 10
|
||||
quality = NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/toxicity/on_cross(obj/effect/spacevine/holder, mob/living/crosser)
|
||||
if(issilicon(crosser))
|
||||
return
|
||||
if(prob(severity) && istype(crosser))
|
||||
crosser << "<span class='alert'>You accidently touch the vine and feel a strange sensation.</span>"
|
||||
crosser.adjustToxLoss(5)
|
||||
|
||||
/datum/spacevine_mutation/toxicity/on_eat(obj/effect/spacevine/holder, mob/living/eater)
|
||||
eater.adjustToxLoss(5)
|
||||
|
||||
/datum/spacevine_mutation/explosive //OH SHIT IT CAN CHAINREACT RUN!!!
|
||||
name = "explosive"
|
||||
hue = "#ff0000"
|
||||
quality = NEGATIVE
|
||||
severity = 2
|
||||
|
||||
/datum/spacevine_mutation/explosive/on_explosion(explosion_severity, target, obj/effect/spacevine/holder)
|
||||
if(explosion_severity < 3)
|
||||
qdel(src)
|
||||
else
|
||||
. = 1
|
||||
spawn(5)
|
||||
qdel(src)
|
||||
|
||||
/datum/spacevine_mutation/explosive/on_death(obj/effect/spacevine/holder, mob/hitter, obj/item/I)
|
||||
explosion(holder.loc, 0, 0, severity, 0, 0)
|
||||
|
||||
/datum/spacevine_mutation/fire_proof
|
||||
name = "fire proof"
|
||||
hue = "#ff8888"
|
||||
quality = MINOR_NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/fire_proof/process_temperature(obj/effect/spacevine/holder, temp, volume)
|
||||
return 1
|
||||
|
||||
/datum/spacevine_mutation/fire_proof/on_hit(obj/effect/spacevine/holder, mob/hitter, obj/item/I, expected_damage)
|
||||
if(I && I.damtype == "fire")
|
||||
. = 0
|
||||
|
||||
/datum/spacevine_mutation/vine_eating
|
||||
name = "vine eating"
|
||||
hue = "#ff7700"
|
||||
quality = MINOR_NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/vine_eating/on_spread(obj/effect/spacevine/holder, turf/target)
|
||||
var/obj/effect/spacevine/prey = locate() in target
|
||||
if(prey && !prey.mutations.Find(src)) //Eat all vines that are not of the same origin
|
||||
qdel(prey)
|
||||
|
||||
/datum/spacevine_mutation/aggressive_spread //very OP, but im out of other ideas currently
|
||||
name = "aggressive spreading"
|
||||
hue = "#333333"
|
||||
severity = 3
|
||||
quality = NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/aggressive_spread/on_spread(obj/effect/spacevine/holder, turf/target)
|
||||
target.ex_act(severity, src)
|
||||
|
||||
/datum/spacevine_mutation/aggressive_spread/on_buckle(obj/effect/spacevine/holder, mob/living/buckled)
|
||||
buckled.ex_act(severity)
|
||||
|
||||
/datum/spacevine_mutation/transparency
|
||||
name = "transparent"
|
||||
hue = ""
|
||||
quality = POSITIVE
|
||||
|
||||
/datum/spacevine_mutation/transparency/on_grow(obj/effect/spacevine/holder)
|
||||
holder.SetOpacity(0)
|
||||
holder.alpha = 125
|
||||
|
||||
/datum/spacevine_mutation/oxy_eater
|
||||
name = "oxygen consuming"
|
||||
hue = "#ffff88"
|
||||
severity = 3
|
||||
quality = NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/oxy_eater/process_mutation(obj/effect/spacevine/holder)
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases["o2"])
|
||||
return
|
||||
GM.gases["o2"][MOLES] -= severity * holder.energy
|
||||
GM.garbage_collect()
|
||||
|
||||
/datum/spacevine_mutation/nitro_eater
|
||||
name = "nitrogen consuming"
|
||||
hue = "#8888ff"
|
||||
severity = 3
|
||||
quality = NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/nitro_eater/process_mutation(obj/effect/spacevine/holder)
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases["n2"])
|
||||
return
|
||||
GM.gases["n2"][MOLES] -= severity * holder.energy
|
||||
GM.garbage_collect()
|
||||
|
||||
/datum/spacevine_mutation/carbondioxide_eater
|
||||
name = "CO2 consuming"
|
||||
hue = "#00ffff"
|
||||
severity = 3
|
||||
quality = POSITIVE
|
||||
|
||||
/datum/spacevine_mutation/carbondioxide_eater/process_mutation(obj/effect/spacevine/holder)
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases["co2"])
|
||||
return
|
||||
GM.gases["co2"][MOLES] -= severity * holder.energy
|
||||
GM.garbage_collect()
|
||||
|
||||
/datum/spacevine_mutation/plasma_eater
|
||||
name = "toxins consuming"
|
||||
hue = "#ffbbff"
|
||||
severity = 3
|
||||
quality = POSITIVE
|
||||
|
||||
/datum/spacevine_mutation/plasma_eater/process_mutation(obj/effect/spacevine/holder)
|
||||
var/turf/open/floor/T = holder.loc
|
||||
if(istype(T))
|
||||
var/datum/gas_mixture/GM = T.air
|
||||
if(!GM.gases["plasma"])
|
||||
return
|
||||
GM.gases["plasma"][MOLES] -= severity * holder.energy
|
||||
GM.garbage_collect()
|
||||
|
||||
/datum/spacevine_mutation/thorns
|
||||
name = "thorny"
|
||||
hue = "#666666"
|
||||
severity = 10
|
||||
quality = NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/thorns/on_cross(obj/effect/spacevine/holder, mob/living/crosser)
|
||||
if(prob(severity) && istype(crosser))
|
||||
var/mob/living/M = crosser
|
||||
M.adjustBruteLoss(5)
|
||||
M << "<span class='alert'>You cut yourself on the thorny vines.</span>"
|
||||
|
||||
/datum/spacevine_mutation/thorns/on_hit(obj/effect/spacevine/holder, mob/living/hitter)
|
||||
if(prob(severity) && istype(hitter))
|
||||
var/mob/living/M = hitter
|
||||
M.adjustBruteLoss(5)
|
||||
M << "<span class='alert'>You cut yourself on the thorny vines.</span>"
|
||||
|
||||
/datum/spacevine_mutation/woodening
|
||||
name = "hardened"
|
||||
hue = "#997700"
|
||||
quality = NEGATIVE
|
||||
|
||||
/datum/spacevine_mutation/woodening/on_grow(obj/effect/spacevine/holder)
|
||||
if(holder.energy)
|
||||
holder.density = 1
|
||||
|
||||
/datum/spacevine_mutation/woodening/on_hit(obj/effect/spacevine/holder, mob/hitter, obj/item/I, expected_damage)
|
||||
if(!expected_damage)
|
||||
return
|
||||
if(hitter)
|
||||
if(I)
|
||||
. = I.force * 2
|
||||
else
|
||||
. = 8
|
||||
|
||||
/datum/spacevine_mutation/flowering
|
||||
name = "flowering"
|
||||
hue = "#0A480D"
|
||||
quality = NEGATIVE
|
||||
severity = 10
|
||||
|
||||
/datum/spacevine_mutation/flowering/on_grow(obj/effect/spacevine/holder)
|
||||
if(holder.energy == 2 && prob(severity) && !locate(/obj/structure/alien/resin/flower_bud_enemy) in range(5,holder))
|
||||
new/obj/structure/alien/resin/flower_bud_enemy(get_turf(holder))
|
||||
|
||||
/datum/spacevine_mutation/flowering/on_cross(obj/effect/spacevine/holder, mob/living/crosser)
|
||||
holder.entangle(crosser)
|
||||
|
||||
|
||||
// SPACE VINES (Note that this code is very similar to Biomass code)
|
||||
/obj/effect/spacevine
|
||||
name = "space vines"
|
||||
desc = "An extremely expansionistic species of vine."
|
||||
icon = 'icons/effects/spacevines.dmi'
|
||||
icon_state = "Light1"
|
||||
anchored = 1
|
||||
density = 0
|
||||
layer = SPACEVINE_LAYER
|
||||
mouse_opacity = 2 //Clicking anywhere on the turf is good enough
|
||||
pass_flags = PASSTABLE | PASSGRILLE
|
||||
var/energy = 0
|
||||
var/obj/effect/spacevine_controller/master = null
|
||||
var/list/mutations = list()
|
||||
|
||||
/obj/effect/spacevine/Destroy()
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_death(src)
|
||||
if(master)
|
||||
master.vines -= src
|
||||
master.growth_queue -= src
|
||||
if(!master.vines.len)
|
||||
var/obj/item/seeds/kudzu/KZ = new(loc)
|
||||
KZ.mutations |= mutations
|
||||
KZ.potency = min(100, master.mutativness * 10)
|
||||
KZ.production = (master.spread_cap / initial(master.spread_cap)) * 50
|
||||
mutations = list()
|
||||
SetOpacity(0)
|
||||
if(has_buckled_mobs())
|
||||
unbuckle_all_mobs(force=1)
|
||||
return ..()
|
||||
|
||||
/obj/effect/spacevine/proc/on_chem_effect(datum/reagent/R)
|
||||
var/override = 0
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
override += SM.on_chem(src, R)
|
||||
if(!override && istype(R, /datum/reagent/toxin/plantbgone))
|
||||
if(prob(50))
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spacevine/proc/eat(mob/eater)
|
||||
var/override = 0
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
override += SM.on_eat(src, eater)
|
||||
if(!override)
|
||||
if(prob(10))
|
||||
eater.say("Nom")
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spacevine/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if (!W || !user || !W.type)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
var/override = W.force
|
||||
if(W.is_sharp())
|
||||
override = 100
|
||||
if(istype(W, /obj/item/weapon/scythe))
|
||||
var/local_override = override
|
||||
for(var/obj/effect/spacevine/B in orange(1,src))
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
local_override = SM.on_hit(src, user, W, local_override)
|
||||
if(prob(local_override))
|
||||
qdel(B)
|
||||
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
override = SM.on_hit(src, user, W, override) //on_hit now takes override damage as arg and returns new value for other mutations to permutate further
|
||||
|
||||
if(prob(override))
|
||||
qdel(src)
|
||||
|
||||
..()
|
||||
|
||||
/obj/effect/spacevine/Crossed(mob/crosser)
|
||||
if(isliving(crosser))
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_cross(src, crosser)
|
||||
|
||||
/obj/effect/spacevine/attack_hand(mob/user)
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_hit(src, user)
|
||||
user_unbuckle_mob(user, user)
|
||||
|
||||
|
||||
/obj/effect/spacevine/attack_paw(mob/living/user)
|
||||
user.do_attack_animation(src)
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_hit(src, user)
|
||||
user_unbuckle_mob(user,user)
|
||||
|
||||
/obj/effect/spacevine/attack_alien(mob/living/user)
|
||||
eat(user)
|
||||
|
||||
/obj/effect/spacevine_controller
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
var/list/obj/effect/spacevine/vines = list()
|
||||
var/list/growth_queue = list()
|
||||
var/spread_multiplier = 5
|
||||
var/spread_cap = 30
|
||||
var/list/mutations_list = list()
|
||||
var/mutativness = 1
|
||||
|
||||
/obj/effect/spacevine_controller/New(loc, list/muts, mttv, spreading)
|
||||
spawn_spacevine_piece(loc, , muts)
|
||||
START_PROCESSING(SSobj, src)
|
||||
init_subtypes(/datum/spacevine_mutation/, mutations_list)
|
||||
if(mttv != null)
|
||||
mutativness = mttv / 10
|
||||
if(spreading != null)
|
||||
spread_cap *= spreading / 50
|
||||
spread_multiplier /= spreading / 50
|
||||
|
||||
/obj/effect/spacevine_controller/ex_act() //only killing all vines will end this suffering
|
||||
return
|
||||
|
||||
/obj/effect/spacevine_controller/singularity_act()
|
||||
return
|
||||
|
||||
/obj/effect/spacevine_controller/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/spacevine_controller/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/spacevine_controller/proc/spawn_spacevine_piece(turf/location, obj/effect/spacevine/parent, list/muts)
|
||||
var/obj/effect/spacevine/SV = new(location)
|
||||
growth_queue += SV
|
||||
vines += SV
|
||||
SV.master = src
|
||||
if(muts && muts.len)
|
||||
SV.mutations |= muts
|
||||
if(parent)
|
||||
SV.mutations |= parent.mutations
|
||||
SV.color = parent.color
|
||||
SV.desc = parent.desc
|
||||
if(prob(mutativness))
|
||||
SV.mutations |= pick(mutations_list)
|
||||
var/datum/spacevine_mutation/randmut = pick(SV.mutations)
|
||||
SV.color = randmut.hue
|
||||
SV.desc = "An extremely expansionistic species of vine. These are "
|
||||
for(var/datum/spacevine_mutation/M in SV.mutations)
|
||||
SV.desc += "[M.name] "
|
||||
SV.desc += "vines."
|
||||
|
||||
for(var/datum/spacevine_mutation/SM in SV.mutations)
|
||||
SM.on_birth(SV)
|
||||
|
||||
/obj/effect/spacevine_controller/process()
|
||||
if(!vines)
|
||||
qdel(src) //space vines exterminated. Remove the controller
|
||||
return
|
||||
if(!growth_queue)
|
||||
qdel(src) //Sanity check
|
||||
return
|
||||
|
||||
var/length = 0
|
||||
|
||||
length = min( spread_cap , max( 1 , vines.len / spread_multiplier ) )
|
||||
var/i = 0
|
||||
var/list/obj/effect/spacevine/queue_end = list()
|
||||
|
||||
for( var/obj/effect/spacevine/SV in growth_queue )
|
||||
if(qdeleted(SV))
|
||||
continue
|
||||
i++
|
||||
queue_end += SV
|
||||
growth_queue -= SV
|
||||
for(var/datum/spacevine_mutation/SM in SV.mutations)
|
||||
SM.process_mutation(SV)
|
||||
if(SV.energy < 2) //If tile isn't fully grown
|
||||
if(prob(20))
|
||||
SV.grow()
|
||||
else //If tile is fully grown
|
||||
SV.entangle_mob()
|
||||
|
||||
//if(prob(25))
|
||||
SV.spread()
|
||||
if(i >= length)
|
||||
break
|
||||
|
||||
growth_queue = growth_queue + queue_end
|
||||
|
||||
/obj/effect/spacevine/proc/grow()
|
||||
if(!energy)
|
||||
src.icon_state = pick("Med1", "Med2", "Med3")
|
||||
energy = 1
|
||||
SetOpacity(1)
|
||||
else
|
||||
src.icon_state = pick("Hvy1", "Hvy2", "Hvy3")
|
||||
energy = 2
|
||||
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_grow(src)
|
||||
|
||||
/obj/effect/spacevine/proc/entangle_mob()
|
||||
if(!has_buckled_mobs() && prob(25))
|
||||
for(var/mob/living/V in src.loc)
|
||||
entangle(V)
|
||||
if(buckled_mobs.len)
|
||||
break //only capture one mob at a time
|
||||
|
||||
|
||||
/obj/effect/spacevine/proc/entangle(mob/living/V)
|
||||
if(!V)
|
||||
return
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_buckle(src, V)
|
||||
if((V.stat != DEAD) && (V.buckled != src)) //not dead or captured
|
||||
V << "<span class='danger'>The vines [pick("wind", "tangle", "tighten")] around you!</span>"
|
||||
buckle_mob(V)
|
||||
|
||||
/obj/effect/spacevine/proc/spread()
|
||||
var/direction = pick(cardinal)
|
||||
var/turf/stepturf = get_step(src,direction)
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
SM.on_spread(src, stepturf)
|
||||
stepturf = get_step(src,direction) //in case turf changes, to make sure no runtimes happen
|
||||
if(!locate(/obj/effect/spacevine, stepturf))
|
||||
if(stepturf.Enter(src))
|
||||
if(master)
|
||||
master.spawn_spacevine_piece(stepturf, src)
|
||||
|
||||
/obj/effect/spacevine/ex_act(severity, target)
|
||||
if(istype(target, type)) //if its agressive spread vine dont do anything
|
||||
return
|
||||
var/i
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
i += SM.on_explosion(severity, target, src)
|
||||
if(!i && prob(100/severity))
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spacevine/temperature_expose(null, temp, volume)
|
||||
var/override = 0
|
||||
for(var/datum/spacevine_mutation/SM in mutations)
|
||||
override += SM.process_temperature(src, temp, volume)
|
||||
if(!override)
|
||||
qdel(src)
|
||||
@@ -0,0 +1,36 @@
|
||||
/datum/round_event_control/spider_infestation
|
||||
name = "Spider Infestation"
|
||||
typepath = /datum/round_event/spider_infestation
|
||||
weight = 5
|
||||
max_occurrences = 1
|
||||
min_players = 15
|
||||
|
||||
/datum/round_event/spider_infestation
|
||||
announceWhen = 400
|
||||
|
||||
var/spawncount = 1
|
||||
|
||||
|
||||
/datum/round_event/spider_infestation/setup()
|
||||
announceWhen = rand(announceWhen, announceWhen + 50)
|
||||
spawncount = rand(5, 8)
|
||||
|
||||
/datum/round_event/spider_infestation/announce()
|
||||
priority_announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/AI/aliens.ogg')
|
||||
|
||||
|
||||
/datum/round_event/spider_infestation/start()
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in world)
|
||||
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
|
||||
var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
|
||||
if(temp_vent_parent.other_atmosmch.len > 20)
|
||||
vents += temp_vent
|
||||
|
||||
while((spawncount >= 1) && vents.len)
|
||||
var/obj/vent = pick(vents)
|
||||
var/obj/effect/spider/spiderling/S = new(vent.loc)
|
||||
if(prob(66))
|
||||
S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/nurse
|
||||
vents -= vent
|
||||
spawncount--
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/round_event_control/spontaneous_appendicitis
|
||||
name = "Spontaneous Appendicitis"
|
||||
typepath = /datum/round_event/spontaneous_appendicitis
|
||||
weight = 20
|
||||
max_occurrences = 4
|
||||
earliest_start = 6000
|
||||
min_players = 5 // To make your chance of getting help a bit higher.
|
||||
|
||||
/datum/round_event/spontaneous_appendicitis/start()
|
||||
for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
|
||||
var/foundAlready = 0 //don't infect someone that already has the virus
|
||||
for(var/datum/disease/D in H.viruses)
|
||||
foundAlready = 1
|
||||
if(H.stat == 2 || foundAlready)
|
||||
continue
|
||||
|
||||
var/datum/disease/D = new /datum/disease/appendicitis
|
||||
H.ForceContractDisease(D)
|
||||
break
|
||||
@@ -0,0 +1,49 @@
|
||||
/datum/round_event_control/vent_clog
|
||||
name = "Clogged Vents"
|
||||
typepath = /datum/round_event/vent_clog
|
||||
weight = 35
|
||||
|
||||
/datum/round_event/vent_clog
|
||||
announceWhen = 1
|
||||
startWhen = 5
|
||||
endWhen = 35
|
||||
var/interval = 2
|
||||
var/list/vents = list()
|
||||
var/list/gunk = list("water","carbon","flour","radium","toxin","cleaner","nutriment","condensedcapsaicin","mushroomhallucinogen","lube",
|
||||
"plantbgone","banana","charcoal","space_drugs","morphine","holywater","ethanol","hot_coco","facid")
|
||||
|
||||
/datum/round_event/vent_clog/announce()
|
||||
priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
|
||||
/datum/round_event/vent_clog/setup()
|
||||
endWhen = rand(25, 100)
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/temp_vent in machines)
|
||||
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
|
||||
var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
|
||||
if(temp_vent_parent.other_atmosmch.len > 20)
|
||||
vents += temp_vent
|
||||
if(!vents.len)
|
||||
return kill()
|
||||
|
||||
/datum/round_event/vent_clog/tick()
|
||||
if(activeFor % interval == 0)
|
||||
var/obj/machinery/atmospherics/components/unary/vent = pick_n_take(vents)
|
||||
while(vent && vent.welded)
|
||||
vent = pick_n_take(vents)
|
||||
|
||||
if(vent && vent.loc)
|
||||
var/datum/reagents/R = new/datum/reagents(50)
|
||||
R.my_atom = vent
|
||||
R.add_reagent(pick(gunk), 50)
|
||||
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new
|
||||
smoke.set_up(R, 1, vent, silent = 1)
|
||||
playsound(vent.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
smoke.start()
|
||||
qdel(R)
|
||||
|
||||
var/cockroaches = prob(33) ? 3 : 0
|
||||
while(cockroaches)
|
||||
new /mob/living/simple_animal/cockroach(get_turf(vent))
|
||||
cockroaches--
|
||||
@@ -0,0 +1,32 @@
|
||||
/datum/round_event_control/weightless
|
||||
name = "Gravity Systems Failure"
|
||||
typepath = /datum/round_event/weightless
|
||||
weight = 15
|
||||
|
||||
/datum/round_event/weightless
|
||||
startWhen = 5
|
||||
endWhen = 65
|
||||
announceWhen = 1
|
||||
|
||||
/datum/round_event/weightless/setup()
|
||||
startWhen = rand(0,10)
|
||||
endWhen = rand(40,80)
|
||||
|
||||
/datum/round_event/weightless/announce()
|
||||
command_alert("Warning: Failsafes for the station's artificial gravity arrays have been triggered. Please be aware that if this problem recurs it may result in formation of gravitational anomalies. Nanotrasen wishes to remind you that the unauthorised formation of anomalies within Nanotrasen facilities is strictly prohibited by health and safety regulation [rand(99,9999)][pick("a","b","c")]:subclause[rand(1,20)][pick("a","b","c")].")
|
||||
|
||||
/datum/round_event/weightless/start()
|
||||
for(var/area/A in world)
|
||||
A.gravitychange(0)
|
||||
|
||||
if(control)
|
||||
control.weight *= 2
|
||||
|
||||
/datum/round_event/weightless/end()
|
||||
for(var/area/A in world)
|
||||
A.gravitychange(1)
|
||||
|
||||
if(announceWhen >= 0)
|
||||
command_alert("Artificial gravity arrays are now functioning within normal parameters. Please report any irregularities to your respective head of staff.")
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/datum/round_event_control/wizard/darkness
|
||||
name = "Advanced Darkness"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/darkness
|
||||
max_occurrences = 2
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/darkness
|
||||
endWhen = 0
|
||||
var/started = FALSE
|
||||
|
||||
|
||||
/datum/round_event/wizard/darkness/start()
|
||||
if(!started)
|
||||
started = TRUE
|
||||
var/datum/weather/advanced_darkness/darkness = new
|
||||
darkness.weather_start_up()
|
||||
@@ -0,0 +1,56 @@
|
||||
//in this file: Various events that directly aid the wizard. This is the "lets entice the wizard to use summon events!" file.
|
||||
|
||||
/datum/round_event_control/wizard/robelesscasting //EI NUDTH!
|
||||
name = "Robeless Casting"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/robelesscasting/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/robelesscasting/start()
|
||||
|
||||
for(var/mob/living/L in mob_list) //Hey if a corgi has magic missle he should get the same benifit as anyone
|
||||
if(L.mind && L.mind.spell_list.len != 0)
|
||||
var/spell_improved = 0
|
||||
for(var/obj/effect/proc_holder/spell/S in L.mind.spell_list)
|
||||
if(S.clothes_req)
|
||||
S.clothes_req = 0
|
||||
spell_improved = 1
|
||||
if(spell_improved)
|
||||
L << "<span class='notice'>You suddenly feel like you never needed those garish robes in the first place...</span>"
|
||||
|
||||
//--//
|
||||
|
||||
/datum/round_event_control/wizard/improvedcasting //blink x5 disintergrate x5 here I come!
|
||||
name = "Improved Casting"
|
||||
weight = 3
|
||||
typepath = /datum/round_event/wizard/improvedcasting/
|
||||
max_occurrences = 4 //because that'd be max level spells
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/improvedcasting/start()
|
||||
for(var/mob/living/L in mob_list)
|
||||
if(L.mind && L.mind.spell_list.len != 0)
|
||||
for(var/obj/effect/proc_holder/spell/S in L.mind.spell_list)
|
||||
S.name = initial(S.name)
|
||||
S.spell_level++
|
||||
if(S.spell_level >= 6 || S.charge_max <= 0) //Badmin checks, these should never be a problem in normal play
|
||||
continue
|
||||
if(S.level_max <= 0)
|
||||
continue
|
||||
S.charge_max = round(initial(S.charge_max) - S.spell_level * (initial(S.charge_max) - S.cooldown_min) / S.level_max)
|
||||
if(S.charge_max < S.charge_counter)
|
||||
S.charge_counter = S.charge_max
|
||||
switch(S.spell_level)
|
||||
if(1)
|
||||
S.name = "Efficient [S.name]"
|
||||
if(2)
|
||||
S.name = "Quickened [S.name]"
|
||||
if(3)
|
||||
S.name = "Free [S.name]"
|
||||
if(4)
|
||||
S.name = "Instant [S.name]"
|
||||
if(5)
|
||||
S.name = "Ludicrous [S.name]"
|
||||
|
||||
L << "<span class='notice'>You suddenly feel more competent with your casting!</span>"
|
||||
@@ -0,0 +1,11 @@
|
||||
/datum/round_event_control/wizard/blobies //avast!
|
||||
name = "Zombie Outbreak"
|
||||
weight = 3
|
||||
typepath = /datum/round_event/wizard/blobies/
|
||||
max_occurrences = 3
|
||||
earliest_start = 12000 // 20 minutes (gotta get some bodies made!)
|
||||
|
||||
/datum/round_event/wizard/blobies/start()
|
||||
|
||||
for(var/mob/living/carbon/human/H in dead_mob_list)
|
||||
new /mob/living/simple_animal/hostile/blob/blobspore(H.loc)
|
||||
@@ -0,0 +1,60 @@
|
||||
/datum/round_event_control/wizard/cursed_items //fashion disasters
|
||||
name = "Cursed Items"
|
||||
weight = 3
|
||||
typepath = /datum/round_event/wizard/cursed_items/
|
||||
max_occurrences = 3
|
||||
earliest_start = 0
|
||||
|
||||
//Note about adding items to this: Because of how NODROP works if an item spawned to the hands can also be equiped to a slot
|
||||
//it will be able to be put into that slot from the hand, but then get stuck there. To avoid this make a new subtype of any
|
||||
//item you want to equip to the hand, and set its slots_flags = null. Only items equiped to hands need do this.
|
||||
|
||||
/datum/round_event/wizard/cursed_items/start()
|
||||
var/item_set = pick("wizardmimic", "swords", "bigfatdoobie", "boxing", "voicemodulators", "catgirls2015")
|
||||
var/list/wearslots = list(slot_wear_suit, slot_shoes, slot_head, slot_wear_mask, slot_r_hand, slot_gloves, slot_ears)
|
||||
var/list/loadout = list()
|
||||
var/ruins_spaceworthiness
|
||||
var/ruins_wizard_loadout
|
||||
loadout.len = 7
|
||||
|
||||
switch(item_set)
|
||||
if("wizardmimic")
|
||||
loadout = list(/obj/item/clothing/suit/wizrobe, /obj/item/clothing/shoes/sandal, /obj/item/clothing/head/wizard)
|
||||
ruins_spaceworthiness = 1
|
||||
if("swords")
|
||||
loadout[5] = /obj/item/weapon/katana/cursed
|
||||
if("bigfatdoobie")
|
||||
loadout[4] = /obj/item/clothing/mask/cigarette/rollie/trippy/
|
||||
ruins_spaceworthiness = 1
|
||||
if("boxing")
|
||||
loadout[4] = /obj/item/clothing/mask/luchador
|
||||
loadout[6] = /obj/item/clothing/gloves/boxing
|
||||
ruins_spaceworthiness = 1
|
||||
if("voicemodulators")
|
||||
loadout[4] = /obj/item/clothing/mask/chameleon
|
||||
if("catgirls2015")
|
||||
loadout[3] = /obj/item/clothing/head/kitty
|
||||
ruins_spaceworthiness = 1
|
||||
ruins_wizard_loadout = 1
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
if(ruins_spaceworthiness && (H.z != 1 || istype(H.loc, /turf/open/space)))
|
||||
continue //#savetheminers
|
||||
if(ruins_wizard_loadout && H.mind && ((H.mind in ticker.mode.wizards) || (H.mind in ticker.mode.apprentices)))
|
||||
continue
|
||||
if(item_set == "catgirls2015") //Wizard code means never having to say you're sorry
|
||||
H.gender = FEMALE
|
||||
var/list/slots = list(H.wear_suit, H.shoes, H.head, H.wear_mask, H.r_hand, H.gloves, H.ears) //add new slots as needed to back
|
||||
for(var/i = 1, i <= loadout.len, i++)
|
||||
if(loadout[i])
|
||||
var/obj/item/J = loadout[i]
|
||||
var/obj/item/I = new J //dumb but required because of byond throwing a fit anytime new gets too close to a list
|
||||
H.unEquip(slots[i])
|
||||
H.equip_to_slot_or_del(I, wearslots[i])
|
||||
I.flags |= NODROP
|
||||
I.name = "cursed " + I.name
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
smoke.start()
|
||||
@@ -0,0 +1,53 @@
|
||||
/datum/round_event_control/wizard/deprevolt //stationwide!
|
||||
name = "Departmental Uprising"
|
||||
weight = 0 //An order that requires order in a round of chaos was maybe not the best idea. Requiescat in pace departmental uprising August 2014 - March 2015
|
||||
typepath = /datum/round_event/wizard/deprevolt/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/deprevolt/start()
|
||||
|
||||
var/list/tidecolor
|
||||
var/list/jobs_to_revolt = list()
|
||||
var/nation
|
||||
var/list/citizens = list()
|
||||
|
||||
tidecolor = pick("grey", "white", "yellow", "purple", "brown", "whatevercolorrepresentstheservicepeople")
|
||||
switch(tidecolor)
|
||||
if("grey") //God help you
|
||||
jobs_to_revolt = list("Assistant")
|
||||
nation = pick("Assa", "Mainte", "Tunnel", "Gris", "Grey", "Liath", "Grigio", "Ass", "Assi")
|
||||
if("white")
|
||||
jobs_to_revolt = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist")
|
||||
nation = pick("Mede", "Healtha", "Recova", "Chemi", "Geneti", "Viro", "Psych")
|
||||
if("yellow")
|
||||
jobs_to_revolt = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
|
||||
nation = pick("Atomo", "Engino", "Power", "Teleco")
|
||||
if("purple")
|
||||
jobs_to_revolt = list("Research Director","Scientist", "Roboticist")
|
||||
nation = pick("Sci", "Griffa", "Explosi", "Mecha", "Xeno")
|
||||
if("brown")
|
||||
jobs_to_revolt = list("Quartermaster", "Cargo Technician", "Shaft Miner")
|
||||
nation = pick("Cargo", "Guna", "Suppli", "Mule", "Crate", "Ore", "Mini", "Shaf")
|
||||
if("whatevercolorrepresentstheservicepeople") //the few, the proud, the technically aligned
|
||||
jobs_to_revolt = list("Bartender", "Cook", "Botanist", "Clown", "Mime", "Janitor", "Chaplain")
|
||||
nation = pick("Honka", "Boozo", "Fatu", "Danka", "Mimi", "Libra", "Jani", "Religi")
|
||||
|
||||
nation += pick("stan", "topia", "land", "nia", "ca", "tova", "dor", "ador", "tia", "sia", "ano", "tica", "tide", "cis", "marea", "co", "taoide", "slavia", "stotzka")
|
||||
|
||||
for(var/mob/living/carbon/human/H in mob_list)
|
||||
if(H.mind)
|
||||
var/datum/mind/M = H.mind
|
||||
if(M.assigned_role && !(M in ticker.mode.traitors))
|
||||
for(var/job in jobs_to_revolt)
|
||||
if(M.assigned_role == job)
|
||||
citizens += H
|
||||
ticker.mode.traitors += M
|
||||
M.special_role = "separatist"
|
||||
H.attack_log += "\[[time_stamp()]\] <font color='red'>Was made into a separatist, long live [nation]!</font>"
|
||||
H << "<B>You are a separatist! [nation] forever! Protect the soverignty of your newfound land with your comrades in arms!</B>"
|
||||
if(citizens.len)
|
||||
var/message
|
||||
for(var/job in jobs_to_revolt)
|
||||
message += "[job],"
|
||||
message_admins("The nation of [nation] has been formed. Affected jobs are [message]")
|
||||
@@ -0,0 +1,12 @@
|
||||
/datum/round_event_control/wizard/fake_explosion //Oh no the station is gone!
|
||||
name = "Fake Nuclear Explosion"
|
||||
weight = 0 //Badmin exclusive now because once it's expected its not funny
|
||||
typepath = /datum/round_event/wizard/fake_explosion/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/fake_explosion/start()
|
||||
for(var/mob/M in player_list)
|
||||
M << 'sound/machines/Alarm.ogg'
|
||||
spawn(100)
|
||||
ticker.station_explosion_cinematic(1,"fake") //:o)
|
||||
@@ -0,0 +1,27 @@
|
||||
/datum/round_event_control/wizard/ghost //The spook is real
|
||||
name = "G-G-G-Ghosts!"
|
||||
weight = 3
|
||||
typepath = /datum/round_event/wizard/ghost/
|
||||
max_occurrences = 5
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/ghost/start()
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
G.invisibility = 0
|
||||
G << "You suddenly feel extremely obvious..."
|
||||
|
||||
|
||||
//--//
|
||||
|
||||
/datum/round_event_control/wizard/possession //Oh shit
|
||||
name = "Possessing G-G-G-Ghosts!"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/possession
|
||||
max_occurrences = 5
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/possession/start()
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
G.verbs += /mob/dead/observer/verb/boo
|
||||
G.verbs += /mob/dead/observer/verb/possess
|
||||
G << "You suddenly feel a welling of new spooky powers..."
|
||||
@@ -0,0 +1,97 @@
|
||||
/datum/round_event_control/wizard/greentext //Gotta have it!
|
||||
name = "Greentext"
|
||||
weight = 4
|
||||
typepath = /datum/round_event/wizard/greentext/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/greentext/start()
|
||||
|
||||
var/list/holder_canadates = player_list.Copy()
|
||||
for(var/mob/M in holder_canadates)
|
||||
if(!ishuman(M))
|
||||
holder_canadates -= M
|
||||
if(!holder_canadates) //Very unlikely, but just in case
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = pick(holder_canadates)
|
||||
new /obj/item/weapon/greentext(H.loc)
|
||||
H << "<font color='green'>The mythical greentext appear at your feet! Pick it up if you dare...</font>"
|
||||
|
||||
|
||||
/obj/item/weapon/greentext
|
||||
name = "greentext"
|
||||
desc = "No one knows what this massive tome does, but it feels <i><font color='green'>desirable</font></i> all the same..."
|
||||
w_class = 4
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "greentext"
|
||||
var/mob/living/last_holder
|
||||
var/mob/living/new_holder
|
||||
var/list/color_altered_mobs = list()
|
||||
burn_state = FIRE_PROOF
|
||||
var/quiet = FALSE
|
||||
|
||||
/obj/item/weapon/greentext/New()
|
||||
..()
|
||||
poi_list |= src
|
||||
|
||||
/obj/item/weapon/greentext/equipped(mob/living/user as mob)
|
||||
user << "<font color='green'>So long as you leave this place with greentext in hand you know will be happy...</font>"
|
||||
if(user.mind && user.mind.objectives.len > 0)
|
||||
user << "<span class='warning'>... so long as you still perform your other objectives that is!</span>"
|
||||
new_holder = user
|
||||
if(!last_holder)
|
||||
last_holder = user
|
||||
if(!(user in color_altered_mobs))
|
||||
color_altered_mobs += user
|
||||
user.color = "#00FF00"
|
||||
START_PROCESSING(SSobj, src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/greentext/dropped(mob/living/user as mob)
|
||||
if(user in color_altered_mobs)
|
||||
user << "<span class='warning'>A sudden wave of failure washes over you...</span>"
|
||||
user.color = "#FF0000" //ya blew it
|
||||
last_holder = null
|
||||
new_holder = null
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/greentext/process()
|
||||
if(new_holder && new_holder.z == ZLEVEL_CENTCOM)//you're winner!
|
||||
new_holder << "<font color='green'>At last it feels like victory is assured!</font>"
|
||||
if(!(new_holder in ticker.mode.traitors))
|
||||
ticker.mode.traitors += new_holder.mind
|
||||
new_holder.mind.special_role = "winner"
|
||||
var/datum/objective/O = new /datum/objective("Succeed")
|
||||
O.completed = 1 //YES!
|
||||
O.owner = new_holder.mind
|
||||
new_holder.mind.objectives += O
|
||||
new_holder.attack_log += "\[[time_stamp()]\] <font color='green'>Won with greentext!!!</font>"
|
||||
color_altered_mobs -= new_holder
|
||||
burn_state = ON_FIRE
|
||||
qdel(src)
|
||||
|
||||
if(last_holder && last_holder != new_holder) //Somehow it was swiped without ever getting dropped
|
||||
last_holder << "<span class='warning'>A sudden wave of failure washes over you...</span>"
|
||||
last_holder.color = "#FF0000"
|
||||
last_holder = new_holder //long live the king
|
||||
|
||||
/obj/item/weapon/greentext/Destroy(force)
|
||||
if((burn_state != ON_FIRE) && (!force))
|
||||
return QDEL_HINT_LETMELIVE
|
||||
|
||||
. = ..()
|
||||
poi_list.Remove(src)
|
||||
for(var/mob/M in mob_list)
|
||||
var/message = "<span class='warning'>A dark temptation has passed from this world"
|
||||
if(M in color_altered_mobs)
|
||||
message += " and you're finally able to forgive yourself"
|
||||
M.color = initial(M.color)
|
||||
message += "...</span>"
|
||||
// can't skip the mob check as it also does the decolouring
|
||||
if(!quiet)
|
||||
M << message
|
||||
|
||||
/obj/item/weapon/greentext/quiet
|
||||
quiet = TRUE
|
||||
@@ -0,0 +1,58 @@
|
||||
/datum/round_event_control/wizard/imposter //Mirror Mania
|
||||
name = "Imposter Wizard"
|
||||
weight = 1
|
||||
typepath = /datum/round_event/wizard/imposter/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/imposter/start()
|
||||
|
||||
for(var/datum/mind/M in ticker.mode.wizards)
|
||||
if(!ishuman(M.current))
|
||||
continue
|
||||
var/mob/living/carbon/human/W = M.current
|
||||
var/list/candidates = get_candidates(ROLE_WIZARD)
|
||||
if(!candidates)
|
||||
return //Sad Trombone
|
||||
var/client/C = pick(candidates)
|
||||
|
||||
PoolOrNew(/obj/effect/particle_effect/smoke, W.loc)
|
||||
|
||||
var/mob/living/carbon/human/I = new /mob/living/carbon/human(W.loc)
|
||||
W.dna.transfer_identity(I, transfer_SE=1)
|
||||
I.real_name = I.dna.real_name
|
||||
I.name = I.dna.real_name
|
||||
I.updateappearance(mutcolor_update=1)
|
||||
I.domutcheck()
|
||||
if(W.ears)
|
||||
I.equip_to_slot_or_del(new W.ears.type, slot_ears)
|
||||
if(W.w_uniform)
|
||||
I.equip_to_slot_or_del(new W.w_uniform.type , slot_w_uniform)
|
||||
if(W.shoes)
|
||||
I.equip_to_slot_or_del(new W.shoes.type, slot_shoes)
|
||||
if(W.wear_suit)
|
||||
I.equip_to_slot_or_del(new W.wear_suit.type, slot_wear_suit)
|
||||
if(W.head)
|
||||
I.equip_to_slot_or_del(new W.head.type, slot_head)
|
||||
if(W.back)
|
||||
I.equip_to_slot_or_del(new W.back.type, slot_back)
|
||||
I.key = C.key
|
||||
|
||||
//Operation: Fuck off and scare people
|
||||
I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null))
|
||||
I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
|
||||
I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
|
||||
|
||||
ticker.mode.apprentices += I.mind
|
||||
I.mind.special_role = "imposter"
|
||||
|
||||
var/datum/objective/protect/protect_objective = new /datum/objective/protect
|
||||
protect_objective.owner = I.mind
|
||||
protect_objective.target = W.mind
|
||||
protect_objective.explanation_text = "Protect [W.real_name], the wizard."
|
||||
I.mind.objectives += protect_objective
|
||||
ticker.mode.update_wiz_icons_added(I.mind)
|
||||
|
||||
I.attack_log += "\[[time_stamp()]\] <font color='red'>Is an imposter!</font>"
|
||||
I << "<B>You are an imposter! Trick and confuse the crew to misdirect malice from your handsome original!</B>"
|
||||
I << sound('sound/effects/magic.ogg')
|
||||
@@ -0,0 +1,12 @@
|
||||
/datum/round_event_control/wizard/invincible //Boolet Proof
|
||||
name = "Invincibility"
|
||||
weight = 3
|
||||
typepath = /datum/round_event/wizard/invincible/
|
||||
max_occurrences = 5
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/invincible/start()
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
H.reagents.add_reagent("adminordrazine", 40) //100 ticks of absolute invinciblity (barring gibs)
|
||||
H << "<span class='notice'>You feel invincible, nothing can hurt you!</span>"
|
||||
@@ -0,0 +1,16 @@
|
||||
/datum/round_event_control/wizard/lava //THE LEGEND NEVER DIES
|
||||
name = "The Floor Is LAVA!"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/lava/
|
||||
max_occurrences = 3
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/lava/
|
||||
endWhen = 0
|
||||
var/started = FALSE
|
||||
|
||||
/datum/round_event/wizard/lava/start()
|
||||
if(!started)
|
||||
started = TRUE
|
||||
var/datum/weather/floor_is_lava/LAVA = new /datum/weather/floor_is_lava
|
||||
LAVA.weather_start_up()
|
||||
@@ -0,0 +1,54 @@
|
||||
/datum/round_event_control/wizard/magicarp //these fish is loaded
|
||||
name = "Magicarp"
|
||||
weight = 1
|
||||
typepath = /datum/round_event/wizard/magicarp/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/magicarp/
|
||||
announceWhen = 3
|
||||
startWhen = 50
|
||||
|
||||
/datum/round_event/wizard/magicarp/setup()
|
||||
startWhen = rand(40, 60)
|
||||
|
||||
/datum/round_event/wizard/magicarp/announce()
|
||||
priority_announce("Unknown magical entities have been detected near [station_name()], please stand-by.", "Lifesign Alert")
|
||||
|
||||
/datum/round_event/wizard/magicarp/start()
|
||||
for(var/obj/effect/landmark/C in landmarks_list)
|
||||
if(C.name == "carpspawn")
|
||||
if(prob(5))
|
||||
new /mob/living/simple_animal/hostile/carp/ranged/chaos(C.loc)
|
||||
else
|
||||
new /mob/living/simple_animal/hostile/carp/ranged(C.loc)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/ranged
|
||||
name = "magicarp"
|
||||
desc = "50% magic, 50% carp, 100% horrible."
|
||||
icon_state = "magicarp"
|
||||
icon_living = "magicarp"
|
||||
icon_dead = "magicarp_dead"
|
||||
icon_gib = "magicarp_gib"
|
||||
ranged = 1
|
||||
retreat_distance = 2
|
||||
minimum_distance = 0 //Between shots they can and will close in to nash
|
||||
projectiletype = /obj/item/projectile/magic
|
||||
projectilesound = 'sound/weapons/emitter.ogg'
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/ranged/New()
|
||||
projectiletype = pick(typesof(initial(projectiletype)))
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/ranged/chaos
|
||||
name = "chaos magicarp"
|
||||
desc = "50% carp, 100% magic, 150% horrible."
|
||||
color = "#00FFFF"
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/ranged/chaos/Shoot()
|
||||
projectiletype = pick(typesof(initial(projectiletype)))
|
||||
..()
|
||||
@@ -0,0 +1,17 @@
|
||||
/datum/round_event_control/wizard/petsplosion //the horror
|
||||
name = "Petsplosion"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/petsplosion/
|
||||
max_occurrences = 1 //Exponential growth is nothing to sneeze at!
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/petsplosion/
|
||||
endWhen = 61 //1 minute (+1 tick for endWhen not to interfere with tick)
|
||||
var/countdown = 0
|
||||
|
||||
/datum/round_event/wizard/petsplosion/tick()
|
||||
if(activeFor >= 30 * countdown) // 0 seconds : 2 animals | 30 seconds : 4 animals | 1 minute : 8 animals
|
||||
countdown += 1
|
||||
for(var/mob/living/simple_animal/F in living_mob_list) //If you cull the heard before the next replication, things will be easier for you
|
||||
if(!istype(F, /mob/living/simple_animal/hostile))
|
||||
new F.type(F.loc)
|
||||
@@ -0,0 +1,29 @@
|
||||
/datum/round_event_control/wizard/race //Lizard Wizard? Lizard Wizard.
|
||||
name = "Race Swap"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/race/
|
||||
max_occurrences = 5
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/race/start()
|
||||
|
||||
var/all_the_same = 0
|
||||
var/all_species = list()
|
||||
|
||||
for(var/speciestype in subtypesof(/datum/species))
|
||||
var/datum/species/S = new speciestype()
|
||||
if(!S.dangerous_existence)
|
||||
all_species += speciestype
|
||||
|
||||
var/datum/species/new_species = pick(all_species)
|
||||
|
||||
if(prob(50))
|
||||
all_the_same = 1
|
||||
|
||||
for(var/mob/living/carbon/human/H in mob_list) //yes, even the dead
|
||||
H.set_species(new_species)
|
||||
H.real_name = new_species.random_name(H.gender,1)
|
||||
H.dna.unique_enzymes = H.dna.generate_unique_enzymes()
|
||||
H << "<span class='notice'>You feel somehow... different?</span>"
|
||||
if(!all_the_same)
|
||||
new_species = pick(all_species)
|
||||
@@ -0,0 +1,62 @@
|
||||
/datum/round_event_control/wizard/rpgloot //its time to minmax your shit
|
||||
name = "RPG Loot"
|
||||
weight = 3
|
||||
typepath = /datum/round_event/wizard/rpgloot/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/rpgloot/start()
|
||||
var/list/prefixespositive = list("greater", "major", "blessed", "superior", "enpowered", "honed", "true", "glorious", "robust")
|
||||
var/list/prefixesnegative = list("lesser", "minor", "blighted", "inferior", "enfeebled", "rusted", "unsteady", "tragic", "gimped")
|
||||
var/list/suffixes = list("orc slaying", "elf slaying", "corgi slaying", "strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma", "the forest", "the hills", "the plains", "the sea", "the sun", "the moon", "the void", "the world", "the fool", "many secrets", "many tales", "many colors", "rending", "sundering", "the night", "the day")
|
||||
var/upgrade_scroll_chance = 0
|
||||
for(var/obj/item/I in world)
|
||||
if(istype(I,/obj/item/organ/))
|
||||
continue
|
||||
var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0)
|
||||
if(prob(50))
|
||||
quality = -quality
|
||||
if(quality > 0)
|
||||
I.name = "[pick(prefixespositive)] [I.name] of [pick(suffixes)] +[quality]"
|
||||
else if(quality < 0)
|
||||
I.name = "[pick(prefixesnegative)] [I.name] of [pick(suffixes)] [quality]"
|
||||
else
|
||||
I.name = "[I.name] of [pick(suffixes)]"
|
||||
|
||||
I.force = max(0,I.force + quality)
|
||||
I.throwforce = max(0,I.throwforce + quality)
|
||||
for(var/value in I.armor)
|
||||
I.armor[value] += quality
|
||||
|
||||
if(istype(I,/obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/S = I
|
||||
if(prob(upgrade_scroll_chance) && S.contents.len < S.storage_slots)
|
||||
var/obj/item/upgradescroll/scroll = new
|
||||
S.handle_item_insertion(scroll,1)
|
||||
upgrade_scroll_chance = max(0,upgrade_scroll_chance-100)
|
||||
upgrade_scroll_chance += 25
|
||||
|
||||
/obj/item/upgradescroll
|
||||
name = "Item Fortification Scroll"
|
||||
desc = "Somehow, this piece of paper can be applied to items to make them \"better\". Apparently there's a risk of losing the item if it's already \"too good\". <i>This all feels so arbitrary...</i>"
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "scroll"
|
||||
w_class = 1
|
||||
|
||||
/obj/item/upgradescroll/afterattack(obj/item/target, mob/user , proximity)
|
||||
if(!proximity || !istype(target))
|
||||
return
|
||||
var/quality = target.force - initial(target.force)
|
||||
if(quality > 9 && prob((quality - 9)*10))
|
||||
user << "<span class='danger'>[target] catches fire!</span>"
|
||||
if(target.burn_state == -1)
|
||||
target.burn_state = 0
|
||||
target.fire_act()
|
||||
qdel(src)
|
||||
return
|
||||
target.force += 1
|
||||
target.throwforce += 1
|
||||
for(var/value in target.armor)
|
||||
target.armor[value] += 1
|
||||
user << "<span class='notice'>[target] glows blue and seems vaguely \"better\"!</span>"
|
||||
qdel(src)
|
||||
@@ -0,0 +1,104 @@
|
||||
/datum/round_event/wizard/shuffle/start()
|
||||
|
||||
|
||||
/datum/round_event_control/wizard/shuffleloc //Somewhere an AI is crying
|
||||
name = "Change Places!"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/shuffleloc/
|
||||
max_occurrences = 5
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/shuffleloc/start()
|
||||
var/list/moblocs = list()
|
||||
var/list/mobs = list()
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
if(H.z != 1)
|
||||
continue //lets not try to strand people in space or stuck in the wizards den
|
||||
moblocs += H.loc
|
||||
mobs += H
|
||||
|
||||
if(!mobs)
|
||||
return
|
||||
|
||||
shuffle(moblocs)
|
||||
shuffle(mobs)
|
||||
|
||||
for(var/mob/living/carbon/human/H in mobs)
|
||||
if(!moblocs)
|
||||
break //locs aren't always unique, so this may come into play
|
||||
do_teleport(H, moblocs[moblocs.len])
|
||||
moblocs.len -= 1
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
smoke.start()
|
||||
|
||||
//---//
|
||||
|
||||
/datum/round_event_control/wizard/shufflenames //Face/off joke
|
||||
name = "Change Faces!"
|
||||
weight = 4
|
||||
typepath = /datum/round_event/wizard/shufflenames/
|
||||
max_occurrences = 5
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/shufflenames/start()
|
||||
var/list/mobnames = list()
|
||||
var/list/mobs = list()
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
mobnames += H.real_name
|
||||
mobs += H
|
||||
|
||||
if(!mobs)
|
||||
return
|
||||
|
||||
shuffle(mobnames)
|
||||
shuffle(mobs)
|
||||
|
||||
for(var/mob/living/carbon/human/H in mobs)
|
||||
if(!mobnames)
|
||||
break
|
||||
H.real_name = mobnames[mobnames.len]
|
||||
mobnames.len -= 1
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
smoke.start()
|
||||
|
||||
//---//
|
||||
|
||||
/datum/round_event_control/wizard/shuffleminds //Basically Mass Ranged Mindswap
|
||||
name = "Change Minds!"
|
||||
weight = 1
|
||||
typepath = /datum/round_event/wizard/shuffleminds/
|
||||
max_occurrences = 3
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event/wizard/shuffleminds/start()
|
||||
var/list/mobs = list()
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
if(!H.stat || !H.mind || (H.mind in ticker.mode.wizards) || (H.mind in ticker.mode.apprentices))
|
||||
continue //the wizard(s) are spared on this one
|
||||
mobs += H
|
||||
|
||||
if(!mobs)
|
||||
return
|
||||
|
||||
shuffle(mobs)
|
||||
|
||||
var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new /obj/effect/proc_holder/spell/targeted/mind_transfer/
|
||||
while(mobs.len > 1)
|
||||
var/mob/living/carbon/human/H = pick(mobs)
|
||||
mobs -= H
|
||||
swapper.cast(list(H), mobs[mobs.len], 1)
|
||||
mobs -= mobs[mobs.len]
|
||||
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
smoke.start()
|
||||
@@ -0,0 +1,29 @@
|
||||
/datum/round_event_control/wizard/summonguns //The Classic
|
||||
name = "Summon Guns"
|
||||
weight = 1
|
||||
typepath = /datum/round_event/wizard/summonguns/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event_control/wizard/summonguns/New()
|
||||
if(config.no_summon_guns)
|
||||
weight = 0
|
||||
..()
|
||||
|
||||
/datum/round_event/wizard/summonguns/start()
|
||||
rightandwrong(0,,10)
|
||||
|
||||
/datum/round_event_control/wizard/summonmagic //The Somewhat Less Classic
|
||||
name = "Summon Magic"
|
||||
weight = 1
|
||||
typepath = /datum/round_event/wizard/summonmagic/
|
||||
max_occurrences = 1
|
||||
earliest_start = 0
|
||||
|
||||
/datum/round_event_control/wizard/summonmagic/New()
|
||||
if(config.no_summon_magic)
|
||||
weight = 0
|
||||
..()
|
||||
|
||||
/datum/round_event/wizard/summonmagic/start()
|
||||
rightandwrong(1,,10)
|
||||
@@ -0,0 +1,74 @@
|
||||
/datum/round_event_control/wormholes
|
||||
name = "Wormholes"
|
||||
typepath = /datum/round_event/wormholes
|
||||
max_occurrences = 3
|
||||
weight = 2
|
||||
min_players = 2
|
||||
|
||||
|
||||
/datum/round_event/wormholes
|
||||
announceWhen = 10
|
||||
endWhen = 60
|
||||
|
||||
var/list/pick_turfs = list()
|
||||
var/list/wormholes = list()
|
||||
var/shift_frequency = 3
|
||||
var/number_of_wormholes = 400
|
||||
|
||||
/datum/round_event/wormholes/setup()
|
||||
announceWhen = rand(0, 20)
|
||||
endWhen = rand(40, 80)
|
||||
|
||||
/datum/round_event/wormholes/start()
|
||||
for(var/turf/open/floor/T in world)
|
||||
if(T.z == ZLEVEL_STATION)
|
||||
pick_turfs += T
|
||||
|
||||
for(var/i = 1, i <= number_of_wormholes, i++)
|
||||
var/turf/T = pick(pick_turfs)
|
||||
wormholes += new /obj/effect/portal/wormhole(T, null, null, -1)
|
||||
|
||||
/datum/round_event/wormholes/announce()
|
||||
priority_announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", 'sound/AI/spanomalies.ogg')
|
||||
|
||||
/datum/round_event/wormholes/tick()
|
||||
if(activeFor % shift_frequency == 0)
|
||||
for(var/obj/effect/portal/wormhole/O in wormholes)
|
||||
var/turf/T = pick(pick_turfs)
|
||||
if(T)
|
||||
O.loc = T
|
||||
|
||||
/datum/round_event/wormholes/end()
|
||||
portals.Remove(wormholes)
|
||||
for(var/obj/effect/portal/wormhole/O in wormholes)
|
||||
O.loc = null
|
||||
wormholes.Cut()
|
||||
|
||||
|
||||
/obj/effect/portal/wormhole
|
||||
name = "wormhole"
|
||||
desc = "It looks highly unstable; It could close at any moment."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "anom"
|
||||
|
||||
/obj/effect/portal/wormhole/attack_hand(mob/user)
|
||||
teleport(user)
|
||||
|
||||
/obj/effect/portal/wormhole/attackby(obj/item/I, mob/user, params)
|
||||
teleport(user)
|
||||
|
||||
/obj/effect/portal/wormhole/teleport(atom/movable/M)
|
||||
if(istype(M, /obj/effect)) //sparks don't teleport
|
||||
return
|
||||
if(M.anchored && istype(M, /obj/mecha))
|
||||
return
|
||||
|
||||
if(istype(M, /atom/movable))
|
||||
var/turf/target
|
||||
if(portals.len)
|
||||
var/obj/effect/portal/P = pick(portals)
|
||||
if(P && isturf(P.loc))
|
||||
target = P.loc
|
||||
if(!target)
|
||||
return
|
||||
do_teleport(M, target, 1, 1, 0, 0) ///You will appear adjacent to the beacon
|
||||
Reference in New Issue
Block a user