Merge remote-tracking branch 'refs/remotes/origin/master' into upstream-merge-27268

This commit is contained in:
Poojawa
2017-05-21 00:44:08 -05:00
149 changed files with 5040 additions and 2255 deletions
File diff suppressed because it is too large Load Diff
@@ -63624,6 +63624,7 @@
dir = 8
},
/obj/effect/turf_decal/bot,
/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel,
/area/engine/engineering)
"cqt" = (
+4 -1
View File
@@ -2,4 +2,7 @@
#define ANTAG_DATUM_CULT_MASTER /datum/antagonist/cult/master
#define ANTAG_DATUM_CLOCKCULT /datum/antagonist/clockcult
#define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent
#define ANTAG_DATUM_DEVIL /datum/antagonist/devil
#define ANTAG_DATUM_DEVIL /datum/antagonist/devil
#define ANTAG_DATUM_NINJA /datum/antagonist/ninja
#define ANTAG_DATUM_NINJA_FRIENDLY /datum/antagonist/ninja/friendly
#define ANTAG_DATUM_NINJA_RANDOM /datum/antagonist/ninja/randomAllegiance/
+9
View File
@@ -0,0 +1,9 @@
//rune colors, for easy reference
#define RUNE_COLOR_TALISMAN "#0000FF"
#define RUNE_COLOR_TELEPORT "#551A8B"
#define RUNE_COLOR_OFFER "#FFFFFF"
#define RUNE_COLOR_DARKRED "#7D1717"
#define RUNE_COLOR_MEDIUMRED "#C80000"
#define RUNE_COLOR_RED "#FF0000"
#define RUNE_COLOR_EMP "#4D94FF"
#define RUNE_COLOR_SUMMON "#00FF00"
+1
View File
@@ -27,6 +27,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define BLOCK_GAS_SMOKE_EFFECT 4096 // blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
#define THICKMATERIAL 8192 //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
#define DROPDEL 16384 // When dropped, it calls qdel on itself
#define PREVENT_CLICK_UNDER 32768 //Prevent clicking things below it on the same turf eg. doors/ fulltile windows
/* Secondary atom flags, access using the SECONDARY_FLAG macros */
+4
View File
@@ -407,3 +407,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
//Error handler defines
#define ERROR_USEFUL_LEN 2
#define NO_FIELD 0
#define FIELD_TURF 1
#define FIELD_EDGE 2
+14
View File
@@ -340,6 +340,20 @@ Proc for attack log creation, because really why not
qdel(progbar)
//some additional checks as a callback for for do_afters that want to break on losing health or on the mob taking action
/mob/proc/break_do_after_checks(list/checked_health, check_clicks)
if(check_clicks && next_move > world.time)
return FALSE
return TRUE
//pass a list in the format list("health" = mob's health var) to check health during this
/mob/living/break_do_after_checks(list/checked_health, check_clicks)
if(islist(checked_health))
if(health < checked_health["health"])
return FALSE
checked_health["health"] = health
return ..()
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null)
if(!user)
return 0
+2 -1
View File
@@ -13,4 +13,5 @@ GLOBAL_VAR_INIT(sac_image, null)
GLOBAL_VAR_INIT(cult_vote_called, FALSE)
GLOBAL_VAR_INIT(cult_mastered, FALSE)
GLOBAL_VAR_INIT(reckoning_complete, FALSE)
GLOBAL_VAR_INIT(sac_complete, FALSE)
GLOBAL_VAR_INIT(sac_complete, FALSE)
GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
+21
View File
@@ -92,6 +92,9 @@
if(next_move > world.time) // in the year 2000...
return
if(A.IsObscured())
return
if(istype(loc,/obj/mecha))
var/obj/mecha/M = loc
return M.click_action(A,src,params)
@@ -141,6 +144,24 @@
else
RangedAttack(A,params)
//Is the atom obscured by a PREVENT_CLICK_UNDER object above it
/atom/proc/IsObscured()
if(!isturf(loc)) //This only makes sense for things directly on turfs for now
return FALSE
var/turf/T = get_turf_pixel(src)
if(!T)
return FALSE
for(var/atom/movable/AM in T)
if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer)
return TRUE
return FALSE
/turf/IsObscured()
for(var/atom/movable/AM in src)
if(AM.flags & PREVENT_CLICK_UNDER && AM.density)
return TRUE
return FALSE
/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE)
if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms
if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks
+6 -7
View File
@@ -287,9 +287,9 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
GLOB.blood_target = null
else
blood_target = GLOB.blood_target
if(Cviewer)
if(Cviewer.seeking && Cviewer.master)
blood_target = Cviewer.master
if(Cviewer && Cviewer.seeking && Cviewer.master)
blood_target = Cviewer.master
desc = "Your blood sense is leading you to [Cviewer.master]"
if(!blood_target)
if(!GLOB.sac_complete)
if(icon_state == "runed_sense0")
@@ -301,22 +301,21 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin."
add_overlay(GLOB.sac_image)
else
if(SSticker.mode.eldergod)
desc = "The sacrifice is complete, prepare to summon Nar-Sie!"
else
desc = "The summoning is complete, glory to Nar-Sie!"
if(icon_state == "runed_sense1")
return
animate(src, transform = null, time = 1, loop = 0)
angle = 0
cut_overlays()
icon_state = "runed_sense1"
desc = "The sacrifice is complete, bring the wrath of Nar-Sie upon the crew!"
add_overlay(narnar)
return
var/turf/P = get_turf(blood_target)
var/turf/Q = get_turf(mob_viewer)
var/area/A = get_area(P)
if(P.z != Q.z) //The target is on a different Z level, we cannot sense that far.
icon_state = "runed_sense2"
desc = "[blood_target] is no longer in your sector, you cannot sense its presence here."
return
desc = "You are currently tracking [blood_target] in [A.name]."
var/target_angle = Get_Angle(Q, P)
+8 -12
View File
@@ -42,7 +42,6 @@ SUBSYSTEM_DEF(blackbox)
msg_cargo = SSblackbox.msg_cargo
msg_other = SSblackbox.msg_other
feedback = SSblackbox.feedback
//no touchie
@@ -55,8 +54,8 @@ SUBSYSTEM_DEF(blackbox)
return FALSE
/datum/controller/subsystem/blackbox/Shutdown()
set_val("ahelp_unresolved", GLOB.ahelp_tickets.active_tickets.len)
set_val("ahelp_unresolved", GLOB.ahelp_tickets.active_tickets.len)
var/pda_msg_amt = 0
var/rc_msg_amt = 0
@@ -87,19 +86,16 @@ SUBSYSTEM_DEF(blackbox)
if (!SSdbcore.Connect())
return
var/sqlrowlist = ""
var/list/sqlrowlist = list()
for (var/datum/feedback_variable/FV in feedback)
if (sqlrowlist != "")
sqlrowlist += ", " //a comma (,) at the start of the first row to insert will trigger a SQL error
sqlrowlist += list("time" = "Now()", "round_id" = GLOB.round_id, "var_name" = "'[sanitizeSQL(FV.get_variable())]'", "var_value" = FV.get_value(), "details" = "'[sanitizeSQL(FV.get_details())]'")
sqlrowlist += "(null, Now(), [GLOB.round_id], \"[sanitizeSQL(FV.get_variable())]\", [FV.get_value()], \"[sanitizeSQL(FV.get_details())]\")"
if (sqlrowlist == "")
if (!length(sqlrowlist))
return
var/datum/DBQuery/query_feedback_save = SSdbcore.NewQuery("INSERT DELAYED IGNORE INTO [format_table_name("feedback")] VALUES " + sqlrowlist)
query_feedback_save.Execute()
SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE)
/datum/controller/subsystem/blackbox/proc/LogBroadcast(blackbox_msg, freq)
switch(freq)
@@ -245,4 +241,4 @@ SUBSYSTEM_DEF(blackbox)
return details
/datum/feedback_variable/proc/get_parsed()
return list(variable,value,details)
return list(variable,value,details)
+74 -2
View File
@@ -77,15 +77,87 @@ SUBSYSTEM_DEF(dbcore)
return FALSE
return _dm_db_is_connected(_db_con)
/datum/controller/subsystem/dbcore/proc/Quote(str)
/datum/controller/subsystem/dbcore/proc/Quote(str)
return _dm_db_quote(_db_con, str)
/datum/controller/subsystem/dbcore/proc/ErrorMsg()
/datum/controller/subsystem/dbcore/proc/ErrorMsg()
if(!config.sql_enabled)
return "Database disabled by configuration"
return _dm_db_error_msg(_db_con)
/datum/controller/subsystem/dbcore/proc/NewQuery(sql_query, cursor_handler = Default_Cursor)
if(IsAdminAdvancedProcCall())
log_admin_private("ERROR: Advanced admin proc call led to sql query: [sql_query]. Query has been blocked")
message_admins("ERROR: Advanced admin proc call led to sql query. Query has been blocked")
return FALSE
return new /datum/DBQuery(sql_query, src, cursor_handler)
/*
Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query.
Rows missing columns present in other rows will resolve to SQL NULL
You are expected to do your own escaping of the data, and expected to provide your own quotes for strings.
The duplicate_key arg can be true to automatically generate this part of the query
or set to a string that is appended to the end of the query
Ignore_errors instructes mysql to continue inserting rows if some of them have errors.
the erroneous row(s) aren't inserted and there isn't really any way to know why or why errored
Delayed insert mode was removed in mysql 7 and only works with MyISAM type tables,
It was included because it is still supported in mariadb.
It does not work with duplicate_key and the mysql server ignores it in those cases
*/
/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, delayed = FALSE, warn = FALSE)
if (!table || !rows || !istype(rows))
return
var/list/columns = list()
var/list/sorted_rows = list()
for (var/list/row in rows)
var/list/sorted_row = list()
sorted_row.len = columns.len
for (var/column in row)
var/idx = columns[column]
if (!idx)
idx = columns.len + 1
columns[column] = idx
sorted_row.len = columns.len
sorted_row[idx] = row[column]
sorted_rows[++sorted_rows.len] = sorted_row
if (duplicate_key == TRUE)
var/list/column_list = list()
for (var/column in columns)
column_list += "[column] = VALUES([column])"
duplicate_key = "ON DUPLICATE KEY UPDATE [column_list.Join(", ")]\n"
else if (duplicate_key == FALSE)
duplicate_key = null
if (ignore_errors)
ignore_errors = " IGNORE"
else
ignore_errors = null
if (delayed)
delayed = " DELAYED"
else
delayed = null
var/list/sqlrowlist = list()
var/len = columns.len
for (var/list/row in sorted_rows)
if (length(row) != len)
row.len = len
for (var/value in row)
if (value == null)
value = "NULL"
sqlrowlist += "([row.Join(", ")])"
sqlrowlist = " [sqlrowlist.Join(",\n ")]"
var/datum/DBQuery/Query = NewQuery("INSERT[ignore_errors][delayed] INTO [table]\n([columns.Join(", ")])\nVALUES\n[sqlrowlist]\n[duplicate_key]")
if (warn)
return Query.warn_execute()
else
return Query.Execute()
/datum/DBQuery
var/sql // The sql query being executed.
+27
View File
@@ -0,0 +1,27 @@
SUBSYSTEM_DEF(fields)
name = "Fields"
wait = 2
priority = 40
flags = SS_KEEP_TIMING
var/list/datum/proximity_monitor/advanced/running = list()
var/list/datum/proximity_monitor/advanced/currentrun = list()
/datum/controller/subsystem/fields/fire(resumed = 0)
if(!resumed)
src.currentrun = running.Copy()
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/proximity_monitor/advanced/F = currentrun[currentrun.len]
currentrun.len--
if(!F.requires_processing)
continue
F.process()
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/fields/proc/register_new_field(datum/proximity_monitor/advanced/F)
running += F
/datum/controller/subsystem/fields/proc/unregister_field(datum/proximity_monitor/advanced/F)
running -= F
+3 -2
View File
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(server_maint)
wait = 6
flags = SS_POST_FIRE_TIMING
priority = 10
init_order = INIT_ORDER_SERVER_MAINT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun
@@ -16,7 +17,7 @@ SUBSYSTEM_DEF(server_maint)
/datum/controller/subsystem/server_maint/fire(resumed = FALSE)
if(!resumed)
src.currentrun = GLOB.clients.Copy()
var/list/currentrun = src.currentrun
var/round_started = SSticker.HasRoundStarted()
@@ -44,4 +45,4 @@ SUBSYSTEM_DEF(server_maint)
if(C && config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[config.server]")
#undef PING_BUFFER_TIME
#undef PING_BUFFER_TIME
@@ -1,9 +0,0 @@
diff a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm (rejected hunks)
@@ -5,6 +5,7 @@ SUBSYSTEM_DEF(server_maint)
wait = 6
flags = SS_POST_FIRE_TIMING|SS_FIRE_IN_LOBBY
priority = 10
+ init_order = INIT_ORDER_SERVER_MAINT
var/list/currentrun
/datum/controller/subsystem/server_maint/Initialize(timeofday)
+20 -1
View File
@@ -64,6 +64,7 @@ SUBSYSTEM_DEF(ticker)
var/modevoted = FALSE //Have we sent a vote for the gamemode?
/datum/controller/subsystem/ticker/Initialize(timeofday)
load_mode()
var/list/music = world.file2list(ROUND_START_MUSIC_LIST, "\n")
login_music = pick(music)
@@ -285,7 +286,7 @@ SUBSYSTEM_DEF(ticker)
//Now animate the cinematic
switch(station_missed)
if(NUKE_NEAR_MISS) //nuke was nearby but (mostly) missed
if( mode && !override )
if(mode && !override )
override = mode.name
switch( override )
if("nuclear emergency") //Nuke wasn't on station when it blew up
@@ -295,6 +296,17 @@ SUBSYSTEM_DEF(ticker)
station_explosion_detonation(bomb)
flick("station_intact_fade_red",cinematic)
cinematic.icon_state = "summary_nukefail"
if("cult")
cinematic.icon_state = null
flick("intro_cult",cinematic)
sleep(25)
world << sound('sound/magic/enter_blood.ogg')
sleep(28)
world << sound('sound/machines/terminal_off.ogg')
sleep(20)
flick("station_corrupted",cinematic)
world << sound('sound/effects/ghost.ogg')
actually_blew_up = FALSE
if("gang war") //Gang Domination (just show the override screen)
cinematic.icon_state = "intro_malf_still"
flick("intro_malf",cinematic)
@@ -343,6 +355,13 @@ SUBSYSTEM_DEF(ticker)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb) //TODO: no idea what this case could be
cinematic.icon_state = "summary_selfdes"
if("cult") //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb) //TODO: no idea what this case could be
cinematic.icon_state = "summary_cult"
if("no_core") //Nuke failed to detonate as it had no core
flick("intro_nuke",cinematic)
sleep(35)
-9
View File
@@ -1,9 +0,0 @@
diff a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm (rejected hunks)
@@ -60,6 +60,7 @@ SUBSYSTEM_DEF(ticker)
var/list/round_start_events
/datum/controller/subsystem/ticker/Initialize(timeofday)
+ load_mode()
var/list/music = world.file2list(ROUND_START_MUSIC_LIST, "\n")
login_music = pick(music)
+1 -1
View File
@@ -125,7 +125,7 @@ SUBSYSTEM_DEF(vote)
log_admin("Gamemode has been voted for and switched to: [GLOB.master_mode].")
if("gamemode")
if(GLOB.master_mode != .)
world.save_mode(.)
SSticker.save_mode(.)
if(SSticker.HasRoundStarted())
restart = 1
else
+53
View File
@@ -358,6 +358,59 @@
active = FALSE
..()
/datum/action/item_action/initialize_ninja_suit
name = "Toggle ninja suit"
/datum/action/item_action/ninjajaunt
name = "Phase Jaunt (10E)"
desc = "Utilizes the internal VOID-shift device to rapidly transit in direction facing."
button_icon_state = "ninja_phase"
/datum/action/item_action/ninjasmoke
name = "Smoke Bomb"
desc = "Blind your enemies momentarily with a well-placed smoke bomb."
button_icon_state = "smoke"
/datum/action/item_action/ninjaboost
name = "Adrenaline Boost"
desc = "Inject a secret chemical that will counteract all movement-impairing effect."
button_icon_state = "repulse"
/datum/action/item_action/ninjapulse
name = "EM Burst (25E)"
desc = "Disable any nearby technology with a electro-magnetic pulse."
button_icon_state = "emp"
/datum/action/item_action/ninjastar
name = "Create Throwing Stars (1E)"
desc = "Creates some throwing stars"
button_icon_state = "throwingstar"
icon_icon = 'icons/obj/weapons.dmi'
/datum/action/item_action/ninjanet
name = "Energy Net (20E)"
desc = "Captures a fallen opponent in a net of energy. Will teleport them to a holding facility after 30 seconds."
button_icon_state = "energynet"
icon_icon = 'icons/effects/effects.dmi'
/datum/action/item_action/ninja_sword_recall
name = "Recall Energy Katana (Variable Cost)"
desc = "Teleports the Energy Katana linked to this suit to its wearer, cost based on distance."
button_icon_state = "energy_katana"
icon_icon = 'icons/obj/weapons.dmi'
/datum/action/item_action/ninja_stealth
name = "Toggle Stealth"
desc = "Toggles stealth mode on and off."
button_icon_state = "ninja_cloak"
/datum/action/item_action/toggle_glove
name = "Toggle interaction"
desc = "Switch between normal interaction and drain mode."
button_icon_state = "s-ninjan"
icon_icon = 'icons/obj/clothing/gloves.dmi'
/datum/action/item_action/organ_action
check_flags = AB_CHECK_CONSCIOUS
+153
View File
@@ -0,0 +1,153 @@
/datum/antagonist/ninja
name = "Ninja"
var/team
var/helping_station = 0
var/give_objectives = TRUE
/datum/antagonist/ninja/friendly
helping_station = 1
/datum/antagonist/ninja/friendly/noobjective
give_objectives = FALSE
/datum/antagonist/ninja/New(datum/mind/new_owner)
if(new_owner && !ishuman(new_owner.current))//It's fine if we aren't passed a mind, but if we are, they have to be human.
throw EXCEPTION("Only humans and/or humanoids may be ninja'ed")
..(new_owner)
/datum/antagonist/ninja/randomAllegiance/New(datum/mind/new_owner)
..(new_owner)
helping_station = rand(0,1)
/datum/antagonist/ninja/proc/equip_space_ninja(mob/living/carbon/human/H = owner.current, safety=0)//Safety in case you need to unequip stuff for existing characters.
if(safety)
qdel(H.w_uniform)
qdel(H.wear_suit)
qdel(H.wear_mask)
qdel(H.head)
qdel(H.shoes)
qdel(H.gloves)
var/obj/item/clothing/suit/space/space_ninja/theSuit = new(H)
var/obj/item/weapon/katana/energy/EK = new(H)
theSuit.energyKatana = EK
H.equip_to_slot_or_del(new /obj/item/device/radio/headset(H), slot_ears)
H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/space_ninja(H), slot_shoes)
H.equip_to_slot_or_del(theSuit, slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/space_ninja(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/space_ninja(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/space_ninja(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night(H), slot_glasses)
H.equip_to_slot_or_del(EK, slot_belt)
H.equip_to_slot_or_del(new /obj/item/device/flashlight(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/x4(H), slot_l_store)
H.equip_to_slot_or_del(new /obj/item/weapon/tank/internals/emergency_oxygen(H), slot_s_store)
H.equip_to_slot_or_del(new /obj/item/weapon/tank/jetpack/carbondioxide(H), slot_back)
theSuit.randomize_param()
var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(H)
E.implant(H)
return 1
/datum/antagonist/ninja/proc/addMemories()
owner.store_memory("I am an elite mercenary assassin of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!")
owner.store_memory("Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!")
owner.store_memory("Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.")
/datum/antagonist/ninja/proc/addObjectives(quantity = 6)
var/list/possible_targets = list()
for(var/datum/mind/M in SSticker.minds)
if(M.current && M.current.stat != DEAD)
if(ishuman(M.current))
if(M.special_role)
possible_targets[M] = 0 //bad-guy
else if(M.assigned_role in GLOB.command_positions)
possible_targets[M] = 1 //good-guy
var/list/objectives = list(1,2,3,4)
while(owner.objectives.len < quantity)
switch(pick_n_take(objectives))
if(1) //research
var/datum/objective/download/O = new /datum/objective/download()
O.owner = owner
O.gen_amount_goal()
owner.objectives += O
if(2) //steal
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
O.owner = owner
owner.objectives += O
if(3) //protect/kill
if(!possible_targets.len) continue
var/index = rand(1,possible_targets.len)
var/datum/mind/M = possible_targets[index]
var/is_bad_guy = possible_targets[M]
possible_targets.Cut(index,index+1)
if(is_bad_guy ^ helping_station) //kill (good-ninja + bad-guy or bad-ninja + good-guy)
var/datum/objective/assassinate/O = new /datum/objective/assassinate()
O.owner = owner
O.target = M
O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]."
owner.objectives += O
else //protect
var/datum/objective/protect/O = new /datum/objective/protect()
O.owner = owner
O.target = M
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
owner.objectives += O
if(4) //debrain/capture
if(!possible_targets.len) continue
var/selected = rand(1,possible_targets.len)
var/datum/mind/M = possible_targets[selected]
var/is_bad_guy = possible_targets[M]
possible_targets.Cut(selected,selected+1)
if(is_bad_guy ^ helping_station) //debrain (good-ninja + bad-guy or bad-ninja + good-guy)
var/datum/objective/debrain/O = new /datum/objective/debrain()
O.owner = owner
O.target = M
O.explanation_text = "Steal the brain of [M.current.real_name]."
owner.objectives += O
else //capture
var/datum/objective/capture/O = new /datum/objective/capture()
O.owner = owner
O.gen_amount_goal()
owner.objectives += O
else
break
var/datum/objective/O = new /datum/objective/survive()
O.owner = owner
owner.objectives += O
/proc/remove_ninja(mob/living/L)
if(!L || !L.mind)
return FALSE
var/datum/antagonist/datum = L.mind.has_antag_datum(ANTAG_DATUM_NINJA)
datum.on_removal()
return TRUE
/proc/add_ninja(mob/living/carbon/human/H, type = ANTAG_DATUM_NINJA_RANDOM)
if(!H || !H.mind)
return FALSE
return H.mind.add_antag_datum(type)
/proc/is_ninja(mob/living/M)
return M && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_NINJA)
/datum/antagonist/ninja/greet()
owner.current << sound('sound/effects/ninja_greeting.ogg')
to_chat(owner.current, "I am an elite mercenary assassin of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!")
to_chat(owner.current, "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!")
to_chat(owner.current, "Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.")
return
/datum/antagonist/ninja/on_gain()
if(give_objectives)
addObjectives()
addMemories()
-12
View File
@@ -737,18 +737,6 @@
src.give_disease(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["ninja"])
if(!check_rights(R_FUN))
return
var/mob/M = locate(href_list["ninja"])
if(!istype(M))
to_chat(usr, "This can only be used on instances of type /mob")
return
src.cmd_admin_ninjafy(M)
href_list["datumrefresh"] = href_list["ninja"]
else if(href_list["gib"])
if(!check_rights(R_FUN))
return
+8 -3
View File
@@ -31,6 +31,7 @@
var/obj/machinery/holopad/H = I
if(!QDELETED(H) && H.is_operational())
dialed_holopads += H
H.say("Incoming call.")
LAZYADD(H.holo_calls, src)
if(!dialed_holopads.len)
@@ -42,12 +43,16 @@
//cleans up ALL references :)
/datum/holocall/Destroy()
QDEL_NULL(eye)
user.reset_perspective()
if(user.client)
for(var/datum/camerachunk/chunk in eye.visibleCameraChunks)
user.client.images -= chunk.obscured
user.remote_control = null
QDEL_NULL(eye)
user = null
hologram.HC = null
if(hologram)
hologram.HC = null
hologram = null
calling_holopad.outgoing_call = null
+45 -5
View File
@@ -326,7 +326,8 @@
"traitor", // "traitorchan",
"monkey",
"clockcult",
"devil"
"devil",
"ninja"
)
var/text = ""
@@ -614,9 +615,27 @@
text += "|Disabled in Prefs"
sections["devil"] = text
/** NINJA ***/
text = "ninja"
if(SSticker.mode.config_tag == "ninja")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
var/datum/antagonist/ninja/ninjainfo = has_antag_datum(ANTAG_DATUM_NINJA)
if(ninjainfo)
if(ninjainfo.helping_station)
text += "<a href='?src=\ref[src];ninja=clear'>employee</a> | syndicate | <b>NANOTRASEN</b> | <b><a href='?src=\ref[src];ninja=equip'>EQUIP</a></b>"
else
text += "<a href='?src=\ref[src];ninja=clear'>employee</a> | <b>SYNDICATE</b> | nanotrasen | <b><a href='?src=\ref[src];ninja=equip'>EQUIP</a></b>"
else
text += "<b>EMPLOYEE</b> | <a href='?src=\ref[src];ninja=syndicate'>syndicate</a> | <a href='?src=\ref[src];ninja=nanotrasen'>nanotrasen</a> | <a href='?src=\ref[src];ninja=random'>random allegiance</a>"
if(current && current.client && (ROLE_NINJA in current.client.prefs.be_special))
text += " | Enabled in Prefs"
else
text += " | Disabled in Prefs"
sections["ninja"] = text
/** SILICON ***/
/** SILICON ***/
if(issilicon(current))
text = "silicon"
var/mob/living/silicon/robot/robot = current
@@ -1202,7 +1221,28 @@
else
to_chat(usr, "<span class='warning'>This only works on humans!</span>")
return
else if(href_list["ninja"])
var/datum/antagonist/ninja/ninjainfo = has_antag_datum(ANTAG_DATUM_NINJA)
switch(href_list["ninja"])
if("clear")
remove_ninja(current)
message_admins("[key_name_admin(usr)] has de-ninja'ed [current].")
log_admin("[key_name(usr)] has de-ninja'ed [current].")
if("equip")
ninjainfo.equip_space_ninja()
return
if("nanotrasen")
add_ninja(current, ANTAG_DATUM_NINJA_FRIENDLY)
message_admins("[key_name_admin(usr)] has friendly ninja'ed [current].")
log_admin("[key_name(usr)] has friendly ninja'ed [current].")
if("syndicate")
add_ninja(current, ANTAG_DATUM_NINJA)
message_admins("[key_name_admin(usr)] has syndie ninja'ed [current].")
log_admin("[key_name(usr)] has syndie ninja'ed [current].")
if("random")
add_ninja(current)
message_admins("[key_name_admin(usr)] has random ninja'ed [current].")
log_admin("[key_name(usr)] has random ninja'ed [current].")
else if(href_list["abductor"])
switch(href_list["abductor"])
if("clear")
@@ -1330,7 +1370,7 @@
obj_count++
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.get_contents()
var/list/L = current.GetAllContents()
for (var/obj/item/I in L)
if (I.hidden_uplink)
return I.hidden_uplink
@@ -1615,4 +1655,4 @@
/mob/living/silicon/pai/mind_initialize()
..()
mind.assigned_role = "pAI"
mind.special_role = ""
mind.special_role = ""
@@ -5,60 +5,60 @@
//otherwise, return literally any non-list thing but preferably FALSE
//returning TRUE won't produce the "cannot be proselytized" message and will still prevent proselytizing
/atom/proc/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/atom/proc/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Turf conversion
/turf/closed/wall/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer) //four sheets of metal
/turf/closed/wall/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent) //four sheets of metal
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 4), "spawn_dir" = SOUTH)
/turf/closed/wall/mineral/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer) //two sheets of metal
/turf/closed/wall/mineral/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent) //two sheets of metal
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2), "spawn_dir" = SOUTH)
/turf/closed/wall/mineral/iron/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer) //two sheets of metal, five rods
/turf/closed/wall/mineral/iron/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent) //two sheets of metal, five rods
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2) - (POWER_ROD * 5), "spawn_dir" = SOUTH)
/turf/closed/wall/mineral/cult/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer) //no metal
/turf/closed/wall/mineral/cult/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent) //no metal
return list("operation_time" = 80, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = SOUTH)
/turf/closed/wall/shuttle/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer) //two sheets of metal
/turf/closed/wall/shuttle/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent) //two sheets of metal
return list("operation_time" = 50, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_TOTAL - (POWER_METAL * 2), "spawn_dir" = SOUTH)
/turf/closed/wall/r_wall/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/turf/closed/wall/r_wall/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
/turf/closed/wall/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/turf/closed/wall/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return list("operation_time" = 50, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = -POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
/turf/open/floor/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/turf/open/floor/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
if(floor_tile == /obj/item/stack/tile/plasteel)
new floor_tile(src)
make_plating()
playsound(src, 'sound/items/Crowbar.ogg', 10, 1) //clink
return list("operation_time" = 30, "new_obj_type" = /turf/open/floor/clockwork, "power_cost" = POWER_FLOOR, "spawn_dir" = SOUTH)
/turf/open/floor/plating/asteroid/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/turf/open/floor/plating/asteroid/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
/turf/open/floor/plating/ashplanet/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/turf/open/floor/plating/ashplanet/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
/turf/open/floor/plating/lava/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/turf/open/floor/plating/lava/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
/turf/open/floor/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/turf/open/floor/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
if(locate(/obj/structure/table) in src)
return FALSE
if(is_blocked_turf(src, TRUE))
to_chat(user, "<span class='warning'>Something is in the way, preventing you from proselytizing [src] into a clockwork wall.</span>")
return TRUE
var/operation_time = 100
if(proselytizer.speed_multiplier > 0)
if(!GLOB.ratvar_awakens && proselytizer.speed_multiplier > 0) //if ratvar isn't awake, this always takes 10 seconds
operation_time /= proselytizer.speed_multiplier
return list("operation_time" = operation_time, "new_obj_type" = /turf/closed/wall/clockwork, "power_cost" = POWER_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
//False wall conversion
/obj/structure/falsewall/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/falsewall/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
var/cost = POWER_WALL_MINUS_FLOOR
if(ispath(mineral, /obj/item/stack/sheet/metal))
cost -= (POWER_METAL * (2 + mineral_amount)) //four sheets of metal, plus an assumption that the girder is also two
@@ -66,17 +66,17 @@
cost -= (POWER_METAL * 2) //anything that doesn't use metal just has the girder
return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = cost, "spawn_dir" = SOUTH)
/obj/structure/falsewall/iron/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer) //two sheets of metal, two rods; special assumption
/obj/structure/falsewall/iron/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent) //two sheets of metal, two rods; special assumption
return list("operation_time" = 50, "new_obj_type" = /obj/structure/falsewall/brass, "power_cost" = POWER_WALL_MINUS_FLOOR - (POWER_METAL * 2) - (POWER_ROD * 2), "spawn_dir" = SOUTH)
/obj/structure/falsewall/reinforced/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/falsewall/reinforced/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
/obj/structure/falsewall/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/falsewall/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Metal conversion
/obj/item/stack/tile/plasteel/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/item/stack/tile/plasteel/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
if(source)
return FALSE
var/amount_temp = get_amount()
@@ -104,7 +104,7 @@
to_chat(user, "<span class='warning'>You need at least <b>20</b> floor tiles to convert into brass.</span>")
return TRUE
/obj/item/stack/rods/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/item/stack/rods/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
if(source)
return FALSE
if(proselytizer.metal_to_power)
@@ -122,7 +122,7 @@
to_chat(user, "<span class='warning'>You need at least <b>10</b> rods to convert into brass.</span>")
return TRUE
/obj/item/stack/sheet/metal/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/item/stack/sheet/metal/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
if(source)
return FALSE
if(proselytizer.metal_to_power)
@@ -140,7 +140,7 @@
to_chat(user, "<span class='warning'>You need at least <b>5</b> sheets of metal to convert into brass.</span>")
return TRUE
/obj/item/stack/sheet/plasteel/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/item/stack/sheet/plasteel/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
if(source)
return FALSE
if(proselytizer.metal_to_power)
@@ -159,23 +159,23 @@
return TRUE
//Brass directly to power
/obj/item/stack/tile/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/item/stack/tile/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
if(source)
return FALSE
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(amount*POWER_FLOOR), "spawn_dir" = SOUTH)
//Airlock conversion
/obj/machinery/door/airlock/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/machinery/door/airlock/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
var/doortype = /obj/machinery/door/airlock/clockwork
if(glass)
doortype = /obj/machinery/door/airlock/clockwork/brass
return list("operation_time" = 60, "new_obj_type" = doortype, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = dir)
/obj/machinery/door/airlock/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/machinery/door/airlock/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Table conversion
/obj/structure/table/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/table/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
var/prosel_cost = POWER_STANDARD
if(framestack == /obj/item/stack/rods)
prosel_cost -= POWER_ROD*framestackamount
@@ -187,10 +187,10 @@
prosel_cost -= POWER_PLASTEEL*buildstackamount
return list("operation_time" = 20, "new_obj_type" = /obj/structure/table/reinforced/brass, "power_cost" = prosel_cost, "spawn_dir" = SOUTH)
/obj/structure/table/reinforced/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/table/reinforced/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
/obj/structure/table_frame/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/table_frame/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
var/prosel_cost = POWER_FLOOR
if(framestack == /obj/item/stack/rods)
prosel_cost -= POWER_ROD*framestackamount
@@ -198,11 +198,11 @@
prosel_cost -= POWER_FLOOR*framestackamount
return list("operation_time" = 10, "new_obj_type" = /obj/structure/table_frame/brass, "power_cost" = prosel_cost, "spawn_dir" = SOUTH)
/obj/structure/table_frame/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/table_frame/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Window conversion
/obj/structure/window/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/window/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
var/windowtype = /obj/structure/window/reinforced/clockwork
var/new_dir = TRUE
var/prosel_time = 15
@@ -220,18 +220,18 @@
INVOKE_ASYNC(proselytizer, /obj/item/clockwork/clockwork_proselytizer.proc/proselytize, G, user)
return list("operation_time" = prosel_time, "new_obj_type" = windowtype, "power_cost" = prosel_cost, "spawn_dir" = dir, "dir_in_new" = new_dir)
/obj/structure/window/reinforced/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/window/reinforced/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Windoor conversion
/obj/machinery/door/window/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/machinery/door/window/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return list("operation_time" = 30, "new_obj_type" = /obj/machinery/door/window/clockwork, "power_cost" = POWER_STANDARD, "spawn_dir" = dir, "dir_in_new" = TRUE)
/obj/machinery/door/window/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/machinery/door/window/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Grille conversion
/obj/structure/grille/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/grille/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
var/grilletype = /obj/structure/grille/ratvar
var/prosel_time = 15
if(broken)
@@ -239,32 +239,32 @@
prosel_time = 5
return list("operation_time" = prosel_time, "new_obj_type" = grilletype, "power_cost" = 0, "spawn_dir" = dir)
/obj/structure/grille/ratvar/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/grille/ratvar/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Lattice conversion
/obj/structure/lattice/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/lattice/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
/obj/structure/lattice/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/lattice/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
ratvar_act() //just in case we're the wrong type for some reason??
return FALSE
/obj/structure/lattice/catwalk/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/lattice/catwalk/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return list("operation_time" = 0, "new_obj_type" = /obj/structure/lattice/catwalk/clockwork, "power_cost" = 0, "spawn_dir" = SOUTH, "no_target_deletion" = TRUE)
/obj/structure/lattice/catwalk/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/lattice/catwalk/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
return FALSE
//Girder conversion
/obj/structure/girder/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/girder/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
var/prosel_cost = POWER_GEAR - (POWER_METAL * 2)
if(state == GIRDER_REINF_STRUTS || state == GIRDER_REINF)
prosel_cost -= POWER_PLASTEEL
return list("operation_time" = 20, "new_obj_type" = /obj/structure/destructible/clockwork/wall_gear, "power_cost" = prosel_cost, "spawn_dir" = SOUTH)
//Hitting a clockwork structure will try to repair it.
/obj/structure/destructible/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/structure/destructible/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
. = TRUE
var/list/repair_values = list()
if(!proselytizer.proselytizer_repair_checks(repair_values, src, user))
@@ -287,7 +287,7 @@
"<span class='alloy'>You finish repairing [src]. It is now at <b>[obj_integrity]/[max_integrity]</b> integrity.</span>")
//Hitting a sigil of transmission will try to charge from it.
/obj/effect/clockwork/sigil/transmission/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/obj/effect/clockwork/sigil/transmission/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
. = TRUE
var/list/charge_values = list()
if(!proselytizer.sigil_charge_checks(charge_values, src, user))
@@ -337,7 +337,7 @@
adjustHealth(-amount)
//Hitting a ratvar'd silicon will also try to repair it.
/mob/living/silicon/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/mob/living/silicon/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
. = TRUE
if(health == maxHealth) //if we're at maximum health, prosel the turf under us
return FALSE
@@ -346,7 +346,7 @@
"<span class='alloy'>You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_they(TRUE)] [p_are()]"] now at <b>[abs(HEALTH_THRESHOLD_DEAD - health)]/[abs(HEALTH_THRESHOLD_DEAD - maxHealth)]</b> health.</span>")
//Same with clockwork mobs.
/mob/living/simple_animal/hostile/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/mob/living/simple_animal/hostile/clockwork/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
. = TRUE
if(health == maxHealth) //if we're at maximum health, prosel the turf under us
return FALSE
@@ -355,7 +355,7 @@
"<span class='alloy'>You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_they(TRUE)] [p_are()]"] now at <b>[health]/[maxHealth]</b> health.</span>")
//Cogscarabs get special interaction because they're drones and have innate self-heals/revives.
/mob/living/simple_animal/drone/cogscarab/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
/mob/living/simple_animal/drone/cogscarab/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent)
. = TRUE
if(stat == DEAD)
try_reactivate(user) //if we're at maximum health, prosel the turf under us
@@ -374,17 +374,36 @@
proselytizer.repairing = null
//Convert shards and gear bits directly to power
/obj/item/clockwork/alloy_shards/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -POWER_STANDARD, "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent, power_amount)
if(!power_amount)
power_amount = -POWER_STANDARD
if(proselytizer.can_use_power(power_amount))
var/obj/effect/overlay/temp/ratvar/beam/itemconsume/B = new /obj/effect/overlay/temp/ratvar/beam/itemconsume(get_turf(src))
B.pixel_x = pixel_x
B.pixel_y = pixel_y
if(!silent) //looper no looping
for(var/obj/item/clockwork/alloy_shards/S in get_turf(src)) //convert all other shards in the turf if we can
if(S == src)
continue //we want the shards to be proselytized after the main shard, thus this delay
addtimer(CALLBACK(proselytizer, /obj/item/clockwork/clockwork_proselytizer.proc/proselytize, S, user, TRUE), 0)
return list("operation_time" = 0, "new_obj_type" = null, "power_cost" = power_amount, "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/medium/gear_bit/large/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.08), "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/medium/gear_bit/large/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.08)
return ..()
/obj/item/clockwork/alloy_shards/large/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.06), "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/large/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.06)
return ..()
/obj/item/clockwork/alloy_shards/medium/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.04), "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/medium/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.04)
return ..()
/obj/item/clockwork/alloy_shards/small/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 0, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "power_cost" = -(CLOCKCULT_POWER_UNIT*0.02), "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/small/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer, silent, power_amount)
if(!power_amount)
power_amount = -(CLOCKCULT_POWER_UNIT*0.02)
return ..()
@@ -162,14 +162,15 @@
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/randomsinglesprite = FALSE
var/randomspritemax = 2
var/sprite_shift = 9
/obj/item/clockwork/alloy_shards/Initialize()
. = ..()
if(randomsinglesprite)
replace_name_desc()
icon_state = "[icon_state][rand(1, randomspritemax)]"
pixel_x = rand(-9, 9)
pixel_y = rand(-9, 9)
pixel_x = rand(-sprite_shift, sprite_shift)
pixel_y = rand(-sprite_shift, sprite_shift)
/obj/item/clockwork/alloy_shards/proc/replace_name_desc()
name = "replicant alloy shard"
@@ -177,16 +178,21 @@
clockwork_desc = "A broken shard of replicant alloy. Can be proselytized for additional power."
/obj/item/clockwork/alloy_shards/large
w_class = WEIGHT_CLASS_TINY
randomsinglesprite = TRUE
icon_state = "shard_large"
sprite_shift = 9
/obj/item/clockwork/alloy_shards/medium
w_class = WEIGHT_CLASS_TINY
randomsinglesprite = TRUE
icon_state = "shard_medium"
sprite_shift = 10
/obj/item/clockwork/alloy_shards/medium/gear_bit
randomspritemax = 4
icon_state = "gear_bit"
sprite_shift = 12
/obj/item/clockwork/alloy_shards/medium/gear_bit/replace_name_desc()
name = "gear bit"
@@ -200,9 +206,11 @@
name = "complex gear bit"
/obj/item/clockwork/alloy_shards/small
w_class = WEIGHT_CLASS_TINY
randomsinglesprite = TRUE
randomspritemax = 3
icon_state = "shard_small"
sprite_shift = 12
/obj/item/clockwork/alloy_shards/pinion_lock
name = "pinion lock"
@@ -178,21 +178,24 @@
return TRUE
//A note here; return values are for if we CAN BE PUT ON A TABLE, not IF WE ARE SUCCESSFUL, unless no_table_check is TRUE
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize(atom/target, mob/living/user, no_table_check)
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize(atom/target, mob/living/user, silent, no_table_check)
if(!target || !user)
return FALSE
if(repairing)
to_chat(user, "<span class='warning'>You are currently repairing [repairing] with [src]!</span>")
if(!silent)
to_chat(user, "<span class='warning'>You are currently repairing [repairing] with [src]!</span>")
return FALSE
if(recharging)
to_chat(user, "<span class='warning'>You are currently recharging [src] from the [recharging.sigil_name]!</span>")
if(!silent)
to_chat(user, "<span class='warning'>You are currently recharging [src] from the [recharging.sigil_name]!</span>")
return FALSE
var/list/proselytize_values = target.proselytize_vals(user, src) //relevant values for proselytizing stuff, given as an associated list
var/list/proselytize_values = target.proselytize_vals(user, src, silent) //relevant values for proselytizing stuff, given as an associated list
if(!islist(proselytize_values))
if(proselytize_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
if(!isturf(target)) //otherwise, if we didn't get TRUE and the original target wasn't a turf, try to proselytize the turf
return proselytize(get_turf(target), user, no_table_check)
to_chat(user, "<span class='warning'>[target] cannot be proselytized!</span>")
if(!silent)
to_chat(user, "<span class='warning'>[target] cannot be proselytized!</span>")
if(!no_table_check)
return TRUE
return FALSE
@@ -207,19 +210,22 @@
var/target_type = target.type
if(!proselytize_checks(proselytize_values, target, target_type, user))
if(!proselytize_checks(proselytize_values, target, target_type, user, silent))
return FALSE
proselytize_values["operation_time"] *= speed_multiplier
playsound(target, 'sound/machines/click.ogg', 50, 1)
if(proselytize_values["operation_time"])
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
if(!silent)
user.visible_message("<span class='warning'>[user]'s [name] begins tearing apart [target]!</span>", "<span class='brass'>You begin proselytizing [target]...</span>")
if(!do_after(user, proselytize_values["operation_time"], target = target, extra_checks = CALLBACK(src, .proc/proselytize_checks, proselytize_values, target, target_type, user, TRUE)))
return FALSE
user.visible_message("<span class='warning'>[user]'s [name] covers [target] in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
if(!silent)
user.visible_message("<span class='warning'>[user]'s [name] covers [target] in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
else
user.visible_message("<span class='warning'>[user]'s [name] tears apart [target], covering it in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
if(!silent)
user.visible_message("<span class='warning'>[user]'s [name] tears apart [target], covering it in golden energy!</span>", "<span class='brass'>You proselytize [target].</span>")
playsound(target, 'sound/items/Deconstruct.ogg', 50, 1)
var/new_thing_type = proselytize_values["new_obj_type"]
@@ -227,11 +233,12 @@
var/turf/T = target
T.ChangeTurf(new_thing_type)
else
if(proselytize_values["dir_in_new"])
new new_thing_type(get_turf(target), proselytize_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New()
else
var/atom/A = new new_thing_type(get_turf(target))
A.setDir(proselytize_values["spawn_dir"])
if(new_thing_type)
if(proselytize_values["dir_in_new"])
new new_thing_type(get_turf(target), proselytize_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New()
else
var/atom/A = new new_thing_type(get_turf(target))
A.setDir(proselytize_values["spawn_dir"])
if(!proselytize_values["no_target_deletion"]) //for some cases where proselytize_vals() modifies the object but doesn't want it deleted
qdel(target)
modify_stored_power(-proselytize_values["power_cost"])
@@ -239,8 +246,13 @@
return TRUE
return FALSE
//The following three procs are heavy wizardry.
//What these procs do is they take an existing list of values, which they then modify.
//This(modifying an existing object, in this case the list) is the only way to get information OUT of a do_after callback, which this is used as.
//The proselytize check proc.
/obj/item/clockwork/clockwork_proselytizer/proc/proselytize_checks(list/proselytize_values, atom/target, expected_type, mob/user, silent) //checked constantly while proselytizing
if(!islist(proselytize_values) || !target || QDELETED(target) || !user)
if(!islist(proselytize_values) || QDELETED(target) || QDELETED(user))
return FALSE
if(repairing || recharging)
return FALSE
@@ -259,11 +271,8 @@
return TRUE
//The repair check proc.
//Is dark magic. Can probably kill you.
//What this proc does is it takes an existing list of values, which it modifies.
//This(modifying an existing object) is the only way to get information OUT of a do_after callback, which this is used as.
/obj/item/clockwork/clockwork_proselytizer/proc/proselytizer_repair_checks(list/repair_values, atom/target, mob/user, silent) //Exists entirely to avoid an otherwise unreadable series of checks.
if(!islist(repair_values) || !target || QDELETED(target) || !user)
if(!islist(repair_values) || QDELETED(target) || QDELETED(user))
return FALSE
if(isliving(target)) //standard checks for if we can affect the target
var/mob/living/L = target
@@ -302,9 +311,9 @@
return FALSE
return TRUE
//checked constantly while charging from a sigil
//The sigil charge check proc.
/obj/item/clockwork/clockwork_proselytizer/proc/sigil_charge_checks(list/charge_values, obj/effect/clockwork/sigil/transmission/sigil, mob/user, silent)
if(!islist(charge_values) || !sigil || QDELETED(sigil) || !user)
if(!islist(charge_values) || QDELETED(sigil) || QDELETED(user))
return FALSE
if(can_use_power(RATVAR_POWER_CHECK))
return FALSE
@@ -28,7 +28,7 @@
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
var/area/A = get_area(src)
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0, 0)
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 0, null, FALSE, 0)
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
GLOB.ratvar_awakens--
+1 -1
View File
@@ -152,7 +152,7 @@
return TRUE
/datum/action/innate/cult/master/IsAvailable()
if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER) || GLOB.cult_narsie)
return 0
return ..()
+1 -1
View File
@@ -214,7 +214,7 @@
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/worn_overlays(isinhands)
. = list()
if(!isinhands && current_charges)
. += mutable_appearance('icons/effects/effects.dmi', "shield-cult", MOB_LAYER + 0.01)
. += mutable_appearance('icons/effects/cult_effects.dmi', "shield-cult", MOB_LAYER + 0.01)
/obj/item/clothing/suit/hooded/cultrobes/berserker
name = "flagellant's robes"
@@ -0,0 +1,70 @@
//after a delay, creates a rune below you. for constructs creating runes.
/datum/action/innate/cult/create_rune
background_icon_state = "bg_cult"
var/obj/effect/rune/rune_type
var/cooldown = 0
var/base_cooldown = 900
var/scribe_time = 100
var/damage_interrupt = TRUE
var/action_interrupt = TRUE
var/obj/effect/overlay/temp/cult/rune_spawn/rune_word_type
var/obj/effect/overlay/temp/cult/rune_spawn/rune_innerring_type
var/obj/effect/overlay/temp/cult/rune_spawn/rune_center_type
var/rune_color
/datum/action/innate/cult/create_rune/IsAvailable()
if(!rune_type || cooldown > world.time)
return FALSE
return ..()
/datum/action/innate/cult/create_rune/Activate()
var/chosen_keyword
if(!isturf(owner.loc))
to_chat(owner, "<span class='warning>You need more space to scribe a rune!</span>")
return
if(initial(rune_type.req_keyword))
chosen_keyword = stripped_input(owner, "Enter a keyword for the new rune.", "Words of Power")
if(!chosen_keyword)
return
//the outer ring is always the same across all runes
var/obj/effect/overlay/temp/cult/rune_spawn/R1 = new(owner.loc, scribe_time, rune_color)
//the rest are not always the same, so we need types for em
var/obj/effect/overlay/temp/cult/rune_spawn/R2
if(rune_word_type)
R2 = new rune_word_type(owner.loc, scribe_time, rune_color)
var/obj/effect/overlay/temp/cult/rune_spawn/R3
if(rune_innerring_type)
R3 = new rune_innerring_type(owner.loc, scribe_time, rune_color)
var/obj/effect/overlay/temp/cult/rune_spawn/R4
if(rune_center_type)
R4 = new rune_center_type(owner.loc, scribe_time, rune_color)
cooldown = base_cooldown + world.time
owner.update_action_buttons_icon()
addtimer(CALLBACK(owner, /mob.proc/update_action_buttons_icon), base_cooldown)
var/list/health
if(damage_interrupt && isliving(owner))
var/mob/living/L = owner
health = list("health" = L.health)
if(do_after(owner, scribe_time, target = owner, extra_checks = CALLBACK(owner, /mob.proc/break_do_after_checks, health, action_interrupt)))
var/obj/effect/rune/new_rune = new rune_type(owner.loc)
new_rune.keyword = chosen_keyword
else
qdel(R1)
if(R2)
qdel(R2)
if(R3)
qdel(R3)
if(R4)
qdel(R4)
cooldown = 0
owner.update_action_buttons_icon()
//teleport rune
/datum/action/innate/cult/create_rune/tele
button_icon_state = "telerune"
rune_type = /obj/effect/rune/teleport
rune_word_type = /obj/effect/overlay/temp/cult/rune_spawn/rune2
rune_innerring_type = /obj/effect/overlay/temp/cult/rune_spawn/rune2/inner
rune_center_type = /obj/effect/overlay/temp/cult/rune_spawn/rune2/center
rune_color = RUNE_COLOR_TELEPORT
+30 -30
View File
@@ -24,7 +24,7 @@ To draw a rune, use an arcane tome.
icon_state = "1"
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
layer = LOW_OBJ_LAYER
color = "#FF0000"
color = RUNE_COLOR_RED
var/invocation = "Aiy ele-mayo!" //This is said by cultists when the rune is invoked.
var/req_cultists = 1 //The amount of cultists required around the rune to invoke it. If only 1, any cultist can invoke it.
@@ -148,8 +148,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/proc/fail_invoke()
//This proc contains the effects of a rune if it is not invoked correctly, through either invalid wording or not enough cultists. By default, it's just a basic fizzle.
visible_message("<span class='warning'>The markings pulse with a \
small flash of red light, then fall dark.</span>")
visible_message("<span class='warning'>The markings pulse with a small flash of red light, then fall dark.</span>")
var/oldcolor = color
color = rgb(255, 0, 0)
animate(src, color = oldcolor, time = 5)
@@ -192,7 +191,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "transforms paper into powerful magic talismans."
invocation = "H'drak v'loso, mir'kanas verbot!"
icon_state = "3"
color = "#0000FF"
color = RUNE_COLOR_TALISMAN
/obj/effect/rune/imbue/invoke(var/list/invokers)
var/mob/living/user = invokers[1] //the first invoker is always the user
@@ -247,7 +246,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "warps everything above it to another chosen teleport rune."
invocation = "Sas'so c'arta forbici!"
icon_state = "2"
color = "#551A8B"
color = RUNE_COLOR_TELEPORT
req_keyword = TRUE
var/listkey
@@ -307,10 +306,11 @@ structure_check() searches for nearby cultist structures required for the invoca
A.forceMove(target)
if(movedsomething)
..()
visible_message("<span class='warning'>There is a sharp crack of inrushing air, and everything above the rune disappears!</span>")
visible_message("<span class='warning'>There is a sharp crack of inrushing air, and everything above the rune disappears!</span>", null, "<i>You hear a sharp crack.</i>")
to_chat(user, "<span class='cult'>You[moveuserlater ? "r vision blurs, and you suddenly appear somewhere else":" send everything above the rune away"].</span>")
if(moveuserlater)
user.forceMove(target)
target.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
else
fail_invoke()
@@ -322,7 +322,7 @@ structure_check() searches for nearby cultist structures required for the invoca
req_cultists_text = "2 for conversion, 3 for living sacrifices and sacrifice targets."
invocation = "Mah'weyh pleggh at e'ntrath!"
icon_state = "3"
color = "#FFFFFF"
color = RUNE_COLOR_OFFER
req_cultists = 1
allow_excess_invokers = TRUE
rune_in_use = FALSE
@@ -345,7 +345,7 @@ structure_check() searches for nearby cultist structures required for the invoca
rune_in_use = TRUE
visible_message("<span class='warning'>[src] pulses blood red!</span>")
var/oldcolor = color
color = "#7D1717"
color = RUNE_COLOR_DARKRED
var/mob/living/L = pick(myriad_targets)
var/is_clock = is_servant_of_ratvar(L)
var/is_convertable = is_convertable_to_cult(L)
@@ -442,7 +442,7 @@ structure_check() searches for nearby cultist structures required for the invoca
invocation = "TOK-LYR RQA-NAP G'OLT-ULOFT!!"
req_cultists = 9
icon = 'icons/effects/96x96.dmi'
color = "#7D1717"
color = RUNE_COLOR_DARKRED
icon_state = "rune_large"
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
pixel_y = -32
@@ -479,9 +479,9 @@ structure_check() searches for nearby cultist structures required for the invoca
var/turf/T = get_turf(src)
sleep(40)
if(src)
color = "#FF0000"
color = RUNE_COLOR_RED
SSticker.mode.eldergod = FALSE
new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed
new /obj/singularity/narsie/large/cult(T) //Causes Nar-Sie to spawn even if the rune has been removed
/obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal.
if((istype(I, /obj/item/weapon/tome) && iscultist(user)))
@@ -502,7 +502,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived."
invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below
icon_state = "1"
color = "#C80000"
color = RUNE_COLOR_MEDIUMRED
var/static/revives_used = 0
/obj/effect/rune/raise_dead/examine(mob/user)
@@ -593,7 +593,7 @@ structure_check() searches for nearby cultist structures required for the invoca
invocation = "Ta'gh fara'qha fel d'amar det!"
icon_state = "5"
allow_excess_invokers = 1
color = "#4D94FF"
color = RUNE_COLOR_EMP
/obj/effect/rune/emp/invoke(var/list/invokers)
var/turf/E = get_turf(src)
@@ -623,7 +623,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
invocation = "Fwe'sh mah erl nyag r'ya!"
icon_state = "7"
color = "#7D1717"
color = RUNE_COLOR_DARKRED
rune_in_use = 0 //One at a time, please!
construct_invoke = 0
var/mob/living/affecting = null
@@ -649,9 +649,9 @@ structure_check() searches for nearby cultist structures required for the invoca
var/mob/living/user = invokers[1]
..()
var/turf/T = get_turf(src)
rune_in_use = 1
rune_in_use = TRUE
affecting = user
user.color = "#7D1717"
user.add_atom_colour(RUNE_COLOR_DARKRED, ADMIN_COLOUR_PRIORITY)
user.visible_message("<span class='warning'>[user] freezes statue-still, glowing an unearthly red.</span>", \
"<span class='cult'>You see what lies beyond. All is revealed. While this is a wondrous experience, your physical form will waste away in this state. Hurry...</span>")
user.ghostize(1)
@@ -659,7 +659,7 @@ structure_check() searches for nearby cultist structures required for the invoca
if(!affecting)
visible_message("<span class='warning'>[src] pulses gently before falling dark.</span>")
affecting = null //In case it's assigned to a number or something
rune_in_use = 0
rune_in_use = FALSE
return
affecting.apply_damage(0.1, BRUTE)
if(!(user in T))
@@ -669,9 +669,9 @@ structure_check() searches for nearby cultist structures required for the invoca
if(user.key)
user.visible_message("<span class='warning'>[user] slowly relaxes, the glow around [user.p_them()] dimming.</span>", \
"<span class='danger'>You are re-united with your physical form. [src] releases its hold over you.</span>")
user.color = initial(user.color)
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY, RUNE_COLOR_DARKRED)
user.Weaken(3)
rune_in_use = 0
rune_in_use = FALSE
affecting = null
return
if(user.stat == UNCONSCIOUS)
@@ -679,14 +679,14 @@ structure_check() searches for nearby cultist structures required for the invoca
var/mob/dead/observer/G = user.get_ghost()
to_chat(G, "<span class='cultitalic'>You feel the link between you and your body weakening... you must hurry!</span>")
if(user.stat == DEAD)
user.color = initial(user.color)
rune_in_use = 0
user.remove_atom_colour(ADMIN_COLOUR_PRIORITY, RUNE_COLOR_DARKRED)
rune_in_use = FALSE
affecting = null
var/mob/dead/observer/G = user.get_ghost()
to_chat(G, "<span class='cultitalic'><b>You suddenly feel your physical form pass on. [src]'s exertion has killed you!</b></span>")
return
sleep(1)
rune_in_use = 0
rune_in_use = FALSE
//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
/obj/effect/rune/wall
@@ -694,7 +694,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "when invoked, makes a temporary invisible wall to block passage. Can be invoked again to reverse this."
invocation = "Khari'd! Eske'te tannin!"
icon_state = "1"
color = "#C80000"
color = RUNE_COLOR_MEDIUMRED
CanAtmosPass = ATMOS_PASS_DENSITY
var/density_timer
var/recharging = FALSE
@@ -753,7 +753,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/wall/proc/recharge()
recharging = FALSE
add_atom_colour("#C80000", FIXED_COLOUR_PRIORITY)
add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY)
/obj/effect/rune/wall/proc/update_state()
deltimer(density_timer)
@@ -764,10 +764,10 @@ structure_check() searches for nearby cultist structures required for the invoca
shimmer.alpha = 60
shimmer.color = "#701414"
add_overlay(shimmer)
add_atom_colour("#FF0000", FIXED_COLOUR_PRIORITY)
add_atom_colour(RUNE_COLOR_RED, FIXED_COLOUR_PRIORITY)
else
cut_overlays()
add_atom_colour("#C80000", FIXED_COLOUR_PRIORITY)
add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY)
//Rite of Joined Souls: Summons a single cultist.
/obj/effect/rune/summon
@@ -777,7 +777,7 @@ structure_check() searches for nearby cultist structures required for the invoca
req_cultists = 2
allow_excess_invokers = 1
icon_state = "5"
color = "#00FF00"
color = RUNE_COLOR_SUMMON
/obj/effect/rune/summon/invoke(var/list/invokers)
var/mob/living/user = invokers[1]
@@ -822,7 +822,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "boils the blood of non-believers who can see the rune, rapidly dealing extreme amounts of damage. Requires 3 invokers."
invocation = "Dedo ol'btoh!"
icon_state = "4"
color = "#C80000"
color = RUNE_COLOR_MEDIUMRED
light_color = LIGHT_COLOR_LAVA
req_cultists = 3
construct_invoke = 0
@@ -889,7 +889,7 @@ structure_check() searches for nearby cultist structures required for the invoca
invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this
icon_state = "6"
construct_invoke = 0
color = "#C80000"
color = RUNE_COLOR_MEDIUMRED
var/ghost_limit = 5
var/ghosts = 0
@@ -962,4 +962,4 @@ structure_check() searches for nearby cultist structures required for the invoca
"<span class='cultlarge'>Your link to the world fades. Your form breaks apart.</span>")
for(var/obj/I in new_human)
new_human.dropItemToGround(I, TRUE)
new_human.dust()
new_human.dust()
+1 -1
View File
@@ -49,7 +49,7 @@
/obj/item/weapon/paper/talisman/teleport
cultist_name = "Talisman of Teleportation"
cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
color = "#551A8B" // purple
color = RUNE_COLOR_TELEPORT
invocation = "Sas'so c'arta forbici!"
health_cost = 5
creation_time = 80
+4 -1
View File
@@ -210,13 +210,16 @@
var/datum/action/innate/seek_master/SM = new()
SM.Grant(newstruct)
newstruct.key = target.key
var/obj/screen/alert/bloodsense/BS
if(newstruct.mind && ((stoner && iscultist(stoner)) || cultoverride) && SSticker && SSticker.mode)
SSticker.mode.add_cultist(newstruct.mind, 0)
BS = newstruct.alerts.Find("bloodsense")
if(iscultist(stoner) || cultoverride)
to_chat(newstruct, "<b>You are still bound to serve the cult[stoner ? " and [stoner]":""], follow their orders and help them complete their goals at all costs.</b>")
else if(stoner)
to_chat(newstruct, "<b>You are still bound to serve your creator, [stoner], follow their orders and help them complete their goals at all costs.</b>")
var/obj/screen/alert/bloodsense/BS = newstruct.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
BS = newstruct.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
if(BS)
BS.Cviewer = newstruct
newstruct.cancel_camera()
-3
View File
@@ -25,9 +25,6 @@
if(istype(I, /obj/item/stack/spacecash))
var/obj/item/stack/spacecash/C = I
value = C.value * C.amount
if(istype(I, /obj/item/weapon/coin))
var/obj/item/weapon/coin/C = I
value = C.value
if(value)
SSshuttle.points += value
to_chat(user, "<span class='notice'>You deposit [I]. The station now has [SSshuttle.points] credits.</span>")
+2 -1
View File
@@ -43,7 +43,8 @@
/obj/item/weapon/grenade/chem_grenade/glitter/pink = 1,
/obj/item/weapon/grenade/chem_grenade/glitter/blue = 1,
/obj/item/weapon/grenade/chem_grenade/glitter/white = 1,
/obj/item/toy/eightball = 2)
/obj/item/toy/eightball = 2,
/obj/item/toy/windupToolbox = 2)
light_color = LIGHT_COLOR_GREEN
+1
View File
@@ -12,6 +12,7 @@
max_integrity = 350
armor = list(melee = 30, bullet = 30, laser = 20, energy = 20, bomb = 10, bio = 100, rad = 100, fire = 80, acid = 70)
CanAtmosPass = ATMOS_PASS_DENSITY
flags = PREVENT_CLICK_UNDER
var/secondsElectrified = 0
var/shockedby = list()
+1 -3
View File
@@ -26,8 +26,6 @@ Possible to do for anyone motivated enough:
#define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2
GLOBAL_LIST_EMPTY(holopads)
#define HOLOPAD_MODE RANGE_BASED
/obj/machinery/holopad
@@ -295,7 +293,7 @@ GLOBAL_LIST_EMPTY(holopads)
Hologram.Impersonation = user
Hologram.language_holder = user.get_language_holder()
Hologram.copy_known_languages_from(user,replace = TRUE)
Hologram.mouse_opacity = 0//So you can't click on it.
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
+23 -5
View File
@@ -48,6 +48,7 @@
var/icon_deny //Icon_state when vending!
var/seconds_electrified = 0 //Shock customers like an airlock.
var/shoot_inventory = 0 //Fire items at customers! We're broken!
var/shoot_inventory_chance = 2
var/shut_up = 0 //Stop spouting those godawful pitches!
var/extended_inventory = 0 //can we access the hidden inventory?
var/scan_id = 1
@@ -561,7 +562,7 @@
speak(slogan)
last_slogan = world.time
if(shoot_inventory && prob(2))
if(shoot_inventory && prob(shoot_inventory_chance))
throw_item()
@@ -592,7 +593,7 @@
if(!target)
return 0
for(var/datum/data/vending_product/R in product_records)
for(var/datum/data/vending_product/R in shuffle(product_records))
if(R.amount <= 0) //Try to use a record that actually has something to dump.
continue
var/dump_path = R.product_path
@@ -605,19 +606,22 @@
if(!throw_item)
return 0
pre_throw(throw_item)
throw_item.throw_at(target, 16, 3)
visible_message("<span class='danger'>[src] launches [throw_item] at [target]!</span>")
return 1
/obj/machinery/vending/proc/pre_throw(obj/item/I)
return
/obj/machinery/vending/proc/shock(mob/user, prb)
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
return FALSE
if(!prob(prb))
return FALSE
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(5, 1, src)
s.start()
do_sparks(5, TRUE, src)
var/tmp/check_range = TRUE
if(electrocute_mob(user, get_area(src), src, 0.7, check_range))
return TRUE
@@ -864,6 +868,11 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/item/weapon/storage/fancy/cigarettes/cigars = 1, /obj/item/weapon/storage/fancy/cigarettes/cigars/havana = 1, /obj/item/weapon/storage/fancy/cigarettes/cigars/cohiba = 1)
refill_canister = /obj/item/weapon/vending_refill/cigarette
/obj/machinery/vending/cigarette/pre_throw(obj/item/I)
if(istype(I, /obj/item/weapon/lighter))
var/obj/item/weapon/lighter/L = I
L.set_lit(TRUE)
/obj/machinery/vending/medical
name = "\improper NanoMed Plus"
desc = "Medical drug dispenser."
@@ -919,6 +928,15 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
resistance_flags = FIRE_PROOF
/obj/machinery/vending/security/pre_throw(obj/item/I)
if(istype(I, /obj/item/weapon/grenade))
var/obj/item/weapon/grenade/G = I
G.preprime()
else if(istype(I, /obj/item/device/flashlight))
var/obj/item/device/flashlight/F = I
F.on = TRUE
F.update_brightness()
/obj/machinery/vending/hydronutrients
name = "\improper NutriMax"
desc = "A plant nutrients vendor."
-614
View File
@@ -18,620 +18,6 @@
..()
QDEL_IN(src, 10)
/obj/effect/overlay/temp
icon_state = "nothing"
anchored = 1
layer = ABOVE_MOB_LAYER
mouse_opacity = 0
var/duration = 10 //in deciseconds
var/randomdir = TRUE
var/timerid
/obj/effect/overlay/temp/Destroy()
. = ..()
deltimer(timerid)
/obj/effect/overlay/temp/Initialize()
. = ..()
if(randomdir)
setDir(pick(GLOB.cardinal))
timerid = QDEL_IN(src, duration)
/obj/effect/overlay/temp/ex_act()
return
/obj/effect/overlay/temp/dir_setting
randomdir = FALSE
/obj/effect/overlay/temp/dir_setting/Initialize(mapload, set_dir)
if(set_dir)
setDir(set_dir)
. = ..()
/obj/effect/overlay/temp/dir_setting/bloodsplatter
icon = 'icons/effects/blood.dmi'
duration = 5
randomdir = FALSE
layer = BELOW_MOB_LAYER
var/splatter_type = "splatter"
/obj/effect/overlay/temp/dir_setting/bloodsplatter/Initialize(mapload, set_dir)
if(set_dir in GLOB.diagonals)
icon_state = "[splatter_type][pick(1, 2, 6)]"
else
icon_state = "[splatter_type][pick(3, 4, 5)]"
. = ..()
var/target_pixel_x = 0
var/target_pixel_y = 0
switch(set_dir)
if(NORTH)
target_pixel_y = 16
if(SOUTH)
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
if(EAST)
target_pixel_x = 16
if(WEST)
target_pixel_x = -16
if(NORTHEAST)
target_pixel_x = 16
target_pixel_y = 16
if(NORTHWEST)
target_pixel_x = -16
target_pixel_y = 16
if(SOUTHEAST)
target_pixel_x = 16
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
if(SOUTHWEST)
target_pixel_x = -16
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter
splatter_type = "xsplatter"
/obj/effect/overlay/temp/dir_setting/speedbike_trail
name = "speedbike trails"
icon_state = "ion_fade"
layer = BELOW_MOB_LAYER
duration = 10
randomdir = 0
/obj/effect/overlay/temp/dir_setting/firing_effect
icon = 'icons/effects/effects.dmi'
icon_state = "firing_effect"
duration = 2
/obj/effect/overlay/temp/dir_setting/firing_effect/setDir(newdir)
switch(newdir)
if(NORTH)
layer = BELOW_MOB_LAYER
pixel_x = rand(-3,3)
pixel_y = rand(4,6)
if(SOUTH)
pixel_x = rand(-3,3)
pixel_y = rand(-1,1)
else
pixel_x = rand(-1,1)
pixel_y = rand(-1,1)
..()
/obj/effect/overlay/temp/dir_setting/firing_effect/energy
icon_state = "firing_effect_energy"
duration = 3
/obj/effect/overlay/temp/dir_setting/firing_effect/magic
icon_state = "shieldsparkles"
duration = 3
/obj/effect/overlay/temp/dir_setting/ninja
name = "ninja shadow"
icon = 'icons/mob/mob.dmi'
icon_state = "uncloak"
duration = 9
/obj/effect/overlay/temp/dir_setting/ninja/cloak
icon_state = "cloak"
/obj/effect/overlay/temp/dir_setting/ninja/shadow
icon_state = "shadow"
/obj/effect/overlay/temp/dir_setting/ninja/phase
name = "ninja energy"
icon_state = "phasein"
/obj/effect/overlay/temp/dir_setting/ninja/phase/out
icon_state = "phaseout"
/obj/effect/overlay/temp/dir_setting/wraith
name = "blood"
icon = 'icons/mob/mob.dmi'
icon_state = "phase_shift2"
duration = 12
/obj/effect/overlay/temp/dir_setting/wraith/out
icon_state = "phase_shift"
/obj/effect/overlay/temp/dir_setting/tailsweep
icon_state = "tailsweep"
duration = 4
/obj/effect/overlay/temp/wizard
name = "water"
icon = 'icons/mob/mob.dmi'
icon_state = "reappear"
duration = 5
/obj/effect/overlay/temp/wizard/out
icon_state = "liquify"
duration = 12
/obj/effect/overlay/temp/monkeyify
icon = 'icons/mob/mob.dmi'
icon_state = "h2monkey"
duration = 22
/obj/effect/overlay/temp/monkeyify/humanify
icon_state = "monkey2h"
/obj/effect/overlay/temp/borgflash
icon = 'icons/mob/mob.dmi'
icon_state = "blspell"
duration = 5
/obj/effect/overlay/temp/guardian
randomdir = 0
/obj/effect/overlay/temp/guardian/phase
duration = 5
icon_state = "phasein"
/obj/effect/overlay/temp/guardian/phase/out
icon_state = "phaseout"
/obj/effect/overlay/temp/decoy
desc = "It's a decoy!"
duration = 15
/obj/effect/overlay/temp/decoy/Initialize(mapload, atom/mimiced_atom)
. = ..()
alpha = initial(alpha)
if(mimiced_atom)
name = mimiced_atom.name
appearance = mimiced_atom.appearance
setDir(mimiced_atom.dir)
mouse_opacity = 0
/obj/effect/overlay/temp/decoy/fading/Initialize(mapload, atom/mimiced_atom)
. = ..()
animate(src, alpha = 0, time = duration)
/obj/effect/overlay/temp/decoy/fading/fivesecond
duration = 50
/obj/effect/overlay/temp/small_smoke
icon_state = "smoke"
duration = 50
/obj/effect/overlay/temp/fire
icon = 'icons/effects/fire.dmi'
icon_state = "3"
duration = 20
/obj/effect/overlay/temp/cult
randomdir = 0
duration = 10
/obj/effect/overlay/temp/cult/sparks
randomdir = 1
name = "blood sparks"
icon_state = "bloodsparkles"
/obj/effect/overlay/temp/cult/blood // The traditional teleport
name = "blood jaunt"
duration = 12
icon_state = "bloodin"
/obj/effect/overlay/temp/cult/blood/out
icon_state = "bloodout"
/obj/effect/overlay/temp/dir_setting/cult/phase // The veil shifter teleport
name = "phase glow"
duration = 7
icon_state = "cultin"
/obj/effect/overlay/temp/dir_setting/cult/phase/out
icon_state = "cultout"
/obj/effect/overlay/temp/cult/sac
name = "maw of Nar-Sie"
icon_state = "sacconsume"
/obj/effect/overlay/temp/cult/door
name = "unholy glow"
icon_state = "doorglow"
layer = CLOSED_FIREDOOR_LAYER //above closed doors
/obj/effect/overlay/temp/cult/door/unruned
icon_state = "unruneddoorglow"
/obj/effect/overlay/temp/cult/turf
name = "unholy glow"
icon_state = "wallglow"
layer = ABOVE_NORMAL_TURF_LAYER
/obj/effect/overlay/temp/cult/turf/floor
icon_state = "floorglow"
duration = 5
/obj/effect/overlay/temp/ratvar
name = "ratvar's light"
icon = 'icons/effects/clockwork_effects.dmi'
duration = 8
randomdir = 0
layer = ABOVE_NORMAL_TURF_LAYER
/obj/effect/overlay/temp/ratvar/door
icon_state = "ratvardoorglow"
layer = CLOSED_DOOR_LAYER //above closed doors
/obj/effect/overlay/temp/ratvar/door/window
icon_state = "ratvarwindoorglow"
layer = ABOVE_WINDOW_LAYER
/obj/effect/overlay/temp/ratvar/beam
icon_state = "ratvarbeamglow"
/obj/effect/overlay/temp/ratvar/beam/door
layer = CLOSED_DOOR_LAYER
/obj/effect/overlay/temp/ratvar/beam/grille
layer = BELOW_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/beam/itemconsume
layer = HIGH_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/beam/falsewall
layer = OBJ_LAYER
/obj/effect/overlay/temp/ratvar/beam/catwalk
layer = LATTICE_LAYER
/obj/effect/overlay/temp/ratvar/wall
icon_state = "ratvarwallglow"
/obj/effect/overlay/temp/ratvar/wall/false
layer = OBJ_LAYER
/obj/effect/overlay/temp/ratvar/floor
icon_state = "ratvarfloorglow"
/obj/effect/overlay/temp/ratvar/floor/catwalk
layer = LATTICE_LAYER
/obj/effect/overlay/temp/ratvar/window
icon_state = "ratvarwindowglow"
layer = ABOVE_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/window/single
icon_state = "ratvarwindowglow_s"
/obj/effect/overlay/temp/ratvar/gear
icon_state = "ratvargearglow"
layer = BELOW_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/grille
icon_state = "ratvargrilleglow"
layer = BELOW_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/grille/broken
icon_state = "ratvarbrokengrilleglow"
/obj/effect/overlay/temp/ratvar/mending_mantra
layer = ABOVE_MOB_LAYER
duration = 20
alpha = 200
icon_state = "mending_mantra"
light_range = 1.5
light_color = "#1E8CE1"
/obj/effect/overlay/temp/ratvar/mending_mantra/Initialize(mapload)
. = ..()
transform = matrix()*2
var/matrix/M = transform
M.Turn(90)
animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL)
/obj/effect/overlay/temp/ratvar/volt_hit
name = "volt blast"
layer = ABOVE_MOB_LAYER
duration = 5
icon_state = "volt_hit"
light_range = 1.5
light_power = 2
light_color = LIGHT_COLOR_ORANGE
var/mob/user
var/damage = 20
/obj/effect/overlay/temp/ratvar/volt_hit/Initialize(mapload, caster, multiplier)
if(multiplier)
damage *= multiplier
duration = max(round(damage * 0.2), 1)
. = ..()
/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
. = ..()
user = caster
if(user)
var/matrix/M = new
M.Turn(Get_Angle(src, user))
transform = M
INVOKE_ASYNC(src, .proc/volthit)
/obj/effect/overlay/temp/ratvar/volt_hit/proc/volthit()
if(user)
Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray)
var/hit_amount = 0
var/turf/T = get_turf(src)
for(var/mob/living/L in T)
if(is_servant_of_ratvar(L))
continue
var/obj/item/I = L.null_rod_check()
if(I)
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
continue
L.visible_message("<span class='warning'>[L] is struck by a [name]!</span>", "<span class='userdanger'>You're struck by a [name]!</span>")
L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!"))
add_logs(user, L, "struck with a volt blast")
hit_amount++
for(var/obj/mecha/M in T)
if(M.occupant)
if(is_servant_of_ratvar(M.occupant))
continue
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
M.visible_message("<span class='warning'>[M] is struck by a [name]!</span>")
M.take_damage(damage, BURN, 0, 0)
hit_amount++
if(hit_amount)
playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1)
else
playsound(src, "sparks", 50, 1)
/obj/effect/overlay/temp/ratvar/ocular_warden
name = "warden's gaze"
layer = ABOVE_MOB_LAYER
icon_state = "warden_gaze"
duration = 3
/obj/effect/overlay/temp/ratvar/ocular_warden/Initialize()
. = ..()
pixel_x = rand(-8, 8)
pixel_y = rand(-10, 10)
animate(src, alpha = 0, time = 3, easing = EASE_OUT)
/obj/effect/overlay/temp/ratvar/spearbreak
icon = 'icons/effects/64x64.dmi'
icon_state = "ratvarspearbreak"
layer = BELOW_MOB_LAYER
pixel_y = -16
pixel_x = -16
/obj/effect/overlay/temp/ratvar/geis_binding
icon_state = "geisbinding"
/obj/effect/overlay/temp/ratvar/geis_binding/top
icon_state = "geisbinding_top"
/obj/effect/overlay/temp/ratvar/component
icon = 'icons/obj/clockwork_objects.dmi'
icon_state = "belligerent_eye"
layer = ABOVE_MOB_LAYER
duration = 10
/obj/effect/overlay/temp/ratvar/component/Initialize()
. = ..()
transform = matrix()*0.75
pixel_x = rand(-10, 10)
pixel_y = rand(-10, -2)
animate(src, pixel_y = pixel_y + 10, alpha = 50, time = 10, easing = EASE_OUT)
/obj/effect/overlay/temp/ratvar/component/cogwheel
icon_state = "vanguard_cogwheel"
/obj/effect/overlay/temp/ratvar/component/capacitor
icon_state = "geis_capacitor"
/obj/effect/overlay/temp/ratvar/component/alloy
icon_state = "replicant_alloy"
/obj/effect/overlay/temp/ratvar/component/ansible
icon_state = "hierophant_ansible"
/obj/effect/overlay/temp/ratvar/sigil
name = "glowing circle"
icon_state = "sigildull"
/obj/effect/overlay/temp/ratvar/sigil/transgression
color = "#FAE48C"
layer = ABOVE_MOB_LAYER
duration = 70
light_range = 5
light_power = 2
light_color = "#FAE48C"
/obj/effect/overlay/temp/ratvar/sigil/transgression/Initialize()
. = ..()
var/oldtransform = transform
animate(src, transform = matrix()*2, time = 5)
animate(transform = oldtransform, alpha = 0, time = 65)
/obj/effect/overlay/temp/ratvar/sigil/vitality
color = "#1E8CE1"
icon_state = "sigilactivepulse"
layer = ABOVE_MOB_LAYER
light_range = 1.4
light_power = 0.5
light_color = "#1E8CE1"
/obj/effect/overlay/temp/ratvar/sigil/accession
color = "#AF0AAF"
layer = ABOVE_MOB_LAYER
duration = 70
icon_state = "sigilactiveoverlay"
alpha = 0
/obj/effect/overlay/temp/revenant
name = "spooky lights"
icon_state = "purplesparkles"
/obj/effect/overlay/temp/revenant/cracks
name = "glowing cracks"
icon_state = "purplecrack"
duration = 6
/obj/effect/overlay/temp/gravpush
name = "gravity wave"
icon_state = "shieldsparkles"
duration = 5
/obj/effect/overlay/temp/telekinesis
name = "telekinetic force"
icon_state = "empdisable"
duration = 5
/obj/effect/overlay/temp/emp
name = "emp sparks"
icon_state = "empdisable"
/obj/effect/overlay/temp/emp/pulse
name = "emp pulse"
icon_state = "emppulse"
duration = 8
randomdir = 0
/obj/effect/overlay/temp/gib_animation
icon = 'icons/mob/mob.dmi'
duration = 15
/obj/effect/overlay/temp/gib_animation/Initialize(mapload, gib_icon)
icon_state = gib_icon // Needs to be before ..() so icon is correct
. = ..()
/obj/effect/overlay/temp/gib_animation/ex_act(severity)
return //so the overlay isn't deleted by the explosion that gibbed the mob.
/obj/effect/overlay/temp/gib_animation/animal
icon = 'icons/mob/animal.dmi'
/obj/effect/overlay/temp/dust_animation
icon = 'icons/mob/mob.dmi'
duration = 15
/obj/effect/overlay/temp/dust_animation/Initialize(mapload, dust_icon)
icon_state = dust_icon // Before ..() so the correct icon is flick()'d
. = ..()
/obj/effect/overlay/temp/mummy_animation
icon = 'icons/mob/mob.dmi'
icon_state = "mummy_revive"
duration = 20
/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
name = "healing glow"
icon_state = "heal"
duration = 15
/obj/effect/overlay/temp/heal/Initialize(mapload, colour)
if(colour)
color = colour
. = ..()
pixel_x = rand(-12, 12)
pixel_y = rand(-9, 0)
/obj/effect/overlay/temp/kinetic_blast
name = "kinetic explosion"
icon = 'icons/obj/projectiles.dmi'
icon_state = "kinetic_blast"
layer = ABOVE_ALL_MOB_LAYER
duration = 4
/obj/effect/overlay/temp/explosion
name = "explosion"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion"
pixel_x = -32
pixel_y = -32
duration = 8
/obj/effect/overlay/temp/explosion/fast
icon_state = "explosionfast"
duration = 4
/obj/effect/overlay/temp/blob
name = "blob"
icon_state = "blob_attack"
alpha = 140
randomdir = 0
duration = 6
/obj/effect/overlay/temp/impact_effect
icon_state = "impact_bullet"
duration = 5
/obj/effect/overlay/temp/impact_effect/Initialize(mapload, atom/target, obj/item/projectile/P)
if(target == P.original) //the projectile hit the target originally clicked
pixel_x = P.p_x + target.pixel_x - 16 + rand(-4,4)
pixel_y = P.p_y + target.pixel_y - 16 + rand(-4,4)
else
pixel_x = target.pixel_x + rand(-4,4)
pixel_y = target.pixel_y + rand(-4,4)
. = ..()
/obj/effect/overlay/temp/impact_effect/red_laser
icon_state = "impact_laser"
duration = 4
/obj/effect/overlay/temp/impact_effect/red_laser/wall
icon_state = "impact_laser_wall"
duration = 10
/obj/effect/overlay/temp/impact_effect/blue_laser
icon_state = "impact_laser_blue"
duration = 4
/obj/effect/overlay/temp/impact_effect/green_laser
icon_state = "impact_laser_green"
duration = 4
/obj/effect/overlay/temp/impact_effect/purple_laser
icon_state = "impact_laser_purple"
duration = 4
/obj/effect/overlay/temp/impact_effect/ion
icon_state = "shieldsparkles"
duration = 6
/obj/effect/overlay/temp/heart
name = "heart"
icon = 'icons/mob/animal.dmi'
icon_state = "heart"
duration = 25
/obj/effect/overlay/temp/heart/Initialize(mapload)
. = ..()
pixel_x = rand(-4,4)
pixel_y = rand(-4,4)
animate(src, pixel_y = pixel_y + 32, alpha = 0, time = 25)
/obj/effect/overlay/palmtree_r
name = "Palm tree"
icon = 'icons/misc/beach2.dmi'
@@ -0,0 +1,218 @@
//temporary visual effects(/obj/effect/overlay/temp) used by clockcult stuff
/obj/effect/overlay/temp/ratvar
name = "ratvar's light"
icon = 'icons/effects/clockwork_effects.dmi'
duration = 8
randomdir = 0
layer = ABOVE_NORMAL_TURF_LAYER
/obj/effect/overlay/temp/ratvar/door
icon_state = "ratvardoorglow"
layer = CLOSED_DOOR_LAYER //above closed doors
/obj/effect/overlay/temp/ratvar/door/window
icon_state = "ratvarwindoorglow"
layer = ABOVE_WINDOW_LAYER
/obj/effect/overlay/temp/ratvar/beam
icon_state = "ratvarbeamglow"
/obj/effect/overlay/temp/ratvar/beam/door
layer = CLOSED_DOOR_LAYER
/obj/effect/overlay/temp/ratvar/beam/grille
layer = BELOW_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/beam/itemconsume
layer = HIGH_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/beam/falsewall
layer = OBJ_LAYER
/obj/effect/overlay/temp/ratvar/beam/catwalk
layer = LATTICE_LAYER
/obj/effect/overlay/temp/ratvar/wall
icon_state = "ratvarwallglow"
/obj/effect/overlay/temp/ratvar/wall/false
layer = OBJ_LAYER
/obj/effect/overlay/temp/ratvar/floor
icon_state = "ratvarfloorglow"
/obj/effect/overlay/temp/ratvar/floor/catwalk
layer = LATTICE_LAYER
/obj/effect/overlay/temp/ratvar/window
icon_state = "ratvarwindowglow"
layer = ABOVE_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/window/single
icon_state = "ratvarwindowglow_s"
/obj/effect/overlay/temp/ratvar/gear
icon_state = "ratvargearglow"
layer = BELOW_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/grille
icon_state = "ratvargrilleglow"
layer = BELOW_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/grille/broken
icon_state = "ratvarbrokengrilleglow"
/obj/effect/overlay/temp/ratvar/mending_mantra
layer = ABOVE_MOB_LAYER
duration = 20
alpha = 200
icon_state = "mending_mantra"
light_range = 1.5
light_color = "#1E8CE1"
/obj/effect/overlay/temp/ratvar/mending_mantra/Initialize(mapload)
. = ..()
transform = matrix()*2
var/matrix/M = transform
M.Turn(90)
animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL)
/obj/effect/overlay/temp/ratvar/volt_hit
name = "volt blast"
layer = ABOVE_MOB_LAYER
duration = 5
icon_state = "volt_hit"
light_range = 1.5
light_power = 2
light_color = LIGHT_COLOR_ORANGE
var/mob/user
var/damage = 20
/obj/effect/overlay/temp/ratvar/volt_hit/Initialize(mapload, caster, multiplier)
if(multiplier)
damage *= multiplier
duration = max(round(damage * 0.2), 1)
. = ..()
/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
. = ..()
user = caster
if(user)
var/matrix/M = new
M.Turn(Get_Angle(src, user))
transform = M
INVOKE_ASYNC(src, .proc/volthit)
/obj/effect/overlay/temp/ratvar/volt_hit/proc/volthit()
if(user)
Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray)
var/hit_amount = 0
var/turf/T = get_turf(src)
for(var/mob/living/L in T)
if(is_servant_of_ratvar(L))
continue
var/obj/item/I = L.null_rod_check()
if(I)
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
continue
L.visible_message("<span class='warning'>[L] is struck by a [name]!</span>", "<span class='userdanger'>You're struck by a [name]!</span>")
L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!"))
add_logs(user, L, "struck with a volt blast")
hit_amount++
for(var/obj/mecha/M in T)
if(M.occupant)
if(is_servant_of_ratvar(M.occupant))
continue
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
M.visible_message("<span class='warning'>[M] is struck by a [name]!</span>")
M.take_damage(damage, BURN, 0, 0)
hit_amount++
if(hit_amount)
playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1)
else
playsound(src, "sparks", 50, 1)
/obj/effect/overlay/temp/ratvar/ocular_warden
name = "warden's gaze"
layer = ABOVE_MOB_LAYER
icon_state = "warden_gaze"
duration = 3
/obj/effect/overlay/temp/ratvar/ocular_warden/Initialize()
. = ..()
pixel_x = rand(-8, 8)
pixel_y = rand(-10, 10)
animate(src, alpha = 0, time = 3, easing = EASE_OUT)
/obj/effect/overlay/temp/ratvar/spearbreak
icon = 'icons/effects/64x64.dmi'
icon_state = "ratvarspearbreak"
layer = BELOW_MOB_LAYER
pixel_y = -16
pixel_x = -16
/obj/effect/overlay/temp/ratvar/geis_binding
icon_state = "geisbinding"
/obj/effect/overlay/temp/ratvar/geis_binding/top
icon_state = "geisbinding_top"
/obj/effect/overlay/temp/ratvar/component
icon = 'icons/obj/clockwork_objects.dmi'
icon_state = "belligerent_eye"
layer = ABOVE_MOB_LAYER
duration = 10
/obj/effect/overlay/temp/ratvar/component/Initialize()
. = ..()
transform = matrix()*0.75
pixel_x = rand(-10, 10)
pixel_y = rand(-10, -2)
animate(src, pixel_y = pixel_y + 10, alpha = 50, time = 10, easing = EASE_OUT)
/obj/effect/overlay/temp/ratvar/component/cogwheel
icon_state = "vanguard_cogwheel"
/obj/effect/overlay/temp/ratvar/component/capacitor
icon_state = "geis_capacitor"
/obj/effect/overlay/temp/ratvar/component/alloy
icon_state = "replicant_alloy"
/obj/effect/overlay/temp/ratvar/component/ansible
icon_state = "hierophant_ansible"
/obj/effect/overlay/temp/ratvar/sigil
name = "glowing circle"
icon_state = "sigildull"
/obj/effect/overlay/temp/ratvar/sigil/transgression
color = "#FAE48C"
layer = ABOVE_MOB_LAYER
duration = 70
light_range = 5
light_power = 2
light_color = "#FAE48C"
/obj/effect/overlay/temp/ratvar/sigil/transgression/Initialize()
. = ..()
var/oldtransform = transform
animate(src, transform = matrix()*2, time = 5)
animate(transform = oldtransform, alpha = 0, time = 65)
/obj/effect/overlay/temp/ratvar/sigil/vitality
color = "#1E8CE1"
icon_state = "sigilactivepulse"
layer = ABOVE_MOB_LAYER
light_range = 1.4
light_power = 0.5
light_color = "#1E8CE1"
/obj/effect/overlay/temp/ratvar/sigil/accession
color = "#AF0AAF"
layer = ABOVE_MOB_LAYER
duration = 70
icon_state = "sigilactiveoverlay"
alpha = 0
@@ -0,0 +1,144 @@
//temporary visual effects(/obj/effect/overlay/temp) used by cult stuff
/obj/effect/overlay/temp/cult
icon = 'icons/effects/cult_effects.dmi'
randomdir = 0
duration = 10
/obj/effect/overlay/temp/cult/sparks
randomdir = 1
name = "blood sparks"
icon_state = "bloodsparkles"
/obj/effect/overlay/temp/cult/blood // The traditional teleport
name = "blood jaunt"
duration = 12
icon_state = "bloodin"
/obj/effect/overlay/temp/cult/blood/out
icon_state = "bloodout"
/obj/effect/overlay/temp/dir_setting/cult/phase // The veil shifter teleport
name = "phase glow"
duration = 7
icon_state = "cultin"
/obj/effect/overlay/temp/dir_setting/cult/phase/out
icon_state = "cultout"
/obj/effect/overlay/temp/cult/sac
name = "maw of Nar-Sie"
icon_state = "sacconsume"
/obj/effect/overlay/temp/cult/door
name = "unholy glow"
icon_state = "doorglow"
layer = CLOSED_FIREDOOR_LAYER //above closed doors
/obj/effect/overlay/temp/cult/door/unruned
icon_state = "unruneddoorglow"
/obj/effect/overlay/temp/cult/turf
name = "unholy glow"
icon_state = "wallglow"
layer = ABOVE_NORMAL_TURF_LAYER
/obj/effect/overlay/temp/cult/turf/floor
icon_state = "floorglow"
duration = 5
//visuals for runes being magically created
/obj/effect/overlay/temp/cult/rune_spawn
icon_state = "runeouter"
alpha = 0
var/turnedness = 179 //179 turns counterclockwise, 181 turns clockwise
/obj/effect/overlay/temp/cult/rune_spawn/Initialize(mapload, set_duration, set_color)
if(isnum(set_duration))
duration = set_duration
if(set_color)
add_atom_colour(set_color, FIXED_COLOUR_PRIORITY)
. = ..()
var/oldtransform = transform
transform = matrix()*2
var/matrix/M = transform
M.Turn(turnedness)
transform = M
animate(src, alpha = 255, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
animate(src, transform = oldtransform, time = duration, flags = ANIMATION_PARALLEL)
/obj/effect/overlay/temp/cult/rune_spawn/rune1
icon_state = "rune1words"
turnedness = 181
/obj/effect/overlay/temp/cult/rune_spawn/rune1/inner
icon_state = "rune1inner"
turnedness = 179
/obj/effect/overlay/temp/cult/rune_spawn/rune1/center
icon_state = "rune1center"
/obj/effect/overlay/temp/cult/rune_spawn/rune2
icon_state = "rune2words"
turnedness = 181
/obj/effect/overlay/temp/cult/rune_spawn/rune2/inner
icon_state = "rune2inner"
turnedness = 179
/obj/effect/overlay/temp/cult/rune_spawn/rune2/center
icon_state = "rune2center"
/obj/effect/overlay/temp/cult/rune_spawn/rune3
icon_state = "rune3words"
turnedness = 181
/obj/effect/overlay/temp/cult/rune_spawn/rune3/inner
icon_state = "rune3inner"
turnedness = 179
/obj/effect/overlay/temp/cult/rune_spawn/rune3/center
icon_state = "rune3center"
/obj/effect/overlay/temp/cult/rune_spawn/rune4
icon_state = "rune4words"
turnedness = 181
/obj/effect/overlay/temp/cult/rune_spawn/rune4/inner
icon_state = "rune4inner"
turnedness = 179
/obj/effect/overlay/temp/cult/rune_spawn/rune4/center
icon_state = "rune4center"
/obj/effect/overlay/temp/cult/rune_spawn/rune5
icon_state = "rune5words"
turnedness = 181
/obj/effect/overlay/temp/cult/rune_spawn/rune5/inner
icon_state = "rune5inner"
turnedness = 179
/obj/effect/overlay/temp/cult/rune_spawn/rune5/center
icon_state = "rune5center"
/obj/effect/overlay/temp/cult/rune_spawn/rune6
icon_state = "rune6words"
turnedness = 181
/obj/effect/overlay/temp/cult/rune_spawn/rune6/inner
icon_state = "rune6inner"
turnedness = 179
/obj/effect/overlay/temp/cult/rune_spawn/rune6/center
icon_state = "rune6center"
/obj/effect/overlay/temp/cult/rune_spawn/rune7
icon_state = "rune7words"
turnedness = 181
/obj/effect/overlay/temp/cult/rune_spawn/rune7/inner
icon_state = "rune7inner"
turnedness = 179
/obj/effect/overlay/temp/cult/rune_spawn/rune7/center
icon_state = "rune7center"
@@ -0,0 +1,312 @@
//unsorted miscellaneous temporary visuals
/obj/effect/overlay/temp/dir_setting/bloodsplatter
icon = 'icons/effects/blood.dmi'
duration = 5
randomdir = FALSE
layer = BELOW_MOB_LAYER
var/splatter_type = "splatter"
/obj/effect/overlay/temp/dir_setting/bloodsplatter/Initialize(mapload, set_dir)
if(set_dir in GLOB.diagonals)
icon_state = "[splatter_type][pick(1, 2, 6)]"
else
icon_state = "[splatter_type][pick(3, 4, 5)]"
. = ..()
var/target_pixel_x = 0
var/target_pixel_y = 0
switch(set_dir)
if(NORTH)
target_pixel_y = 16
if(SOUTH)
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
if(EAST)
target_pixel_x = 16
if(WEST)
target_pixel_x = -16
if(NORTHEAST)
target_pixel_x = 16
target_pixel_y = 16
if(NORTHWEST)
target_pixel_x = -16
target_pixel_y = 16
if(SOUTHEAST)
target_pixel_x = 16
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
if(SOUTHWEST)
target_pixel_x = -16
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter
splatter_type = "xsplatter"
/obj/effect/overlay/temp/dir_setting/speedbike_trail
name = "speedbike trails"
icon_state = "ion_fade"
layer = BELOW_MOB_LAYER
duration = 10
randomdir = 0
/obj/effect/overlay/temp/dir_setting/firing_effect
icon = 'icons/effects/effects.dmi'
icon_state = "firing_effect"
duration = 2
/obj/effect/overlay/temp/dir_setting/firing_effect/setDir(newdir)
switch(newdir)
if(NORTH)
layer = BELOW_MOB_LAYER
pixel_x = rand(-3,3)
pixel_y = rand(4,6)
if(SOUTH)
pixel_x = rand(-3,3)
pixel_y = rand(-1,1)
else
pixel_x = rand(-1,1)
pixel_y = rand(-1,1)
..()
/obj/effect/overlay/temp/dir_setting/firing_effect/energy
icon_state = "firing_effect_energy"
duration = 3
/obj/effect/overlay/temp/dir_setting/firing_effect/magic
icon_state = "shieldsparkles"
duration = 3
/obj/effect/overlay/temp/dir_setting/ninja
name = "ninja shadow"
icon = 'icons/mob/mob.dmi'
icon_state = "uncloak"
duration = 9
/obj/effect/overlay/temp/dir_setting/ninja/cloak
icon_state = "cloak"
/obj/effect/overlay/temp/dir_setting/ninja/shadow
icon_state = "shadow"
/obj/effect/overlay/temp/dir_setting/ninja/phase
name = "ninja energy"
icon_state = "phasein"
/obj/effect/overlay/temp/dir_setting/ninja/phase/out
icon_state = "phaseout"
/obj/effect/overlay/temp/dir_setting/wraith
name = "blood"
icon = 'icons/mob/mob.dmi'
icon_state = "phase_shift2"
duration = 12
/obj/effect/overlay/temp/dir_setting/wraith/out
icon_state = "phase_shift"
/obj/effect/overlay/temp/dir_setting/tailsweep
icon_state = "tailsweep"
duration = 4
/obj/effect/overlay/temp/wizard
name = "water"
icon = 'icons/mob/mob.dmi'
icon_state = "reappear"
duration = 5
/obj/effect/overlay/temp/wizard/out
icon_state = "liquify"
duration = 12
/obj/effect/overlay/temp/monkeyify
icon = 'icons/mob/mob.dmi'
icon_state = "h2monkey"
duration = 22
/obj/effect/overlay/temp/monkeyify/humanify
icon_state = "monkey2h"
/obj/effect/overlay/temp/borgflash
icon = 'icons/mob/mob.dmi'
icon_state = "blspell"
duration = 5
/obj/effect/overlay/temp/guardian
randomdir = 0
/obj/effect/overlay/temp/guardian/phase
duration = 5
icon_state = "phasein"
/obj/effect/overlay/temp/guardian/phase/out
icon_state = "phaseout"
/obj/effect/overlay/temp/decoy
desc = "It's a decoy!"
duration = 15
/obj/effect/overlay/temp/decoy/Initialize(mapload, atom/mimiced_atom)
. = ..()
alpha = initial(alpha)
if(mimiced_atom)
name = mimiced_atom.name
appearance = mimiced_atom.appearance
setDir(mimiced_atom.dir)
mouse_opacity = 0
/obj/effect/overlay/temp/decoy/fading/Initialize(mapload, atom/mimiced_atom)
. = ..()
animate(src, alpha = 0, time = duration)
/obj/effect/overlay/temp/decoy/fading/fivesecond
duration = 50
/obj/effect/overlay/temp/small_smoke
icon_state = "smoke"
duration = 50
/obj/effect/overlay/temp/fire
icon = 'icons/effects/fire.dmi'
icon_state = "3"
duration = 20
/obj/effect/overlay/temp/revenant
name = "spooky lights"
icon_state = "purplesparkles"
/obj/effect/overlay/temp/revenant/cracks
name = "glowing cracks"
icon_state = "purplecrack"
duration = 6
/obj/effect/overlay/temp/gravpush
name = "gravity wave"
icon_state = "shieldsparkles"
duration = 5
/obj/effect/overlay/temp/telekinesis
name = "telekinetic force"
icon_state = "empdisable"
duration = 5
/obj/effect/overlay/temp/emp
name = "emp sparks"
icon_state = "empdisable"
/obj/effect/overlay/temp/emp/pulse
name = "emp pulse"
icon_state = "emppulse"
duration = 8
randomdir = 0
/obj/effect/overlay/temp/gib_animation
icon = 'icons/mob/mob.dmi'
duration = 15
/obj/effect/overlay/temp/gib_animation/Initialize(mapload, gib_icon)
icon_state = gib_icon // Needs to be before ..() so icon is correct
. = ..()
/obj/effect/overlay/temp/gib_animation/animal
icon = 'icons/mob/animal.dmi'
/obj/effect/overlay/temp/dust_animation
icon = 'icons/mob/mob.dmi'
duration = 15
/obj/effect/overlay/temp/dust_animation/Initialize(mapload, dust_icon)
icon_state = dust_icon // Before ..() so the correct icon is flick()'d
. = ..()
/obj/effect/overlay/temp/mummy_animation
icon = 'icons/mob/mob.dmi'
icon_state = "mummy_revive"
duration = 20
/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
name = "healing glow"
icon_state = "heal"
duration = 15
/obj/effect/overlay/temp/heal/Initialize(mapload, set_color)
if(set_color)
add_atom_colour(set_color, FIXED_COLOUR_PRIORITY)
. = ..()
pixel_x = rand(-12, 12)
pixel_y = rand(-9, 0)
/obj/effect/overlay/temp/kinetic_blast
name = "kinetic explosion"
icon = 'icons/obj/projectiles.dmi'
icon_state = "kinetic_blast"
layer = ABOVE_ALL_MOB_LAYER
duration = 4
/obj/effect/overlay/temp/explosion
name = "explosion"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion"
pixel_x = -32
pixel_y = -32
duration = 8
/obj/effect/overlay/temp/explosion/fast
icon_state = "explosionfast"
duration = 4
/obj/effect/overlay/temp/blob
name = "blob"
icon_state = "blob_attack"
alpha = 140
randomdir = 0
duration = 6
/obj/effect/overlay/temp/impact_effect
icon_state = "impact_bullet"
duration = 5
/obj/effect/overlay/temp/impact_effect/Initialize(mapload, atom/target, obj/item/projectile/P)
if(target == P.original) //the projectile hit the target originally clicked
pixel_x = P.p_x + target.pixel_x - 16 + rand(-4,4)
pixel_y = P.p_y + target.pixel_y - 16 + rand(-4,4)
else
pixel_x = target.pixel_x + rand(-4,4)
pixel_y = target.pixel_y + rand(-4,4)
. = ..()
/obj/effect/overlay/temp/impact_effect/red_laser
icon_state = "impact_laser"
duration = 4
/obj/effect/overlay/temp/impact_effect/red_laser/wall
icon_state = "impact_laser_wall"
duration = 10
/obj/effect/overlay/temp/impact_effect/blue_laser
icon_state = "impact_laser_blue"
duration = 4
/obj/effect/overlay/temp/impact_effect/green_laser
icon_state = "impact_laser_green"
duration = 4
/obj/effect/overlay/temp/impact_effect/purple_laser
icon_state = "impact_laser_purple"
duration = 4
/obj/effect/overlay/temp/impact_effect/ion
icon_state = "shieldsparkles"
duration = 6
/obj/effect/overlay/temp/heart
name = "heart"
icon = 'icons/mob/animal.dmi'
icon_state = "heart"
duration = 25
/obj/effect/overlay/temp/heart/Initialize(mapload)
. = ..()
pixel_x = rand(-4,4)
pixel_y = rand(-4,4)
animate(src, pixel_y = pixel_y + 32, alpha = 0, time = 25)
@@ -0,0 +1,37 @@
//temporary visual effects
/obj/effect/overlay/temp
icon_state = "nothing"
anchored = 1
layer = ABOVE_MOB_LAYER
mouse_opacity = 0
var/duration = 10 //in deciseconds
var/randomdir = TRUE
var/timerid
/obj/effect/overlay/temp/Initialize()
. = ..()
if(randomdir)
setDir(pick(GLOB.cardinal))
timerid = QDEL_IN(src, duration)
/obj/effect/overlay/temp/Destroy()
. = ..()
deltimer(timerid)
/obj/effect/overlay/temp/singularity_act()
return
/obj/effect/overlay/temp/singularity_pull()
return
/obj/effect/overlay/temp/ex_act()
return
/obj/effect/overlay/temp/dir_setting
randomdir = FALSE
/obj/effect/overlay/temp/dir_setting/Initialize(mapload, set_dir)
if(set_dir)
setDir(set_dir)
. = ..()
+3
View File
@@ -528,6 +528,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/obj/item/throw_impact(atom/A)
if(A && !QDELETED(A))
if(is_hot() && isliving(A))
var/mob/living/L = A
L.IgniteMob()
var/itempush = 1
if(w_class < 4)
itempush = 0 //too light to push anything
@@ -504,6 +504,113 @@
S.change_head_color(color2)
dropped = TRUE
//Peacekeeper Cyborg Projectile Dampenening Field
/obj/item/borg/projectile_dampen
name = "Hyperkinetic Dampening projector"
desc = "A device that projects a dampening field that weakens kinetic energy above a certain threshold. <span class='boldnotice'>Projects a field that drains power per second \
while active, that will weaken and slow damaging projectiles inside its field.</span> Still being a prototype, it tends to induce a charge on ungrounded metallic surfaces."
icon = 'icons/obj/device.dmi'
icon_state = "shield"
var/maxenergy = 1500
var/energy = 1500
var/energy_recharge = 7.5
var/energy_recharge_cyborg_drain_coefficient = 0.4
var/cyborg_cell_critical_percentage = 0.05
var/mob/living/silicon/robot/host = null
var/datum/proximity_monitor/advanced/dampening_field
var/projectile_damage_coefficient = 0.5
var/projectile_damage_tick_ecost_coefficient = 2 //Lasers get half their damage chopped off, drains 50 power/tick. Note that fields are processed 5 times per second.
var/projectile_speed_coefficient = 1.5 //Higher the coefficient slower the projectile.
var/projectile_tick_speed_ecost = 15
var/current_damage_dampening = 0
var/list/obj/item/projectile/tracked
var/image/projectile_effect
var/field_radius = 3
/obj/item/borg/projectile_dampen/debug
maxenergy = 50000
energy = 50000
energy_recharge = 5000
/obj/item/borg/projectile_dampen/Initialize()
. = ..()
projectile_effect = image('icons/effects/fields.dmi', "projectile_dampen_effect")
tracked = list()
icon_state = "shield0"
START_PROCESSING(SSfastprocess, src)
/obj/item/borg/projectile_dampen/Destroy()
STOP_PROCESSING(SSfastprocess, src)
return ..()
/obj/item/borg/projectile_dampen/attack_self(mob/user)
var/active = FALSE
if(!istype(dampening_field))
activate_field()
active = TRUE
else
deactivate_field()
active = FALSE
to_chat(user, "<span class='boldnotice'>You [active? "activate":"deactivate"] the [src].</span>")
icon_state = "[initial(icon_state)][active]"
/obj/item/borg/projectile_dampen/proc/activate_field()
if(!istype(dampening_field))
dampening_field = make_field(/datum/proximity_monitor/advanced/peaceborg_dampener, list("current_range" = field_radius, "host" = src, "projector" = src))
/obj/item/borg/projectile_dampen/proc/deactivate_field()
QDEL_NULL(dampening_field)
visible_message("<span class='warning'>The [src] shuts off!</span>")
for(var/obj/item/projectile/P in tracked)
restore_projectile(P)
/obj/item/borg/projectile_dampen/process()
process_recharge()
process_usage()
update_location()
/obj/item/borg/projectile_dampen/proc/update_location()
if(dampening_field)
dampening_field.HandleMove()
/obj/item/borg/projectile_dampen/proc/process_usage()
var/usage = 0
for(var/I in tracked)
if(!tracked[I]) //No damage
continue
usage += projectile_tick_speed_ecost
usage += (current_damage_dampening * projectile_damage_tick_ecost_coefficient)
energy = Clamp(energy - usage, 0, maxenergy)
if(energy <= 0)
deactivate_field()
visible_message("<span class='warning'>The [src] blinks \"ENERGY DEPLETED\"</span>")
/obj/item/borg/projectile_dampen/proc/process_recharge()
if(!istype(host))
energy = Clamp(energy + energy_recharge, 0, maxenergy)
return
if((host.cell.charge >= (host.cell.maxcharge * cyborg_cell_critical_percentage)) && (energy < maxenergy))
host.cell.use(energy_recharge*energy_recharge_cyborg_drain_coefficient)
energy += energy_recharge
/obj/item/borg/projectile_dampen/proc/dampen_projectile(obj/item/projectile/P, track_projectile = TRUE)
if(tracked[P])
return
if(track_projectile)
tracked[P] = P.damage
current_damage_dampening += P.damage
P.damage *= projectile_damage_coefficient
P.speed *= projectile_speed_coefficient
P.add_overlay(projectile_effect)
/obj/item/borg/projectile_dampen/proc/restore_projectile(obj/item/projectile/P)
tracked -= P
P.damage *= (1/projectile_damage_coefficient)
P.speed *= (1/projectile_speed_coefficient)
P.cut_overlay(projectile_effect)
current_damage_dampening -= P.damage
/**********************************************************************
HUD/SIGHT things
***********************************************************************/
+22
View File
@@ -279,6 +279,28 @@
resistance_flags = FLAMMABLE
/obj/item/toy/windupToolbox
name = "windup toolbox"
desc = "A replica toolbox that rumbles when you turn the key"
icon_state = "his_grace"
item_state = "artistic_toolbox"
var/active = FALSE
icon = 'icons/obj/weapons.dmi'
attack_verb = list("robusted")
/obj/item/toy/windupToolbox/attack_self(mob/user)
if(!active)
icon_state = "his_grace_awakened"
to_chat(user, "<span class='warning'>You wind up [src], it begins to rumble.</span>")
active = TRUE
addtimer(CALLBACK(src, .proc/stopRumble), 600)
else
to_chat(user, "[src] is already active.")
/obj/item/toy/windupToolbox/proc/stopRumble()
icon_state = initial(icon_state)
active = FALSE
/*
* Subtype of Double-Bladed Energy Swords
*/
@@ -472,8 +472,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
flags = CONDUCT
slot_flags = SLOT_BELT
var/lit = 0
var/fancy = TRUE
heat = 1500
resistance_flags = FIRE_PROOF
light_color = LIGHT_COLOR_FIRE
/obj/item/weapon/lighter/update_icon()
if(lit)
@@ -484,37 +486,28 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/weapon/lighter/ignition_effect(atom/A, mob/user)
. = "<span class='rose'>With a single flick of their wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool.</span>"
/obj/item/weapon/lighter/greyscale
name = "cheap lighter"
desc = "A cheap-as-free lighter."
icon_state = "lighter"
/obj/item/weapon/lighter/greyscale/Initialize()
. = ..()
add_atom_colour(color2hex(randomColor(1)), FIXED_COLOUR_PRIORITY)
update_icon()
/obj/item/weapon/lighter/greyscale/update_icon()
cut_overlays()
var/mutable_appearance/base_overlay = mutable_appearance(icon,"[initial(icon_state)]_base")
base_overlay.appearance_flags = RESET_COLOR //the edging doesn't change color
/obj/item/weapon/lighter/proc/set_lit(new_lit)
lit = new_lit
if(lit)
base_overlay.icon_state = "[initial(icon_state)]_on"
add_overlay(base_overlay)
/obj/item/weapon/lighter/greyscale/ignition_effect(atom/A, mob/user)
. = "<span class='notice'>After some fiddling, [user] manages to light [A] with [src].</span>"
force = 5
damtype = "fire"
hitsound = 'sound/items/welder.ogg'
attack_verb = list("burnt", "singed")
set_light(1)
START_PROCESSING(SSobj, src)
else
hitsound = "swing_hit"
force = 0
attack_verb = null //human_defense.dm takes care of it
set_light(0)
STOP_PROCESSING(SSobj, src)
update_icon()
/obj/item/weapon/lighter/attack_self(mob/living/user)
if(user.is_holding(src))
if(!lit)
lit = 1
update_icon()
force = 5
damtype = "fire"
hitsound = 'sound/items/welder.ogg'
attack_verb = list("burnt", "singed")
if(!istype(src, /obj/item/weapon/lighter/greyscale))
set_lit(TRUE)
if(fancy)
user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.", "<span class='notice'>Without even breaking stride, you flip open and lights [src] in one smooth movement.</span>")
else
var/prot = FALSE
@@ -534,20 +527,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM
user.apply_damage(5, BURN, hitzone)
user.visible_message("<span class='warning'>After a few attempts, [user] manages to light [src] - however, [user.p_they()] burn their finger in the process.</span>", "<span class='warning'>You burn yourself while lighting the lighter!</span>")
set_light(1)
START_PROCESSING(SSobj, src)
else
lit = 0
update_icon()
hitsound = "swing_hit"
force = 0
attack_verb = null //human_defense.dm takes care of it
if(!istype(src, /obj/item/weapon/lighter/greyscale))
set_lit(FALSE)
if(fancy)
user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.", "<span class='notice'>You quietly shut off [src] without even looking at what you're doing. Wow.</span>")
else
user.visible_message("[user] quietly shuts off [src].", "<span class='notice'>You quietly shut off [src].")
set_light(0)
STOP_PROCESSING(SSobj, src)
else
. = ..()
@@ -562,7 +547,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(M == user)
cig.attackby(src, user)
else
if(!istype(src, /obj/item/weapon/lighter/greyscale))
if(fancy)
cig.light("<span class='rose'>[user] whips the [name] out and holds it for [M]. [user.p_their(TRUE)] arm is as steady as the unflickering flame they light \the [cig] with.</span>")
else
cig.light("<span class='notice'>[user] holds the [name] out for [M], and lights the [cig.name].</span>")
@@ -575,6 +560,30 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/weapon/lighter/is_hot()
return lit * heat
/obj/item/weapon/lighter/greyscale
name = "cheap lighter"
desc = "A cheap-as-free lighter."
icon_state = "lighter"
fancy = FALSE
/obj/item/weapon/lighter/greyscale/Initialize()
. = ..()
add_atom_colour(color2hex(randomColor(1)), FIXED_COLOUR_PRIORITY)
update_icon()
/obj/item/weapon/lighter/greyscale/update_icon()
cut_overlays()
var/mutable_appearance/base_overlay = mutable_appearance(icon,"[initial(icon_state)]_base")
base_overlay.appearance_flags = RESET_COLOR //the edging doesn't change color
if(lit)
base_overlay.icon_state = "[initial(icon_state)]_on"
add_overlay(base_overlay)
/obj/item/weapon/lighter/greyscale/ignition_effect(atom/A, mob/user)
. = "<span class='notice'>After some fiddling, [user] manages to light [A] with [src].</span>"
///////////
//ROLLING//
///////////
@@ -50,9 +50,7 @@
M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"])
M.updateappearance(mutations_overlay_update=1)
log_attack(log_msg)
else
to_chat(user, "<span class='notice'>It appears that [M] does not have compatible DNA.</span>")
return
return TRUE
/obj/item/weapon/dnainjector/attack(mob/target, mob/user)
if(!user.IsAdvancedToolUser())
@@ -79,7 +77,9 @@
add_logs(user, target, "injected", src)
inject(target, user) //Now we actually do the heavy lifting.
if(!inject(target, user)) //Now we actually do the heavy lifting.
to_chat(user, "<span class='notice'>It appears that [target] does not have compatible DNA.</span>")
used = 1
icon_state = "dnainjector0"
desc += " This one is used up."
@@ -48,23 +48,27 @@
/obj/item/weapon/grenade/attack_self(mob/user)
if(!active)
if(clown_check(user))
to_chat(user, "<span class='warning'>You prime the [name]! [det_time/10] seconds!</span>")
playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1)
active = 1
icon_state = initial(icon_state) + "_active"
add_fingerprint(user)
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(bombturf)]"
GLOB.bombers += message
message_admins(message)
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].")
preprime(user)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.throw_mode_on()
spawn(det_time)
prime()
/obj/item/weapon/grenade/proc/preprime(mob/user)
if(user)
to_chat(user, "<span class='warning'>You prime the [name]! [det_time/10] seconds!</span>")
playsound(loc, 'sound/weapons/armbomb.ogg', 60, 1)
active = TRUE
icon_state = initial(icon_state) + "_active"
add_fingerprint(user)
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
if(user)
var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(bombturf)]"
GLOB.bombers += message
message_admins(message)
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].")
addtimer(CALLBACK(src, .proc/prime), det_time)
/obj/item/weapon/grenade/proc/prime()
@@ -104,4 +108,4 @@
if(damage && attack_type == PROJECTILE_ATTACK && prob(15))
owner.visible_message("<span class='danger'>[attack_text] hits [owner]'s [src], setting it off! What a shot!</span>")
prime()
return 1 //It hit the grenade, not them
return 1 //It hit the grenade, not them
@@ -18,6 +18,10 @@
plastic_overlay = mutable_appearance(icon, "[item_state]2")
..()
/obj/item/weapon/grenade/plastic/Initialize(mapload)
. = ..()
SET_SECONDARY_FLAG(src, NO_EMP_WIRES)
/obj/item/weapon/grenade/plastic/Destroy()
qdel(nadeassembly)
nadeassembly = null
@@ -244,7 +244,7 @@
range_multiplier = 3
fire_mode = PCANNON_FIFO
throw_amount = 1
maxWeightClass = 100 //50 pies. :^)
maxWeightClass = 150 //50 pies. :^)
clumsyCheck = FALSE
/obj/item/weapon/pneumatic_cannon/pie/can_load_item(obj/item/I, mob/user)
@@ -252,3 +252,22 @@
return ..()
to_chat(user, "<span class='warning'>[src] only accepts pies!</span>")
return FALSE
/obj/item/weapon/pneumatic_cannon/pie/selfcharge
automatic = TRUE
var/charge_amount = 1
var/charge_ticks = 1
var/charge_tick = 0
maxWeightClass = 60 //20 pies.
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/Initialize()
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/weapon/pneumatic_cannon/pie/selfcharge/process()
if(++charge_tick >= charge_ticks)
fill_with_type(/obj/item/weapon/reagent_containers/food/snacks/pie, charge_amount)
@@ -140,6 +140,8 @@
item_state = "plasmaman_tank_belt"
slot_flags = SLOT_BELT
force = 5
volume = 3
w_class = WEIGHT_CLASS_SMALL //thanks i forgot this
/obj/item/weapon/tank/internals/plasmaman/belt/full/New()
..()
@@ -149,8 +149,8 @@
/obj/effect/mob_spawn/human/golem/attack_hand(mob/user)
if(isgolem(user) && can_transfer)
var/transfer = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
if(!transfer)
var/transfer_choice = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
if(transfer_choice != "Yes")
return
log_game("[user.ckey] golem-swapped into [src]")
user.visible_message("<span class='notice'>A faint light leaves [user], moving to [src] and animating it!</span>","<span class='notice'>You leave your old body behind, and transfer into [src]!</span>")
+6 -6
View File
@@ -440,7 +440,7 @@
dir = FULLTILE_WINDOW_DIR
max_integrity = 50
fulltile = 1
flags = NONE
flags = PREVENT_CLICK_UNDER
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile)
glass_amount = 2
@@ -454,7 +454,7 @@
dir = FULLTILE_WINDOW_DIR
max_integrity = 100
fulltile = 1
flags = NONE
flags = PREVENT_CLICK_UNDER
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile)
@@ -467,7 +467,7 @@
dir = FULLTILE_WINDOW_DIR
max_integrity = 1000
fulltile = 1
flags = NONE
flags = PREVENT_CLICK_UNDER
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile)
level = 3
@@ -481,7 +481,7 @@
icon_state = "tinted_window"
dir = FULLTILE_WINDOW_DIR
fulltile = 1
flags = NONE
flags = PREVENT_CLICK_UNDER
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile,/obj/structure/window/reinforced/highpressure/fulltile, /obj/structure/window/reinforced/tinted/fulltile/)
level = 3
@@ -504,7 +504,7 @@
max_integrity = 100
wtype = "shuttle"
fulltile = 1
flags = NONE
flags = PREVENT_CLICK_UNDER
reinf = 1
heat_resistance = 1600
armor = list(melee = 50, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 100, fire = 80, acid = 100)
@@ -583,7 +583,7 @@
smooth = SMOOTH_TRUE
canSmoothWith = null
fulltile = 1
flags = NONE
flags = PREVENT_CLICK_UNDER
dir = FULLTILE_WINDOW_DIR
max_integrity = 120
level = 3
+3 -3
View File
@@ -42,7 +42,7 @@
if (opacity)
has_opaque_atom = TRUE
return INITIALIZE_HINT_NORMAL
/turf/open/space/attack_ghost(mob/dead/observer/user)
@@ -177,7 +177,7 @@
ChangeTurf(/turf/open/floor/plating)
return TRUE
return FALSE
/turf/open/space/ReplaceWithLattice()
var/dest_x = destination_x
var/dest_y = destination_y
@@ -186,4 +186,4 @@
destination_x = dest_x
destination_y = dest_y
destination_z = dest_z
+19 -18
View File
@@ -92,39 +92,39 @@
LC.attackby(C,user)
return
coil.place_turf(src, user)
return 1
return TRUE
return 0
return FALSE
/turf/CanPass(atom/movable/mover, turf/target, height=1.5)
if(!target) return 0
if(!target) return FALSE
if(istype(mover)) // turf/Enter(...) will perform more advanced checks
return !density
else // Now, doing more detailed checks for air movement and air group formation
if(target.blocks_air||blocks_air)
return 0
return FALSE
for(var/obj/obstacle in src)
if(!obstacle.CanPass(mover, target, height))
return 0
return FALSE
for(var/obj/obstacle in target)
if(!obstacle.CanPass(mover, src, height))
return 0
return FALSE
return 1
return TRUE
/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
if (!mover)
return 1
return TRUE
// First, make sure it can leave its square
if(isturf(mover.loc))
// Nothing but border objects stop you from leaving a tile, only one loop is needed
for(var/obj/obstacle in mover.loc)
if(!obstacle.CheckExit(mover, src) && obstacle != mover && obstacle != forget)
mover.Bump(obstacle, 1)
return 0
return FALSE
var/list/large_dense = list()
//Next, check objects to block entry that are on the border
@@ -132,14 +132,14 @@
if(border_obstacle.flags & ON_BORDER)
if(!border_obstacle.CanPass(mover, mover.loc, 1) && (forget != border_obstacle))
mover.Bump(border_obstacle, 1)
return 0
return FALSE
else
large_dense += border_obstacle
//Then, check the turf itself
if (!src.CanPass(mover, src))
mover.Bump(src, 1)
return 0
return FALSE
//Finally, check objects/mobs to block entry that are not on the border
var/atom/movable/tompost_bump
@@ -151,8 +151,9 @@
top_layer = obstacle.layer
if(tompost_bump)
mover.Bump(tompost_bump,1)
return 0
return 1 //Nothing found to block so return success!
return FALSE
return TRUE //Nothing found to block so return success!
/turf/Entered(atom/movable/AM)
if(explosion_level && AM.ex_check(explosion_id))
@@ -185,7 +186,7 @@
O.make_unfrozen()
/turf/proc/is_plasteel_floor()
return 0
return FALSE
/turf/proc/levelupdate()
for(var/obj/O in src)
@@ -303,7 +304,7 @@
if(src_object.contents.len)
to_chat(usr, "<span class='notice'>You start dumping out the contents...</span>")
if(!do_after(usr,20,target=src_object))
return 0
return FALSE
var/list/things = src_object.contents.Copy()
var/datum/progressbar/progress = new(user, things.len, src)
@@ -311,7 +312,7 @@
sleep(1)
qdel(progress)
return 1
return TRUE
//////////////////////////////
//Distance procs
@@ -325,7 +326,7 @@
// possible. It results in more efficient (CPU-wise) pathing
// for bots and anything else that only moves in cardinal dirs.
/turf/proc/Distance_cardinal(turf/T)
if(!src || !T) return 0
if(!src || !T) return FALSE
return abs(x - T.x) + abs(y - T.y)
////////////////////////////////////////////////////
@@ -341,7 +342,7 @@
return(2)
/turf/proc/can_have_cabling()
return 1
return TRUE
/turf/proc/can_lay_cable()
return can_have_cabling() & !intact
-2
View File
@@ -81,7 +81,6 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/drop_dynex_bomb,
/client/proc/cinematic,
/client/proc/one_click_antag,
/client/proc/send_space_ninja,
/client/proc/cmd_admin_add_freeform_ai_law,
/client/proc/object_say,
/client/proc/toggle_random_events,
@@ -200,7 +199,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/get_dynex_power,
/client/proc/set_dynex_scale,
/client/proc/cinematic,
/client/proc/send_space_ninja,
/client/proc/cmd_admin_add_freeform_ai_law,
/client/proc/cmd_admin_create_centcom_report,
/client/proc/cmd_change_command_name,
+4
View File
@@ -108,7 +108,11 @@ GLOBAL_PROTECT(AdminProcCallCount)
return call(target, procname)(arglist(arguments))
/proc/IsAdminAdvancedProcCall()
#ifdef TESTING
return FALSE
#else
return usr && usr.client && GLOB.AdminProcCaller == usr.client.ckey
#endif
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
set category = "Debug"
+2 -3
View File
@@ -387,9 +387,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
if(L.name=="carpspawn")
ninja_spawn += L
new_character.equip_space_ninja()
new_character.internal = new_character.s_store
new_character.update_internals_hud_icon(1)
var/datum/antagonist/ninja/ninjadatum = new_character.mind.has_antag_datum(ANTAG_DATUM_NINJA)
ninjadatum.equip_space_ninja()
if(ninja_spawn.len)
var/obj/effect/landmark/ninja_spawn_here = pick(ninja_spawn)
new_character.loc = ninja_spawn_here.loc
@@ -153,8 +153,8 @@
return
var/datum/gas_mixture/air1 = AIR1
var/turf/T = get_turf(src)
if(isliving(occupant))
var/mob/living/mob_occupant
if(occupant)
var/mob/living/mob_occupant = occupant
if(mob_occupant.health >= 100) // Don't bother with fully healed people.
on = FALSE
update_icon()
@@ -176,8 +176,8 @@
if(beaker)
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(mob_occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
beaker.reagents.reaction(mob_occupant, VAPOR)
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases["o2"][MOLES] -= 2 / efficiency // Lets use gas for this.
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
reagent_transfer = 0
@@ -192,7 +192,7 @@
on = FALSE
update_icon()
return
if(isliving(occupant))
if(occupant)
var/mob/living/mob_occupant = occupant
var/cold_protection = 0
var/mob/living/carbon/human/H = occupant
@@ -244,7 +244,7 @@
..()
if(occupant)
if(on)
to_chat(user, "[occupant] is inside [src]!")
to_chat(user, "Someone's inside [src]!")
else
to_chat(user, "You can barely make out a form floating in [src].")
else
@@ -299,7 +299,7 @@
data["autoEject"] = autoeject
var/list/occupantData = list()
if(isliving(occupant))
if(occupant)
var/mob/living/mob_occupant = occupant
occupantData["name"] = mob_occupant.name
occupantData["stat"] = mob_occupant.stat
+309
View File
@@ -0,0 +1,309 @@
//Movable and easily code-modified fields! Allows for custom AOE effects that affect movement and anything inside of them, and can do custom turf effects!
//Supports automatic recalculation/reset on movement.
//If there's any way to make this less CPU intensive than I've managed, gimme a call or do it yourself! - kevinz000
//Field shapes
#define FIELD_NO_SHAPE 0 //Does not update turfs automatically
#define FIELD_SHAPE_RADIUS_SQUARE 1 //Uses current_range and square_depth_up/down
#define FIELD_SHAPE_CUSTOM_SQUARE 2 //Uses square_height and square_width and square_depth_up/down
//Proc to make fields. make_field(field_type, field_params_in_associative_list)
/proc/make_field(field_type, list/field_params, override_checks = FALSE, start_field = TRUE)
var/datum/proximity_monitor/advanced/F = new field_type()
if(!F.assume_params(field_params) && !override_checks)
QDEL_NULL(F)
if(!F.check_variables() && !override_checks)
QDEL_NULL(F)
if(start_field && (F || override_checks))
F.Initialize()
return F
/datum/proximity_monitor/advanced
var/name = "\improper Energy Field"
//Field setup specifications
var/field_shape = FIELD_NO_SHAPE
var/square_height = 0
var/square_width = 0
var/square_depth_up = 0
var/square_depth_down = 0
//Processing
var/requires_processing = FALSE
var/process_inner_turfs = FALSE //Don't do this unless it's absolutely necessary
var/process_edge_turfs = FALSE //Don't do this either unless it's absolutely necessary, you can just track what things are inside manually or on the initial setup.
var/setup_edge_turfs = FALSE //Setup edge turfs/all field turfs. Set either or both to ON when you need it, it's defaulting to off unless you do to save CPU.
var/setup_field_turfs = FALSE
var/list/turf/field_turfs = list()
var/list/turf/edge_turfs = list()
var/list/turf/field_turfs_new = list()
var/list/turf/edge_turfs_new = list()
/datum/proximity_monitor/advanced/New()
SSfields.register_new_field(src)
/datum/proximity_monitor/advanced/Destroy()
SSfields.unregister_field(src)
full_cleanup()
return ..()
/datum/proximity_monitor/advanced/proc/assume_params(list/field_params)
var/pass_check = TRUE
for(var/param in field_params)
if(vars[param] || isnull(vars[param]) || (param in vars))
vars[param] = field_params[param]
else
pass_check = FALSE
return pass_check
/datum/proximity_monitor/advanced/proc/check_variables()
var/pass = TRUE
if(field_shape == FIELD_NO_SHAPE) //If you're going to make a manually updated field you shouldn't be using automatic checks so don't.
pass = FALSE
if(current_range < 0 || square_height < 0 || square_width < 0 || square_depth_up < 0 || square_depth_down < 0)
pass = FALSE
if(!istype(host))
pass = FALSE
return pass
/datum/proximity_monitor/advanced/process()
if(process_inner_turfs)
for(var/turf/T in field_turfs)
process_inner_turf(T)
CHECK_TICK //Really crappy lagchecks, needs improvement once someone starts using processed fields.
if(process_edge_turfs)
for(var/turf/T in edge_turfs)
process_edge_turf(T)
CHECK_TICK //Same here.
/datum/proximity_monitor/advanced/proc/process_inner_turf(turf/T)
/datum/proximity_monitor/advanced/proc/process_edge_turf(turf/T)
/datum/proximity_monitor/advanced/proc/Initialize()
setup_field()
post_setup_field()
/datum/proximity_monitor/advanced/proc/full_cleanup() //Full cleanup for when you change something that would require complete resetting.
for(var/turf/T in edge_turfs)
cleanup_edge_turf(T)
for(var/turf/T in field_turfs)
cleanup_field_turf(T)
/datum/proximity_monitor/advanced/proc/recalculate_field(ignore_movement_check = FALSE) //Call every time the field moves (done automatically if you use update_center) or a setup specification is changed.
if(!(ignore_movement_check || ((host.loc != last_host_loc) && (field_shape != FIELD_NO_SHAPE))))
return
update_new_turfs()
var/list/turf/needs_setup = field_turfs_new.Copy()
if(setup_field_turfs)
for(var/turf/T in field_turfs)
if(!(T in needs_setup))
cleanup_field_turf(T)
else
needs_setup -= T
CHECK_TICK
for(var/turf/T in needs_setup)
setup_field_turf(T)
CHECK_TICK
if(setup_edge_turfs)
for(var/turf/T in edge_turfs)
cleanup_edge_turf(T)
CHECK_TICK
for(var/turf/T in edge_turfs_new)
setup_edge_turf(T)
CHECK_TICK
/datum/proximity_monitor/advanced/proc/field_turf_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F, turf/entering)
return TRUE
/datum/proximity_monitor/advanced/proc/field_turf_uncross(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_turf_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_turf_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_turf/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F, turf/entering)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_uncross(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
return TRUE
/datum/proximity_monitor/advanced/proc/field_edge_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
return TRUE
/datum/proximity_monitor/advanced/HandleMove()
var/atom/_host = host
var/atom/new_host_loc = _host.loc
if(last_host_loc != new_host_loc)
recalculate_field()
/datum/proximity_monitor/advanced/proc/post_setup_field()
/datum/proximity_monitor/advanced/proc/setup_field()
update_new_turfs()
if(setup_field_turfs)
for(var/turf/T in field_turfs_new)
setup_field_turf(T)
CHECK_TICK
if(setup_edge_turfs)
for(var/turf/T in edge_turfs_new)
setup_edge_turf(T)
CHECK_TICK
/datum/proximity_monitor/advanced/proc/cleanup_field_turf(turf/T)
qdel(field_turfs[T])
field_turfs -= T
/datum/proximity_monitor/advanced/proc/cleanup_edge_turf(turf/T)
qdel(edge_turfs[T])
edge_turfs -= T
/datum/proximity_monitor/advanced/proc/setup_field_turf(turf/T)
field_turfs[T] = new /obj/effect/abstract/proximity_checker/advanced/field_turf(T, src)
/datum/proximity_monitor/advanced/proc/setup_edge_turf(turf/T)
edge_turfs[T] = new /obj/effect/abstract/proximity_checker/advanced/field_edge(T, src)
/datum/proximity_monitor/advanced/proc/update_new_turfs()
if(!istype(host))
return FALSE
last_host_loc = host.loc
var/turf/center = get_turf(host)
field_turfs_new = list()
edge_turfs_new = list()
switch(field_shape)
if(FIELD_NO_SHAPE)
return FALSE
if(FIELD_SHAPE_RADIUS_SQUARE)
for(var/turf/T in block(locate(center.x-current_range,center.y-current_range,center.z-square_depth_down),locate(center.x+current_range, center.y+current_range,center.z+square_depth_up)))
field_turfs_new += T
edge_turfs_new = field_turfs_new.Copy()
if(current_range >= 1)
var/list/turf/center_turfs = list()
for(var/turf/T in block(locate(center.x-current_range+1,center.y-current_range+1,center.z-square_depth_down),locate(center.x+current_range-1, center.y+current_range-1,center.z+square_depth_up)))
center_turfs += T
for(var/turf/T in center_turfs)
edge_turfs_new -= T
if(FIELD_SHAPE_CUSTOM_SQUARE)
for(var/turf/T in block(locate(center.x-square_width,center.y-square_height,center.z-square_depth_down),locate(center.x+square_width, center.y+square_height,center.z+square_depth_up)))
field_turfs_new += T
edge_turfs_new = field_turfs_new.Copy()
if(square_height >= 1 && square_width >= 1)
var/list/turf/center_turfs = list()
for(var/turf/T in block(locate(center.x-square_width+1,center.y-square_height+1,center.z-square_depth_down),locate(center.x+square_width-1, center.y+square_height-1,center.z+square_depth_up)))
center_turfs += T
for(var/turf/T in center_turfs)
edge_turfs_new -= T
//Gets edge direction/corner, only works with square radius/WDH fields!
/datum/proximity_monitor/advanced/proc/get_edgeturf_direction(turf/T, turf/center_override = null)
var/turf/checking_from = get_turf(host)
if(istype(center_override))
checking_from = center_override
if(field_shape != FIELD_SHAPE_RADIUS_SQUARE && field_shape != FIELD_SHAPE_CUSTOM_SQUARE)
return
if(!(T in edge_turfs))
return
switch(field_shape)
if(FIELD_SHAPE_RADIUS_SQUARE)
if(((T.x == (checking_from.x + current_range)) || (T.x == (checking_from.x - current_range))) && ((T.y == (checking_from.y + current_range)) || (T.y == (checking_from.y - current_range))))
return get_dir(checking_from, T)
if(T.x == (checking_from.x + current_range))
return EAST
if(T.x == (checking_from.x - current_range))
return WEST
if(T.y == (checking_from.y - current_range))
return SOUTH
if(T.y == (checking_from.y + current_range))
return NORTH
if(FIELD_SHAPE_CUSTOM_SQUARE)
if(((T.x == (checking_from.x + square_width)) || (T.x == (checking_from.x - square_width))) && ((T.y == (checking_from.y + square_height)) || (T.y == (checking_from.y - square_height))))
return get_dir(checking_from, T)
if(T.x == (checking_from.x + square_width))
return EAST
if(T.x == (checking_from.x - square_width))
return WEST
if(T.y == (checking_from.y - square_height))
return SOUTH
if(T.y == (checking_from.y + square_height))
return NORTH
//DEBUG FIELDS
/datum/proximity_monitor/advanced/debug
name = "\improper Color Matrix Field"
field_shape = FIELD_SHAPE_RADIUS_SQUARE
current_range = 5
var/set_fieldturf_color = "#aaffff"
var/set_edgeturf_color = "#ffaaff"
setup_field_turfs = TRUE
setup_edge_turfs = TRUE
/datum/proximity_monitor/advanced/debug/recalculate_field()
..()
/datum/proximity_monitor/advanced/debug/post_setup_field()
..()
/datum/proximity_monitor/advanced/debug/setup_edge_turf(turf/T)
T.color = set_edgeturf_color
..()
/datum/proximity_monitor/advanced/debug/cleanup_edge_turf(turf/T)
T.color = initial(T.color)
..()
if(T in field_turfs)
T.color = set_fieldturf_color
/datum/proximity_monitor/advanced/debug/setup_field_turf(turf/T)
T.color = set_fieldturf_color
..()
/datum/proximity_monitor/advanced/debug/cleanup_field_turf(turf/T)
T.color = initial(T.color)
..()
//DEBUG FIELD ITEM
/obj/item/device/multitool/field_debug
name = "strange multitool"
desc = "Seems to project a colored field!"
var/list/field_params = list("field_shape" = FIELD_SHAPE_RADIUS_SQUARE, "current_range" = 5, "set_fieldturf_color" = "#aaffff", "set_edgeturf_color" = "#ffaaff")
var/field_type = /datum/proximity_monitor/advanced/debug
var/operating = FALSE
var/datum/proximity_monitor/advanced/current = null
/obj/item/device/multitool/field_debug/New()
START_PROCESSING(SSobj, src)
..()
/obj/item/device/multitool/field_debug/Destroy()
STOP_PROCESSING(SSobj, src)
QDEL_NULL(current)
..()
/obj/item/device/multitool/field_debug/proc/setup_debug_field()
var/list/new_params = field_params.Copy()
new_params["host"] = src
current = make_field(field_type, new_params)
/obj/item/device/multitool/field_debug/attack_self(mob/user)
operating = !operating
to_chat(user, "You turn the [src] [operating? "on":"off"].")
if(!istype(current) && operating)
setup_debug_field()
else if(!operating)
QDEL_NULL(current)
/obj/item/device/multitool/field_debug/on_mob_move()
check_turf(get_turf(src))
/obj/item/device/multitool/field_debug/process()
check_turf(get_turf(src))
/obj/item/device/multitool/field_debug/proc/check_turf(turf/T)
current.HandleMove()
+106
View File
@@ -0,0 +1,106 @@
//Projectile dampening field that slows projectiles and lowers their damage for an energy cost deducted every 1/5 second.
//Only use square radius for this!
/datum/proximity_monitor/advanced/peaceborg_dampener
name = "\improper Hyperkinetic Dampener Field"
requires_processing = TRUE
setup_edge_turfs = TRUE
setup_field_turfs = TRUE
field_shape = FIELD_SHAPE_RADIUS_SQUARE
var/static/image/edgeturf_south = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_south")
var/static/image/edgeturf_north = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_north")
var/static/image/edgeturf_west = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_west")
var/static/image/edgeturf_east = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_east")
var/static/image/northwest_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_northwest")
var/static/image/southwest_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_southwest")
var/static/image/northeast_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_northeast")
var/static/image/southeast_corner = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_southeast")
var/obj/item/borg/projectile_dampen/projector = null
var/list/obj/item/projectile/tracked
var/list/obj/item/projectile/staging
/datum/proximity_monitor/advanced/peaceborg_dampener/New()
tracked = list()
staging = list()
..()
/datum/proximity_monitor/advanced/peaceborg_dampener/process()
if(!istype(projector))
qdel(src)
var/list/ranged = list()
for(var/obj/item/projectile/P in range(current_range, get_turf(host)))
ranged += P
for(var/obj/item/projectile/P in tracked)
if(!(P in ranged) || !P.loc)
release_projectile(P)
for(var/mob/living/silicon/robot/R in range(current_range, get_turf(host)))
if(R.has_buckled_mobs())
for(var/mob/living/L in R.buckled_mobs)
L.visible_message("<span class='warning'>[L] is knocked off of [R] by the charge in [R]'s chassis induced by [name]!</span>") //I know it's bad.
L.Weaken(3)
R.unbuckle_mob(L)
do_sparks(5, 0, L)
..()
/datum/proximity_monitor/advanced/peaceborg_dampener/setup_edge_turf(turf/T)
..()
var/image/I = get_edgeturf_overlay(get_edgeturf_direction(T))
var/obj/effect/abstract/proximity_checker/advanced/F = edge_turfs[T]
F.appearance = I.appearance
F.invisibility = 0
F.layer = 5
/datum/proximity_monitor/advanced/peaceborg_dampener/cleanup_edge_turf(turf/T)
..()
/datum/proximity_monitor/advanced/peaceborg_dampener/proc/get_edgeturf_overlay(direction)
switch(direction)
if(NORTH)
return edgeturf_north
if(SOUTH)
return edgeturf_south
if(EAST)
return edgeturf_east
if(WEST)
return edgeturf_west
if(NORTHEAST)
return northeast_corner
if(NORTHWEST)
return northwest_corner
if(SOUTHEAST)
return southeast_corner
if(SOUTHWEST)
return southwest_corner
/datum/proximity_monitor/advanced/peaceborg_dampener/proc/capture_projectile(obj/item/projectile/P, track_projectile = TRUE)
if(P in tracked)
return
projector.dampen_projectile(P, track_projectile)
if(track_projectile)
tracked += P
/datum/proximity_monitor/advanced/peaceborg_dampener/proc/release_projectile(obj/item/projectile/P)
projector.restore_projectile(P)
tracked -= P
/datum/proximity_monitor/advanced/peaceborg_dampener/field_edge_uncrossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
if(!is_turf_in_field(get_turf(AM), src))
if(istype(AM, /obj/item/projectile))
if(AM in tracked)
release_projectile(AM)
else
capture_projectile(AM, FALSE)
return ..()
/datum/proximity_monitor/advanced/peaceborg_dampener/field_edge_crossed(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F)
if(istype(AM, /obj/item/projectile) && !(AM in tracked) && staging[AM] && !is_turf_in_field(staging[AM], src))
capture_projectile(AM)
staging -= AM
return ..()
/datum/proximity_monitor/advanced/peaceborg_dampener/field_edge_canpass(atom/movable/AM, obj/effect/abstract/proximity_checker/advanced/field_edge/F, turf/entering)
if(istype(AM, /obj/item/projectile))
staging[AM] = get_turf(AM)
. = ..()
if(!.)
staging -= AM //This one ain't goin' through.
+76
View File
@@ -0,0 +1,76 @@
/obj/effect/abstract/proximity_checker/advanced
name = "field"
desc = "Why can you see energy fields?!"
icon = null
icon_state = null
alpha = 0
invisibility = INVISIBILITY_ABSTRACT
flags = ABSTRACT|ON_BORDER
var/datum/proximity_monitor/advanced/parent = null
/obj/effect/abstract/proximity_checker/advanced/Initialize(mapload, _monitor)
if(_monitor)
parent = _monitor
return ..()
/obj/effect/abstract/proximity_checker/advanced/center
name = "field anchor"
desc = "No."
/obj/effect/abstract/proximity_checker/advanced/field_turf
name = "energy field"
desc = "Get off my turf!"
/obj/effect/abstract/proximity_checker/advanced/field_turf/CanPass(atom/movable/AM, turf/target, height)
if(parent)
return parent.field_turf_canpass(AM, src, target)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_turf/Crossed(atom/movable/AM)
if(parent)
return parent.field_turf_crossed(AM, src)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_turf/Uncross(atom/movable/AM)
if(parent)
return parent.field_turf_uncross(AM, src)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_turf/Uncrossed(atom/movable/AM)
if(parent)
return parent.field_turf_uncrossed(AM, src)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_edge
name = "energy field edge"
desc = "Edgy description here."
/obj/effect/abstract/proximity_checker/advanced/field_edge/CanPass(atom/movable/AM, turf/target, height)
if(parent)
return parent.field_edge_canpass(AM, src, target)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_edge/Crossed(atom/movable/AM)
if(parent)
return parent.field_edge_crossed(AM, src)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_edge/Uncross(atom/movable/AM)
if(parent)
return parent.field_edge_uncross(AM, src)
return TRUE
/obj/effect/abstract/proximity_checker/advanced/field_edge/Uncrossed(atom/movable/AM)
if(parent)
return parent.field_edge_uncrossed(AM, src)
return TRUE
/proc/is_turf_in_field(turf/T, datum/proximity_monitor/advanced/F) //Looking for ways to optimize this!
for(var/obj/effect/abstract/proximity_checker/advanced/O in T)
if(istype(O, /obj/effect/abstract/proximity_checker/advanced/field_edge))
if(O.parent == F)
return FIELD_EDGE
if(O.parent == F)
return FIELD_TURF
return NO_FIELD
@@ -135,7 +135,6 @@
/obj/item/weapon/reagent_containers/food/snacks/customizable/initialize_slice(obj/item/weapon/reagent_containers/food/snacks/slice, reagents_per_slice)
..()
slice.name = "[customname] [initial(slice.name)]"
slice.filling_color = filling_color
slice.update_overlays(src)
+3 -2
View File
@@ -215,8 +215,9 @@
/obj/item/weapon/reagent_containers/food/snacks/proc/initialize_slice(obj/item/weapon/reagent_containers/food/snacks/slice, reagents_per_slice)
slice.create_reagents(slice.volume)
reagents.trans_to(slice,reagents_per_slice)
if( name != initial(name) || desc != initial(desc) )
slice.name = "slice of [src]"
if(name != initial(name))
slice.name = "slice of [name]"
if(desc != initial(desc))
slice.desc = "[desc]"
/obj/item/weapon/reagent_containers/food/snacks/proc/generate_trash(atom/location)
@@ -174,7 +174,6 @@
var/mob/living/carbon/human/gibee = occupant
sourcejob = gibee.job
var/sourcenutriment = mob_occupant.nutrition / 15
var/sourcetotalreagents = mob_occupant.reagents.total_volume
var/gibtype = /obj/effect/decal/cleanable/blood/gibs
var/typeofmeat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human
var/typeofskin = /obj/item/stack/sheet/animalhide/human
@@ -207,7 +206,6 @@
newmeat.reagents.add_reagent ("nutriment", sourcenutriment / meat_produced) // Thehehe. Fat guys go first
if(sourcejob)
newmeat.subjectjob = sourcejob
src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / meat_produced, 1)) // Transfer all the reagents from the
allmeat[i] = newmeat
allskin = newskin
+9 -1
View File
@@ -2,7 +2,8 @@
#define BAD_ZLEVEL 1
#define BAD_AREA 2
#define ZONE_SET 3
#define BAD_COORDS 3
#define ZONE_SET 4
/area/shuttle/auxillary_base
name = "Auxillary Base"
@@ -149,6 +150,9 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
if(T.z != ZLEVEL_MINING)
return BAD_ZLEVEL
var/colony_radius = max(base_dock.width, base_dock.height)*0.5
if(T.x - colony_radius < 1 || T.x + colony_radius >= world.maxx || T.y - colony_radius < 1 || T.y + colony_radius >= world.maxx)
return BAD_COORDS //Avoid dropping the base too close to map boundaries, as it results in parts of it being left in space
var/list/area_counter = get_areas_in_range(colony_radius, T)
if(area_counter.len > 1) //Avoid smashing ruins unless you are inside a really big one
return BAD_AREA
@@ -195,6 +199,7 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
if(!do_after(user, 50, target = user)) //You get a few seconds to cancel if you do not want to drop there.
setting = FALSE
return
setting = FALSE
var/turf/T = get_turf(user)
var/obj/machinery/computer/auxillary_base/AB
@@ -212,6 +217,8 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
to_chat(user, "<span class='warning'>This uplink can only be used in a designed mining zone.</span>")
if(BAD_AREA)
to_chat(user, "<span class='warning'>Unable to acquire a targeting lock. Find an area clear of stuctures or entirely within one.</span>")
if(BAD_COORDS)
to_chat(user, "<span class='warning'>Location is too close to the edge of the station's scanning range. Move several paces away and try again.</span>")
if(ZONE_SET)
qdel(src)
@@ -347,4 +354,5 @@ obj/docking_port/stationary/public_mining_dock/onShuttleMove()
#undef BAD_ZLEVEL
#undef BAD_AREA
#undef BAD_COORDS
#undef ZONE_SET
@@ -1,5 +1,6 @@
//The chests dropped by mob spawner tendrils. Also contains associated loot.
/obj/structure/closet/crate/necropolis
name = "necropolis chest"
desc = "It's watching you closely."
@@ -820,7 +821,9 @@
timer = world.time + cooldown_time
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
chaser_timer = world.time + chaser_cooldown
new /obj/effect/overlay/temp/hierophant/chaser(get_turf(user), user, target, chaser_speed, friendly_fire_check)
var/obj/effect/overlay/temp/hierophant/chaser/C = new(get_turf(user), user, target, chaser_speed, friendly_fire_check)
C.damage = 30
C.monster_damage_boost = FALSE
add_logs(user, target, "fired a chaser at", src)
else
INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast
@@ -940,10 +943,10 @@
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(T, user)
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(source, user)
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE) //blasts produced will not hurt allies
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE) //No friendly fire, this is a utility tool
B.damage = 30
for(var/t in RANGE_TURFS(1, source))
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE) //but absolutely will hurt enemies
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE)
B.damage = 30
for(var/mob/living/L in range(1, source))
INVOKE_ASYNC(src, .proc/teleport_mob, source, L, T, user) //regardless, take all mobs near us along
@@ -1004,7 +1007,9 @@
for(var/i in 1 to range)
if(!J)
return
new /obj/effect/overlay/temp/hierophant/blast(J, user, friendly_fire_check)
var/obj/effect/overlay/temp/hierophant/blast/B = new(J, user, friendly_fire_check)
B.damage = 30
B.monster_damage_boost = FALSE
previousturf = J
J = get_step(previousturf, dir)
@@ -1015,4 +1020,5 @@
playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
for(var/t in RANGE_TURFS(1, T))
new /obj/effect/overlay/temp/hierophant/blast(t, user, friendly_fire_check)
var/obj/effect/overlay/temp/hierophant/blast/B = new(t, user, friendly_fire_check)
B.damage = 15 //keeps monster damage boost due to lower damage
@@ -17,4 +17,4 @@
/mob/living/carbon/alien/AdjustStunned(amount, updating = 1, ignore_canstun = 0)
. = ..()
if(!.)
move_delay_add = min(move_delay_add + round(amount / 2), 10)
move_delay_add = Clamp(move_delay_add + round(amount/2), 0, 10)
+1 -1
View File
@@ -823,7 +823,7 @@
/mob/living/proc/has_bane(banetype)
var/datum/antagonist/devil/devilInfo = is_devil(src)
return (banetype == devilInfo.bane)
return devilInfo && banetype == devilInfo.bane
/mob/living/proc/check_weakness(obj/item/weapon, mob/living/attacker)
if(mind && mind.has_antag_datum(ANTAG_DATUM_DEVIL))
+366 -357
View File
@@ -1,361 +1,370 @@
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null, armour_penetration, penetrated_text)
var/armor = getarmor(def_zone, attack_flag)
//the if "armor" check is because this is used for everything on /living, including humans
if(armor && armour_penetration)
armor = max(0, armor - armour_penetration)
if(penetrated_text)
to_chat(src, "<span class='userdanger'>[penetrated_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor was penetrated!</span>")
else if(armor >= 100)
if(absorb_text)
to_chat(src, "<span class='userdanger'>[absorb_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor absorbs the blow!</span>")
else if(armor > 0)
if(soften_text)
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor softens the blow!</span>")
return armor
/mob/living/proc/getarmor(def_zone, type)
return 0
//this returns the mob's protection against eye damage (number between -1 and 2)
/mob/living/proc/get_eye_protection()
return 0
//this returns the mob's protection against ear damage (0:no protection; 1: some ear protection; 2: has no ears)
/mob/living/proc/get_ear_protection()
return 0
/mob/living/proc/on_hit(obj/item/projectile/P)
return
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
var/armor = run_armor_check(def_zone, P.flag, "","",P.armour_penetration)
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
return P.on_hit(src, armor)
/mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
return 0
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class()
if(istype(I,/obj/item/weapon)) //If the item is a weapon...
var/obj/item/weapon/W = I
dtype = W.damtype
if (W.throwforce > 0) //If the weapon's throwforce is greater than zero...
if (W.throwhitsound) //...and throwhitsound is defined...
playsound(loc, W.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
else if(W.hitsound) //Otherwise, if the weapon's hitsound is defined...
playsound(loc, W.hitsound, volume, 1, -1) //...play the weapon's hitsound.
else if(!W.throwhitsound) //Otherwise, if throwhitsound isn't defined...
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
if(!blocked)
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
"<span class='userdanger'>[src] has been hit by [I].</span>")
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor)
if(I.thrownby)
add_logs(I.thrownby, src, "hit", I)
else
return 1
else
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
..()
/mob/living/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
switch(M.damtype)
if(BRUTE)
Paralyse(1)
take_overall_damage(rand(M.force/2, M.force))
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if(BURN)
take_overall_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/Welder.ogg', 50, 1)
if(TOX)
M.mech_toxin_damage(src)
else
return
updatehealth()
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
step_away(src,M)
add_logs(M.occupant, src, "pushed", M)
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>", null, null, 5)
/mob/living/fire_act()
adjust_fire_stacks(3)
IgniteMob()
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src || anchored || !isturf(user.loc))
return 0
if(!user.pulling || user.pulling != src)
user.start_pulling(src, supress_message)
return
if(!(status_flags & CANPUSH))
to_chat(user, "<span class='warning'>[src] can't be grabbed more aggressively!</span>")
return 0
grippedby(user)
//proc to upgrade a simple pull into a more aggressive grab.
/mob/living/proc/grippedby(mob/living/carbon/user)
if(user.grab_state < GRAB_KILL)
user.changeNext_move(CLICK_CD_GRABBING)
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(user.grab_state) //only the first upgrade is instantaneous
var/old_grab_state = user.grab_state
var/grab_upgrade_time = 30
visible_message("<span class='danger'>[user] starts to tighten [user.p_their()] grip on [src]!</span>", \
"<span class='userdanger'>[user] starts to tighten [user.p_their()] grip on you!</span>")
if(!do_mob(user, src, grab_upgrade_time))
return 0
if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != INTENT_GRAB)
return 0
user.grab_state++
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
add_logs(user, src, "grabbed", addition="aggressively")
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
"<span class='userdanger'>[user] has grabbed [src] aggressively!</span>")
drop_all_held_items()
stop_pulling()
if(GRAB_NECK)
visible_message("<span class='danger'>[user] has grabbed [src] by the neck!</span>",\
"<span class='userdanger'>[user] has grabbed you by the neck!</span>")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
if(GRAB_KILL)
visible_message("<span class='danger'>[user] is strangling [src]!</span>", \
"<span class='userdanger'>[user] is strangling you!</span>")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
return 1
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null, armour_penetration, penetrated_text)
var/armor = getarmor(def_zone, attack_flag)
//the if "armor" check is because this is used for everything on /living, including humans
if(armor && armour_penetration)
armor = max(0, armor - armour_penetration)
if(penetrated_text)
to_chat(src, "<span class='userdanger'>[penetrated_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor was penetrated!</span>")
else if(armor >= 100)
if(absorb_text)
to_chat(src, "<span class='userdanger'>[absorb_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor absorbs the blow!</span>")
else if(armor > 0)
if(soften_text)
to_chat(src, "<span class='userdanger'>[soften_text]</span>")
else
to_chat(src, "<span class='userdanger'>Your armor softens the blow!</span>")
return armor
/mob/living/proc/getarmor(def_zone, type)
return 0
//this returns the mob's protection against eye damage (number between -1 and 2)
/mob/living/proc/get_eye_protection()
return 0
//this returns the mob's protection against ear damage (0:no protection; 1: some ear protection; 2: has no ears)
/mob/living/proc/get_ear_protection()
return 0
/mob/living/proc/on_hit(obj/item/projectile/P)
return
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
var/armor = run_armor_check(def_zone, P.flag, "","",P.armour_penetration)
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor)
if(P.dismemberment)
check_projectile_dismemberment(P, def_zone)
return P.on_hit(src, armor)
/mob/living/proc/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
return 0
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class()
if(istype(I,/obj/item/weapon)) //If the item is a weapon...
var/obj/item/weapon/W = I
dtype = W.damtype
if (W.throwforce > 0) //If the weapon's throwforce is greater than zero...
if (W.throwhitsound) //...and throwhitsound is defined...
playsound(loc, W.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
else if(W.hitsound) //Otherwise, if the weapon's hitsound is defined...
playsound(loc, W.hitsound, volume, 1, -1) //...play the weapon's hitsound.
else if(!W.throwhitsound) //Otherwise, if throwhitsound isn't defined...
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
if(!blocked)
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
"<span class='userdanger'>[src] has been hit by [I].</span>")
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor)
if(I.thrownby)
add_logs(I.thrownby, src, "hit", I)
else
return 1
else
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
..()
/mob/living/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
switch(M.damtype)
if(BRUTE)
Paralyse(1)
take_overall_damage(rand(M.force/2, M.force))
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if(BURN)
take_overall_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/Welder.ogg', 50, 1)
if(TOX)
M.mech_toxin_damage(src)
else
return
updatehealth()
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
step_away(src,M)
add_logs(M.occupant, src, "pushed", M)
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>", null, null, 5)
/mob/living/fire_act()
adjust_fire_stacks(3)
IgniteMob()
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src || anchored || !isturf(user.loc))
return 0
if(!user.pulling || user.pulling != src)
user.start_pulling(src, supress_message)
return
if(!(status_flags & CANPUSH))
to_chat(user, "<span class='warning'>[src] can't be grabbed more aggressively!</span>")
return 0
grippedby(user)
//proc to upgrade a simple pull into a more aggressive grab.
/mob/living/proc/grippedby(mob/living/carbon/user)
if(user.grab_state < GRAB_KILL)
user.changeNext_move(CLICK_CD_GRABBING)
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(user.grab_state) //only the first upgrade is instantaneous
var/old_grab_state = user.grab_state
var/grab_upgrade_time = 30
visible_message("<span class='danger'>[user] starts to tighten [user.p_their()] grip on [src]!</span>", \
"<span class='userdanger'>[user] starts to tighten [user.p_their()] grip on you!</span>")
if(!do_mob(user, src, grab_upgrade_time))
return 0
if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != INTENT_GRAB)
return 0
user.grab_state++
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
add_logs(user, src, "grabbed", addition="aggressively")
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
"<span class='userdanger'>[user] has grabbed [src] aggressively!</span>")
drop_all_held_items()
stop_pulling()
if(GRAB_NECK)
visible_message("<span class='danger'>[user] has grabbed [src] by the neck!</span>",\
"<span class='userdanger'>[user] has grabbed you by the neck!</span>")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
if(GRAB_KILL)
visible_message("<span class='danger'>[user] is strangling [src]!</span>", \
"<span class='userdanger'>[user] is strangling you!</span>")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
return 1
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!SSticker.HasRoundStarted())
to_chat(M, "You cannot attack people before the game has started.")
return
if(M.buckled)
if(M in buckled_mobs)
M.Feedstop()
return // can't attack while eating!
if (stat != DEAD)
add_logs(M, src, "attacked")
M.do_attack_animation(src)
visible_message("<span class='danger'>The [M.name] glomps [src]!</span>", \
"<span class='userdanger'>The [M.name] glomps [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 1
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
if(M.melee_damage_upper == 0)
M.visible_message("<span class='notice'>\The [M] [M.friendly] [src]!</span>")
return 0
else
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "attacked")
return 1
/mob/living/attack_paw(mob/living/carbon/monkey/M)
if(isturf(loc) && istype(loc.loc, /area/start))
to_chat(M, "No attacking people at spawn, you jackass.")
return 0
if (M.a_intent == INTENT_HARM)
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
return 0
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
if (prob(75))
add_logs(M, src, "attacked")
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
"<span class='userdanger'>[M.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 1
else
visible_message("<span class='danger'>[M.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[M.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 0
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
switch(L.a_intent)
if("help")
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
return 0
else
L.do_attack_animation(src)
if(prob(90))
add_logs(L, src, "attacked")
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
"<span class='userdanger'>[L.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
return 1
else
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 0
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
switch(M.a_intent)
if ("help")
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
return 0
if ("grab")
grabbedby(M)
return 0
if("harm")
M.do_attack_animation(src)
return 1
if("disarm")
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return 1
/mob/living/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
return
..()
//Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs.
/mob/living/acid_act(acidpwr, acid_volume)
take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1))
return 1
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
to_chat(M, "You cannot attack people before the game has started.")
return
if(M.buckled)
if(M in buckled_mobs)
M.Feedstop()
return // can't attack while eating!
if (stat != DEAD)
add_logs(M, src, "attacked")
M.do_attack_animation(src)
visible_message("<span class='danger'>The [M.name] glomps [src]!</span>", \
"<span class='userdanger'>The [M.name] glomps [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 1
/mob/living/attack_animal(mob/living/simple_animal/M)
M.face_atom(src)
if(M.melee_damage_upper == 0)
M.visible_message("<span class='notice'>\The [M] [M.friendly] [src]!</span>")
return 0
else
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "attacked")
return 1
/mob/living/attack_paw(mob/living/carbon/monkey/M)
if(isturf(loc) && istype(loc.loc, /area/start))
to_chat(M, "No attacking people at spawn, you jackass.")
return 0
if (M.a_intent == INTENT_HARM)
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
return 0
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
if (prob(75))
add_logs(M, src, "attacked")
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
"<span class='userdanger'>[M.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 1
else
visible_message("<span class='danger'>[M.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[M.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 0
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
switch(L.a_intent)
if("help")
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
return 0
else
L.do_attack_animation(src)
if(prob(90))
add_logs(L, src, "attacked")
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
"<span class='userdanger'>[L.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
return 1
else
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 0
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
switch(M.a_intent)
if ("help")
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
return 0
if ("grab")
grabbedby(M)
return 0
if("harm")
M.do_attack_animation(src)
return 1
if("disarm")
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return 1
/mob/living/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
return
..()
//Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs.
/mob/living/acid_act(acidpwr, acid_volume)
take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1))
return 1
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
if(tesla_shock && HAS_SECONDARY_FLAG(src, TESLA_IGNORE))
return FALSE
if(shock_damage > 0)
if(!illusion)
adjustFireLoss(shock_damage)
visible_message(
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>" \
)
return shock_damage
/mob/living/emp_act(severity)
var/list/L = src.get_contents()
for(var/obj/O in L)
O.emp_act(severity)
..()
/mob/living/singularity_act()
var/gain = 20
investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up!
gib()
return(gain)
/mob/living/narsie_act()
if(status_flags & GODMODE)
return
if(is_servant_of_ratvar(src) && !stat)
to_chat(src, "<span class='userdanger'>You resist Nar-Sie's influence... but not all of it. <i>Run!</i></span>")
adjustBruteLoss(35)
if(src && reagents)
reagents.add_reagent("heparin", 5)
return FALSE
if(client)
return FALSE
if(shock_damage > 0)
if(!illusion)
adjustFireLoss(shock_damage)
visible_message(
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>" \
)
return shock_damage
/mob/living/emp_act(severity)
var/list/L = src.get_contents()
for(var/obj/O in L)
O.emp_act(severity)
..()
/mob/living/singularity_act()
var/gain = 20
investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up!
gib()
return(gain)
/mob/living/narsie_act()
if(status_flags & GODMODE)
return
if(is_servant_of_ratvar(src) && !stat)
to_chat(src, "<span class='userdanger'>You resist Nar-Sie's influence... but not all of it. <i>Run!</i></span>")
adjustBruteLoss(35)
if(src && reagents)
reagents.add_reagent("heparin", 5)
return FALSE
if(GLOB.cult_narsie && GLOB.cult_narsie.souls_needed[src])
GLOB.cult_narsie.resize(1.1)
GLOB.cult_narsie.souls_needed -= src
GLOB.cult_narsie.souls += 1
if((GLOB.cult_narsie.souls == GLOB.cult_narsie.soul_goal) && (GLOB.cult_narsie.resolved == FALSE))
GLOB.cult_narsie.resolved = TRUE
world << sound('sound/machines/Alarm.ogg')
addtimer(CALLBACK(GLOBAL_PROC, .proc/cult_ending_helper, 1), 120)
addtimer(CALLBACK(GLOBAL_PROC, .proc/ending_helper), 270)
if(client)
makeNewConstruct(/mob/living/simple_animal/hostile/construct/harvester, src, cultoverride = TRUE)
else
else
switch(rand(1, 6))
if(1)
new /mob/living/simple_animal/hostile/construct/armored/hostile(get_turf(src))
if(2)
new /mob/living/simple_animal/hostile/construct/wraith/hostile(get_turf(src))
if(3 to 6)
new /mob/living/simple_animal/hostile/construct/builder/hostile(get_turf(src))
spawn_dust()
gib()
return TRUE
/mob/living/ratvar_act()
if(status_flags & GODMODE)
return
if(stat != DEAD && !is_servant_of_ratvar(src))
for(var/obj/item/weapon/implant/mindshield/M in implants)
qdel(M)
if(!add_servant_of_ratvar(src))
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
adjustFireLoss(35)
if(src)
adjust_fire_stacks(1)
IgniteMob()
return FALSE
return TRUE
//called when the mob receives a bright flash
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
if(get_eye_protection() < intensity && (override_blindness_check || !(disabilities & BLIND)))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
return 1
//called when the mob receives a loud bang
/mob/living/proc/soundbang_act()
return 0
//to damage the clothes worn by a mob
/mob/living/proc/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
return
/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
if(A != src)
end_pixel_y = get_standard_pixel_y_offset(lying)
used_item = get_active_held_item()
..()
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
if(1)
new /mob/living/simple_animal/hostile/construct/armored/hostile(get_turf(src))
if(2)
new /mob/living/simple_animal/hostile/construct/wraith/hostile(get_turf(src))
if(3 to 6)
new /mob/living/simple_animal/hostile/construct/builder/hostile(get_turf(src))
spawn_dust()
gib()
return TRUE
/mob/living/ratvar_act()
if(status_flags & GODMODE)
return
if(stat != DEAD && !is_servant_of_ratvar(src))
for(var/obj/item/weapon/implant/mindshield/M in implants)
qdel(M)
if(!add_servant_of_ratvar(src))
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
adjustFireLoss(35)
if(src)
adjust_fire_stacks(1)
IgniteMob()
return FALSE
return TRUE
//called when the mob receives a bright flash
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
if(get_eye_protection() < intensity && (override_blindness_check || !(disabilities & BLIND)))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
return 1
//called when the mob receives a loud bang
/mob/living/proc/soundbang_act()
return 0
//to damage the clothes worn by a mob
/mob/living/proc/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
return
/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
if(A != src)
end_pixel_y = get_standard_pixel_y_offset(lying)
used_item = get_active_held_item()
..()
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
@@ -407,7 +407,8 @@
/obj/item/weapon/reagent_containers/borghypo/peace,
/obj/item/weapon/holosign_creator/cyborg,
/obj/item/borg/cyborghug/peacekeeper,
/obj/item/weapon/extinguisher)
/obj/item/weapon/extinguisher,
/obj/item/borg/projectile_dampen)
emag_modules = list(/obj/item/weapon/reagent_containers/borghypo/peace/hacked)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/peacekeeper,
@@ -171,7 +171,30 @@
attacktext = "slashes"
attack_sound = 'sound/weapons/bladeslice.ogg'
construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift)
playstyle_string = "<b>You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls.</b>"
playstyle_string = "<b>You are a Wraith. Though relatively fragile, you are fast, deadly, can phase through walls, and your attacks will lower the cooldown on phasing.</b>"
var/attack_refund = 10 //1 second per attack
var/crit_refund = 50 //5 seconds when putting a target into critical
var/kill_refund = 250 //full refund on kills
/mob/living/simple_animal/hostile/construct/wraith/AttackingTarget() //refund jaunt cooldown when attacking living targets
var/prev_stat
if(isliving(target) && !iscultist(target))
var/mob/living/L = target
prev_stat = L.stat
. = ..()
if(. && isnum(prev_stat))
var/mob/living/L = target
var/refund = 0
if(QDELETED(L) || (L.stat == DEAD && prev_stat != DEAD)) //they're dead, you killed them
refund += kill_refund
else if(L.InCritical() && prev_stat == CONSCIOUS) //you knocked them into critical
refund += crit_refund
if(L.stat != DEAD && prev_stat != DEAD)
refund += attack_refund
for(var/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/S in mob_spell_list)
S.charge_counter = min(S.charge_counter + refund, S.charge_max)
/mob/living/simple_animal/hostile/construct/wraith/hostile //actually hostile, will move around, hit things
AIStatus = AI_ON
@@ -265,8 +288,8 @@
name = "Harvester"
real_name = "Harvester"
desc = "A long, thin construct built to herald Nar-Sie's rise. It'll be all over soon."
icon_state = "harvester"
icon_living = "harvester"
icon_state = "chosen"
icon_living = "chosen"
maxHealth = 60
health = 60
sight = SEE_MOBS
@@ -277,9 +300,10 @@
construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/area_conversion,
/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
playstyle_string = "<B>You are a Harvester. You are incapable of directly killing humans, but your attacks will remove their limbs: \
Bring those who still cling to this world of illusion back to the Geometer so they may know Truth.</B>"
Bring those who still cling to this world of illusion back to the Geometer so they may know Truth. Your form and any you are pulling can pass through runed walls effortlessly.</B>"
can_repair_constructs = TRUE
/mob/living/simple_animal/hostile/construct/harvester/Bump(atom/AM)
. = ..()
if(istype(AM, /turf/closed/wall/mineral/cult) && AM != loc) //we can go through cult walls
@@ -306,6 +330,8 @@
if(!LAZYLEN(parts))
if(undismembermerable_limbs) //they have limbs we can't remove, and no parts we can, attack!
return ..()
C.Weaken(30)
visible_message("<span class='danger'>[src] paralyzes [C]!</span>")
to_chat(src, "<span class='cultlarge'>\"Bring [C.p_them()] to me.\"</span>")
return FALSE
do_attack_animation(C)
@@ -314,6 +340,11 @@
return FALSE
. = ..()
/mob/living/simple_animal/hostile/construct/harvester/Initialize()
. = ..()
var/datum/action/innate/seek_prey/seek = new()
seek.Grant(src)
seek.Activate()
///////////////////////Master-Tracker///////////////////////
@@ -326,11 +357,14 @@
var/tracking = FALSE
var/mob/living/simple_animal/hostile/construct/the_construct
/datum/action/innate/seek_master/Grant(var/mob/living/C)
the_construct = C
..()
/datum/action/innate/seek_master/Activate()
if(!SSticker.mode.eldergod)
the_construct.master = GLOB.blood_target
if(!the_construct.master)
to_chat(the_construct, "<span class='cultitalic'>You have no master to seek!</span>")
the_construct.seeking = FALSE
@@ -346,6 +380,43 @@
to_chat(the_construct, "<span class='cultitalic'>You are now tracking your master.</span>")
/datum/action/innate/seek_prey
name = "Seek the Harvest"
desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!"
background_icon_state = "bg_demon"
buttontooltipstyle = "cult"
button_icon_state = "cult_mark"
var/tracking = FALSE
var/mob/living/simple_animal/hostile/construct/harvester/the_construct
/datum/action/innate/seek_prey/Grant(var/mob/living/C)
the_construct = C
..()
/datum/action/innate/seek_prey/Activate()
if(GLOB.cult_narsie == null)
return
if(tracking)
desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!"
button_icon_state = "cult_mark"
tracking = FALSE
the_construct.seeking = FALSE
the_construct.master = GLOB.cult_narsie
to_chat(the_construct, "<span class='cultitalic'>You are now tracking Nar'Sie, return to reap the harvest!</span>")
return
else
if(LAZYLEN(GLOB.cult_narsie.souls_needed))
the_construct.master = pick(GLOB.cult_narsie.souls_needed)
to_chat(the_construct, "<span class='cultitalic'>You are now tracking your prey, [the_construct.master] - harvest them!</span>")
else
to_chat(the_construct, "<span class='cultitalic'>Nar'Sie has completed her harvest!</span>")
return
desc = "Activate to track Nar'Sie!"
button_icon_state = "sintouch"
tracking = TRUE
the_construct.seeking = TRUE
/////////////////////////////ui stuff/////////////////////////////
/mob/living/simple_animal/hostile/construct/update_health_hud()
@@ -467,6 +467,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
var/used_message = "<span class='holoparasite'>All the cards seem to be blank now.</span>"
var/failure_message = "<span class='holoparasitebold'>..And draw a card! It's...blank? Maybe you should try again later.</span>"
var/ling_failure = "<span class='holoparasitebold'>The deck refuses to respond to a souless creature such as you.</span>"
var/activation_message = "<span class='holoparasite'>The rest of the deck rapidly flashes to ash!</span>"
var/list/possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
var/random = TRUE
var/allowmultiple = FALSE
@@ -495,6 +496,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
if(candidates.len)
theghost = pick(candidates)
spawn_guardian(user, theghost.key)
to_chat(user, "[activation_message]")
qdel(src)
else
to_chat(user, "[failure_message]")
used = FALSE
@@ -587,6 +590,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
used_message = "<span class='holoparasite'>The injector has already been used.</span>"
failure_message = "<span class='holoparasitebold'>...ERROR. BOOT SEQUENCE ABORTED. AI FAILED TO INTIALIZE. PLEASE CONTACT SUPPORT OR TRY AGAIN LATER.</span>"
ling_failure = "<span class='holoparasitebold'>The holoparasites recoil in horror. They want nothing to do with a creature like you.</span>"
activation_message = "<span class='holoparasite'>The injector self destructs after you inject yourself with it.</span>"
/obj/item/weapon/guardiancreator/tech/choose/traitor
possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
@@ -599,7 +603,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/obj/item/weapon/paper/guardian
name = "Holoparasite Guide"
icon_state = "paper_words"
icon_state = "alienpaper_words"
info = {"<b>A list of Holoparasite Types</b><br>
<br>
@@ -670,6 +674,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
used_message = "<span class='holoparasite'>Someone's already taken a bite out of these fishsticks! Ew.</span>"
failure_message = "<span class='holoparasitebold'>You couldn't catch any carp spirits from the seas of Lake Carp. Maybe there are none, maybe you fucked up.</span>"
ling_failure = "<span class='holoparasitebold'>Carp'sie is fine with changelings, so you shouldn't be seeing this message.</span>"
activation_message = "<span class='holoparasite'>You finish eating the fishsticks! Delicious!>"
allowmultiple = TRUE
allowling = TRUE
random = TRUE
@@ -478,6 +478,8 @@ Difficulty: Hard
var/speed = 3 //how many deciseconds between each step
var/currently_seeking = FALSE
var/friendly_fire_check = FALSE //if blasts produced apply friendly fire
var/monster_damage_boost = TRUE
var/damage = 10
/obj/effect/overlay/temp/hierophant/chaser/Initialize(mapload, new_caster, new_target, new_speed, is_friendly_fire)
. = ..()
@@ -521,9 +523,10 @@ Difficulty: Hard
moving--
sleep(speed)
targetturf = get_turf(target)
/obj/effect/overlay/temp/hierophant/chaser/proc/make_blast()
new /obj/effect/overlay/temp/hierophant/blast(loc, caster, friendly_fire_check)
var/obj/effect/overlay/temp/hierophant/blast/B = new(loc, caster, friendly_fire_check)
B.damage = damage
B.monster_damage_boost = monster_damage_boost
/obj/effect/overlay/temp/hierophant/telegraph
icon = 'icons/effects/96x96.dmi'
@@ -553,6 +556,7 @@ Difficulty: Hard
desc = "Get out of the way!"
duration = 9
var/damage = 10 //how much damage do we do?
var/monster_damage_boost = TRUE //do we deal extra damage to monsters? Used by the boss
var/list/hit_things = list() //we hit these already, ignore them
var/friendly_fire_check = FALSE
var/bursting = FALSE //if we're bursting and need to hit anyone crossing us
@@ -595,7 +599,7 @@ Difficulty: Hard
var/limb_to_hit = L.get_bodypart(pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg"))
var/armor = L.run_armor_check(limb_to_hit, "melee", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
L.apply_damage(damage, BURN, limb_to_hit, armor)
if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid))
if(monster_damage_boost && (ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid)))
L.adjustBruteLoss(damage)
add_logs(caster, L, "struck with a [name]")
for(var/obj/mecha/M in T.contents - hit_things) //and mechs.
-64
View File
@@ -1,64 +0,0 @@
/*
Contents:
- Admin procs that make ninjas
*/
//ADMIN CREATE NINJA (From Player)
/client/proc/cmd_admin_ninjafy(mob/living/carbon/human/H in GLOB.player_list)
set category = null
set name = "Make Space Ninja"
if (!SSticker.mode)
alert("Wait until the game starts")
return
if(!istype(H))
return
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes")
return
log_admin("[key_name(src)] turned [H.key] into a Space Ninja.")
H.mind = create_ninja_mind(H.key)
H.mind_initialize()
H.equip_space_ninja(1)
if(istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja))
H.wear_suit:randomize_param()
spawn(0)
H.wear_suit:ninitialize(10,H)
SSticker.mode.update_ninja_icons_added(H)
//ADMIN CREATE NINJA (From Ghost)
/client/proc/send_space_ninja()
set category = "Fun"
set name = "Spawn Space Ninja"
set desc = "Spawns a space ninja for when you need a teenager with attitude."
set popup_menu = 0
if(!holder)
to_chat(src, "Only administrators may use this command.")
return
if(!SSticker.mode)
alert("The game hasn't started yet!")
return
if(alert("Are you sure you want to send in a space ninja?",,"Yes","No")=="No")
return
var/client/C = input("Pick character to spawn as the Space Ninja", "Key", "") as null|anything in GLOB.clients
if(!C)
return
// passing FALSE means the event doesn't start immediately
var/datum/round_event/ghost_role/ninja/E = new(FALSE)
E.priority_candidates += C
E.processing = TRUE
message_admins("<span class='notice'>[key_name_admin(key)] has spawned [key_name_admin(C.key)] as a Space Ninja.</span>")
log_admin("[key] used Spawn Space Ninja.")
return
+3 -113
View File
@@ -63,98 +63,21 @@ Contents:
Mind.active = 1
//generate objectives - You'll generally get 6 objectives (Ninja is meant to be hardmode!)
var/list/possible_targets = list()
for(var/datum/mind/M in SSticker.minds)
if(M.current && M.current.stat != DEAD)
if(ishuman(M.current))
if(M.special_role)
possible_targets[M] = 0 //bad-guy
else if(M.assigned_role in GLOB.command_positions)
possible_targets[M] = 1 //good-guy
var/list/objectives = list(1,2,3,4)
while(give_objectives && Mind.objectives.len < 6)
switch(pick_n_take(objectives))
if(1) //research
var/datum/objective/download/O = new /datum/objective/download()
O.owner = Mind
O.gen_amount_goal()
Mind.objectives += O
if(2) //steal
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
O.owner = Mind
Mind.objectives += O
if(3) //protect/kill
if(!possible_targets.len) continue
var/index = rand(1,possible_targets.len)
var/datum/mind/M = possible_targets[index]
var/is_bad_guy = possible_targets[M]
possible_targets.Cut(index,index+1)
if(is_bad_guy ^ helping_station) //kill (good-ninja + bad-guy or bad-ninja + good-guy)
var/datum/objective/assassinate/O = new /datum/objective/assassinate()
O.owner = Mind
O.target = M
O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]."
Mind.objectives += O
else //protect
var/datum/objective/protect/O = new /datum/objective/protect()
O.owner = Mind
O.target = M
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
Mind.objectives += O
if(4) //debrain/capture
if(!possible_targets.len) continue
var/selected = rand(1,possible_targets.len)
var/datum/mind/M = possible_targets[selected]
var/is_bad_guy = possible_targets[M]
possible_targets.Cut(selected,selected+1)
if(is_bad_guy ^ helping_station) //debrain (good-ninja + bad-guy or bad-ninja + good-guy)
var/datum/objective/debrain/O = new /datum/objective/debrain()
O.owner = Mind
O.target = M
O.explanation_text = "Steal the brain of [M.current.real_name]."
Mind.objectives += O
else //capture
var/datum/objective/capture/O = new /datum/objective/capture()
O.owner = Mind
O.gen_amount_goal()
Mind.objectives += O
else
break
//Add a survival objective since it's usually broad enough for any round type.
if(give_objectives)
var/datum/objective/O = new /datum/objective/survive()
O.owner = Mind
Mind.objectives += O
//add some RP-fluff
Mind.store_memory("I am an elite mercenary assassin of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!")
Mind.store_memory("Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!")
Mind.store_memory("Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.")
//spawn the ninja and assign the candidate
var/mob/living/carbon/human/Ninja = create_space_ninja(spawn_loc)
Mind.transfer_to(Ninja)
//initialise equipment
if(istype(Ninja.wear_suit,/obj/item/clothing/suit/space/space_ninja))
//Should be true but we have to check these things.
var/obj/item/clothing/suit/space/space_ninja/N = Ninja.wear_suit
N.randomize_param()
var/datum/antagonist/ninja/ninjadatum = add_ninja(Ninja)
ninjadatum.equip_space_ninja()
Ninja.internal = Ninja.s_store
Ninja.update_internals_hud_icon(1)
if(Ninja.mind != Mind) //something has gone wrong!
throw EXCEPTION("Ninja created with incorrect mind")
return
Ninja << sound('sound/effects/ninja_greeting.ogg') //so ninja you probably wouldn't even know if you were made one
SSticker.mode.update_ninja_icons_added(Ninja)
spawned_mobs += Ninja
message_admins("[key_name_admin(Ninja)] has been made into a ninja by an event.")
@@ -171,7 +94,6 @@ Contents:
A.real_name = "[pick(GLOB.ninja_titles)] [pick(GLOB.ninja_names)]"
A.copy_to(new_ninja)
new_ninja.dna.update_dna_identity()
new_ninja.equip_space_ninja()
return new_ninja
@@ -183,38 +105,6 @@ Contents:
return Mind
/mob/living/carbon/human/proc/equip_space_ninja(safety=0)//Safety in case you need to unequip stuff for existing characters.
if(safety)
qdel(w_uniform)
qdel(wear_suit)
qdel(wear_mask)
qdel(head)
qdel(shoes)
qdel(gloves)
var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src)
var/obj/item/clothing/suit/space/space_ninja/theSuit = new(src)
var/obj/item/weapon/katana/energy/EK = new(src)
theSuit.energyKatana = EK
equip_to_slot_or_del(R, slot_ears)
equip_to_slot_or_del(new /obj/item/clothing/under/color/black(src), slot_w_uniform)
equip_to_slot_or_del(new /obj/item/clothing/shoes/space_ninja(src), slot_shoes)
equip_to_slot_or_del(theSuit, slot_wear_suit)
equip_to_slot_or_del(new /obj/item/clothing/gloves/space_ninja(src), slot_gloves)
equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/space_ninja(src), slot_head)
equip_to_slot_or_del(new /obj/item/clothing/mask/gas/space_ninja(src), slot_wear_mask)
equip_to_slot_or_del(new /obj/item/clothing/glasses/night(src), slot_glasses)
equip_to_slot_or_del(EK, slot_belt)
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_r_store)
equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/x4(src), slot_l_store)
equip_to_slot_or_del(new /obj/item/weapon/tank/internals/emergency_oxygen(src), slot_s_store)
equip_to_slot_or_del(new /obj/item/weapon/tank/jetpack/carbondioxide(src), slot_back)
var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(src)
E.implant(src)
return 1
/datum/game_mode/proc/update_ninja_icons_added(var/mob/living/carbon/human/ninja)
var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA]
ninjahud.join_hud(ninja)
+6 -13
View File
@@ -58,30 +58,23 @@
A.add_fingerprint(H)
draining = 1
var/drained = A.ninjadrain_act(suit,H,src)
. = A.ninjadrain_act(suit,H,src)
draining = 0
if(isnum(drained)) //Numerical values of drained handle their feedback here, Alpha values handle it themselves (Research hacking)
if(drained)
to_chat(H, "<span class='notice'>Gained <B>[drained]</B> energy from \the [A].</span>")
if(isnum(.)) //Numerical values of drained handle their feedback here, Alpha values handle it themselves (Research hacking)
if(.)
to_chat(H, "<span class='notice'>Gained <B>[.]</B> energy from \the [A].</span>")
else
to_chat(H, "<span class='danger'>\The [A] has run dry of power, you must find another source!</span>")
else
drained = 0 //as to not cancel attack_hand()
return drained
. = 0 //as to not cancel attack_hand()
/obj/item/clothing/gloves/space_ninja/proc/toggled()
set name = "Toggle Interaction"
set desc = "Toggles special interaction on or off."
set category = "Ninja Equip"
/obj/item/clothing/gloves/space_ninja/proc/toggledrain()
var/mob/living/carbon/human/U = loc
to_chat(U, "You <b>[candrain?"disable":"enable"]</b> special interaction.")
candrain=!candrain
/obj/item/clothing/gloves/space_ninja/examine(mob/user)
..()
if(flags & NODROP)
@@ -1,12 +1,6 @@
//Wakes the user so they are able to do their thing. Also injects a decent dose of radium.
//Movement impairing would indicate drugs and the like.
/obj/item/clothing/suit/space/space_ninja/proc/ninjaboost()
set name = "Adrenaline Boost"
set desc = "Inject a secret chemical that will counteract all movement-impairing effect."
set category = "Ninja Ability"
set popup_menu = 0
if(!ninjacost(0,N_ADRENALINE))//Have to make sure stat is not counted for this ability.
var/mob/living/carbon/human/H = affecting
@@ -25,4 +19,3 @@
a_boost--
to_chat(H, "<span class='notice'>There are <B>[a_boost]</B> adrenaline boosts remaining.</span>")
s_coold = 3
return
@@ -26,4 +26,4 @@
if(!a_boost)
to_chat(H, "<span class='danger'>You do not have any more adrenaline boosters.</span>")
return 1
return (s_coold)//Returns the value of the variable which counts down to zero.
return (s_coold)//Returns the value of the variable which counts down to zero.
@@ -2,14 +2,9 @@
//Disables nearby tech equipment.
/obj/item/clothing/suit/space/space_ninja/proc/ninjapulse()
set name = "EM Burst (25E)"
set desc = "Disable any nearby technology with a electro-magnetic pulse."
set category = "Ninja Ability"
set popup_menu = 0
if(!ninjacost(250,N_STEALTH_CANCEL))
var/mob/living/carbon/human/H = affecting
playsound(H.loc, 'sound/effects/EMPulse.ogg', 60, 2)
empulse(H, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch.
s_coold = 2
return
@@ -1,10 +1,6 @@
//Allows the ninja to kidnap people
/obj/item/clothing/suit/space/space_ninja/proc/ninjanet(mob/living/carbon/C in oview())//Only living carbon mobs.
set name = "Energy Net (20E)"
set desc = "Captures a fallen opponent in a net of energy. Will teleport them to a holding facility after 30 seconds."
set category = null
set src = usr.contents
if(!ninjacost(200,N_STEALTH_CANCEL) && iscarbon(C))
var/mob/living/carbon/human/H = affecting
@@ -26,4 +22,3 @@
to_chat(H, "<span class='warning'>[C.p_they(TRUE)] are already trapped inside an energy net!</span>")
else
to_chat(H, "<span class='warning'>[C.p_they(TRUE)] will bring no honor to your Clan!</span>")
return
@@ -2,10 +2,6 @@
//Smoke bomb
/obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke()
set name = "Smoke Bomb"
set desc = "Blind your enemies momentarily with a well-placed smoke bomb."
set category = "Ninja Ability"
set popup_menu = 0//Will not see it when right clicking.
if(!ninjacost(0,N_SMOKE_BOMB))
var/mob/living/carbon/human/H = affecting
@@ -16,4 +12,3 @@
s_bombs--
to_chat(H, "<span class='notice'>There are <B>[s_bombs]</B> smoke bombs remaining.</span>")
s_coold = 1
return
@@ -2,11 +2,6 @@
//Creates a throwing star
/obj/item/clothing/suit/space/space_ninja/proc/ninjastar()
set name = "Create Throwing Stars (1E)"
set desc = "Creates some throwing stars"
set category = "Ninja Ability"
set popup_menu = 0
if(!ninjacost(10))
var/mob/living/carbon/human/H = affecting
var/obj/item/weapon/throwing_star/ninja/N = new(H)
@@ -21,7 +21,6 @@ Contents:
animate(U, alpha = 50,time = 15)
U.visible_message("<span class='warning'>[U.name] vanishes into thin air!</span>", \
"<span class='notice'>You are now mostly invisible to normal detection.</span>")
return
/obj/item/clothing/suit/space/space_ninja/proc/cancel_stealth()
@@ -38,12 +37,7 @@ Contents:
/obj/item/clothing/suit/space/space_ninja/proc/stealth()
set name = "Toggle Stealth"
set desc = "Utilize the internal CLOAK-tech device to activate or deactivate stealth-camo."
set category = "Ninja Equip"
if(!s_busy)
toggle_stealth()
else
to_chat(affecting, "<span class='danger'>Stealth does not appear to work!</span>")
@@ -1,10 +1,5 @@
/obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall()
set name = "Recall Energy Katana (Variable Cost)"
set desc = "Teleports the Energy Katana linked to this suit to its wearer, cost based on distance."
set category = "Ninja Ability"
set popup_menu = 0
var/mob/living/carbon/human/H = affecting
var/cost = 0
@@ -42,4 +37,3 @@
else //Else just TP it to us.
energyKatana.returnToOwner(H,1)
@@ -16,16 +16,10 @@ Contents:
var/mob/living/victim = H.pulling
if(!victim.anchored)
victim.forceMove(locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z))
return
//Jaunt
/obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt()
set name = "Phase Jaunt (10E)"
set desc = "Utilizes the internal VOID-shift device to rapidly transit in direction facing."
set category = "Ninja Ability"
set popup_menu = 0
if(!ninjacost(100,N_STEALTH_CANCEL))
var/mob/living/carbon/human/H = affecting
var/turf/destination = get_teleport_loc(H.loc,H,9,1,3,1,0,1)
@@ -47,7 +41,6 @@ Contents:
s_coold = 1
else
to_chat(H, "<span class='danger'>The VOID-shift device is malfunctioning, <B>teleportation failed</B>.</span>")
return
//Right-Click teleport: It's basically admin "jump to turf"
@@ -76,6 +69,3 @@ Contents:
s_coold = 1
else
to_chat(H, "<span class='danger'>You cannot teleport into solid walls or from solid matter</span>")
return
+67 -32
View File
@@ -22,6 +22,8 @@ Contents:
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30, fire = 100, acid = 100)
strip_delay = 12
actions_types = list(/datum/action/item_action/initialize_ninja_suit, /datum/action/item_action/ninjajaunt, /datum/action/item_action/ninjasmoke, /datum/action/item_action/ninjaboost, /datum/action/item_action/ninjapulse, /datum/action/item_action/ninjastar, /datum/action/item_action/ninjanet, /datum/action/item_action/ninja_sword_recall, /datum/action/item_action/ninja_stealth, /datum/action/item_action/toggle_glove)
//Important parts of the suit.
var/mob/living/carbon/human/affecting = null
var/obj/item/weapon/stock_parts/cell/cell
@@ -57,7 +59,6 @@ Contents:
/obj/item/clothing/suit/space/space_ninja/New()
..()
verbs += /obj/item/clothing/suit/space/space_ninja/proc/init//suit initialize verb
//Spark Init
spark_system = new()
@@ -109,40 +110,38 @@ Contents:
//This proc prevents the suit from being taken off.
/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/H, checkIcons = 0)
/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/H)
if(!istype(H))
return 0
if(checkIcons)
icon_state = H.gender==FEMALE ? "s-ninjanf" : "s-ninjan"
H.gloves.icon_state = "s-ninjan"
H.gloves.item_state = "s-ninjan"
else
if(H.mind.special_role!="Space Ninja")
to_chat(H, "\red <B>fÄTaL ÈÈRRoR</B>: 382200-*#00CÖDE <B>RED</B>\nUNAU†HORIZED USÈ DETÈC†††eD\nCoMMÈNCING SUB-R0U†IN3 13...\nTÈRMInATING U-U-USÈR...")
H.gib()
return 0
if(!istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja))
to_chat(H, "<span class='userdanger'>ERROR</span>: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...")
return 0
if(!istype(H.shoes, /obj/item/clothing/shoes/space_ninja))
to_chat(H, "<span class='userdanger'>ERROR</span>: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...")
return 0
if(!istype(H.gloves, /obj/item/clothing/gloves/space_ninja))
to_chat(H, "<span class='userdanger'>ERROR</span>: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...")
return 0
if(!is_ninja(H))
to_chat(H, "\red <B>fÄTaL ÈÈRRoR</B>: 382200-*#00CÖDE <B>RED</B>\nUNAU†HORIZED USÈ DETÈC†††eD\nCoMMÈNCING SUB-R0U†IN3 13...\nTÈRMInATING U-U-USÈR...")
H.gib()
return FALSE
if(!istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja))
to_chat(H, "<span class='userdanger'>ERROR</span>: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...")
return FALSE
if(!istype(H.shoes, /obj/item/clothing/shoes/space_ninja))
to_chat(H, "<span class='userdanger'>ERROR</span>: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...")
return FALSE
if(!istype(H.gloves, /obj/item/clothing/gloves/space_ninja))
to_chat(H, "<span class='userdanger'>ERROR</span>: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...")
return FALSE
affecting = H
flags |= NODROP //colons make me go all |=
slowdown = FALSE
n_hood = H.head
n_hood.flags |= NODROP
n_shoes = H.shoes
n_shoes.flags |= NODROP
n_shoes.slowdown--
n_gloves = H.gloves
n_gloves.flags |= NODROP
return TRUE
affecting = H
flags |= NODROP //colons make me go all |=
slowdown = 0
n_hood = H.head
n_hood.flags |= NODROP
n_shoes = H.shoes
n_shoes.flags |= NODROP
n_shoes.slowdown--
n_gloves = H.gloves
n_gloves.flags |= NODROP
return 1
/obj/item/clothing/suit/space/space_ninja/proc/lockIcons(mob/living/carbon/human/H)
icon_state = H.gender==FEMALE ? "s-ninjanf" : "s-ninjan"
H.gloves.icon_state = "s-ninjan"
H.gloves.item_state = "s-ninjan"
//This proc allows the suit to be taken off.
@@ -172,3 +171,39 @@ Contents:
to_chat(user, "The CLOAK-tech device is <B>[s_active?"active":"inactive"]</B>.")
to_chat(user, "There are <B>[s_bombs]</B> smoke bomb\s remaining.")
to_chat(user, "There are <B>[a_boost]</B> adrenaline booster\s remaining.")
/obj/item/clothing/suit/space/space_ninja/ui_action_click(mob/user, action)
if(istype(action, /datum/action/item_action/initialize_ninja_suit))
toggle_on_off()
return TRUE
if(!s_initialized)
to_chat(user, "<span class='warning'><b>ERROR</b>: suit offline. Please activate suit.</span>")
return FALSE
if(istype(action, /datum/action/item_action/ninjajaunt))
ninjajaunt()
return TRUE
if(istype(action, /datum/action/item_action/ninjasmoke))
ninjasmoke()
return TRUE
if(istype(action, /datum/action/item_action/ninjaboost))
ninjaboost()
return TRUE
if(istype(action, /datum/action/item_action/ninjapulse))
ninjapulse()
return TRUE
if(istype(action, /datum/action/item_action/ninjastar))
ninjastar()
return TRUE
if(istype(action, /datum/action/item_action/ninjanet))
ninjanet()
return TRUE
if(istype(action, /datum/action/item_action/ninja_sword_recall))
ninja_sword_recall()
return TRUE
if(istype(action, /datum/action/item_action/ninja_stealth))
stealth()
return TRUE
if(istype(action, /datum/action/item_action/toggle_glove))
n_gloves.toggledrain()
return TRUE
return FALSE
+87 -91
View File
@@ -1,102 +1,98 @@
//Verbs link to procs because verb-like procs have a bug which prevents their use if the arguments are not readily referenced.
//^ Old coder words may be false these days, Not taking the risk for now.
/obj/item/clothing/suit/space/space_ninja/proc/init()
set name = "Initialize Suit"
set desc = "Initializes the suit for field operation."
set category = "Ninja Equip"
ninitialize()
/obj/item/clothing/suit/space/space_ninja/proc/deinit()
set name = "De-Initialize Suit"
set desc = "Begins procedure to remove the suit."
set category = "Ninja Equip"
if(!s_busy)
/obj/item/clothing/suit/space/space_ninja/proc/toggle_on_off()
if(s_busy)
to_chat(loc, "<span class='userdanger'>ERROR</span>: You cannot use this function at this time.")
return FALSE
if(s_initialized)
deinitialize()
else
to_chat(affecting, "<span class='danger'>The function did not trigger!</span>")
ninitialize()
. = TRUE
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize(delay = s_delay, mob/living/carbon/human/U = loc)
if(U.mind && U.mind.assigned_role==U.mind.special_role && !s_initialized && !s_busy)//Shouldn't be busy... but anything is possible I guess.
s_busy = 1
for(var/i,i<7,i++)
switch(i)
if(0)
to_chat(U, "<span class='notice'>Now initializing...</span>")
if(1)
if(!lock_suit(U))//To lock the suit onto wearer.
break
to_chat(U, "<span class='notice'>Securing external locking mechanism...\nNeural-net established.</span>")
if(2)
to_chat(U, "<span class='notice'>Extending neural-net interface...\nNow monitoring brain wave pattern...</span>")
if(3)
if(U.stat==2||U.health<=0)
to_chat(U, "<span class='danger'><B>FĆAL �Rr�R</B>: 344--93#�&&21 BR��N |/|/aV� PATT$RN <B>RED</B>\nA-A-aB�rT�NG...</span>")
unlock_suit()
break
lock_suit(U,1)//Check for icons.
U.regenerate_icons()
to_chat(U, "<span class='notice'>Linking neural-net interface...\nPattern</span>\green <B>GREEN</B><span class='notice'>, continuing operation.</span>")
if(4)
to_chat(U, "<span class='notice'>VOID-shift device status: <B>ONLINE</B>.\nCLOAK-tech device status: <B>ONLINE</B>.</span>")
if(5)
to_chat(U, "<span class='notice'>Primary system status: <B>ONLINE</B>.\nBackup system status: <B>ONLINE</B>.\nCurrent energy capacity: <B>[cell.charge]</B>.</span>")
if(6)
to_chat(U, "<span class='notice'>All systems operational. Welcome to <B>SpiderOS</B>, [U.real_name].</span>")
grant_ninja_verbs()
grant_equip_verbs()
ntick()
sleep(delay)
s_busy = 0
else
if(!U.mind||U.mind.assigned_role!=U.mind.special_role)//Your run of the mill persons shouldn't know what it is. Or how to turn it on.
to_chat(U, "You do not understand how this suit functions. Where the heck did it even come from?")
else if(s_initialized)
to_chat(U, "<span class='danger'>The suit is already functioning.</span> Please report this bug.")
else
to_chat(U, "<span class='userdanger'>ERROR</span>: You cannot use this function at this time.")
return
if(!U.mind)
return //Not sure how this could happen.
if(!is_ninja(U))
to_chat(U, "You do not understand how this suit functions. Where the heck did it even come from?")
return
s_busy = TRUE
to_chat(U, "<span class='notice'>Now initializing...</span>")
addtimer(CALLBACK(src, .proc/ninitialize_two, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_two(delay, mob/living/carbon/human/U)
if(!lock_suit(U))//To lock the suit onto wearer.
s_busy = FALSE
return
to_chat(U, "<span class='notice'>Securing external locking mechanism...\nNeural-net established.</span>")
addtimer(CALLBACK(src, .proc/ninitialize_three, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_three(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Extending neural-net interface...\nNow monitoring brain wave pattern...</span>")
addtimer(CALLBACK(src, .proc/ninitialize_four, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_four(delay, mob/living/carbon/human/U)
if(U.stat==2||U.health<=0)
to_chat(U, "<span class='danger'><B>FĆAL �Rr�R</B>: 344--93#�&&21 BR��N |/|/aV� PATT$RN <B>RED</B>\nA-A-aB�rT�NG...</span>")
unlock_suit()
return
lockIcons(U)//Check for icons.
U.regenerate_icons()
to_chat(U, "<span class='notice'>Linking neural-net interface...\nPattern</span>\green <B>GREEN</B><span class='notice'>, continuing operation.</span>")
addtimer(CALLBACK(src, .proc/ninitialize_five, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_five(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>VOID-shift device status: <B>ONLINE</B>.\nCLOAK-tech device status: <B>ONLINE</B>.</span>")
addtimer(CALLBACK(src, .proc/ninitialize_six, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_six(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Primary system status: <B>ONLINE</B>.\nBackup system status: <B>ONLINE</B>.\nCurrent energy capacity: <B>[cell.charge]</B>.</span>")
addtimer(CALLBACK(src, .proc/ninitialize_seven, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_seven(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>All systems operational. Welcome to <B>SpiderOS</B>, [U.real_name].</span>")
grant_ninja_verbs()
grant_equip_verbs()
ntick()
s_busy = FALSE
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize(delay = s_delay)
if(affecting==loc&&!s_busy)
if(affecting==loc)
var/mob/living/carbon/human/U = affecting
if(!s_initialized)
to_chat(U, "<span class='danger'>The suit is not initialized.</span> Please report this bug.")
return
if(alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No")=="No")
return
if(s_busy)
to_chat(U, "<span class='userdanger'>ERROR</span>: You cannot use this function at this time.")
return
s_busy = 1
for(var/i = 0,i<7,i++)
switch(i)
if(0)
to_chat(U, "<span class='notice'>Now de-initializing...</span>")
spideros = 0//Spideros resets.
if(1)
to_chat(U, "<span class='notice'>Logging off, [U:real_name]. Shutting down <B>SpiderOS</B>.</span>")
remove_ninja_verbs()
if(2)
to_chat(U, "<span class='notice'>Primary system status: <B>OFFLINE</B>.\nBackup system status: <B>OFFLINE</B>.</span>")
if(3)
to_chat(U, "<span class='notice'>VOID-shift device status: <B>OFFLINE</B>.\nCLOAK-tech device status: <B>OFFLINE</B>.</span>")
cancel_stealth()//Shutdowns stealth.
if(4)
to_chat(U, "<span class='notice'>Disconnecting neural-net interface...</span>\green<B>Success</B><span class='notice'>.</span>")
if(5)
to_chat(U, "<span class='notice'>Disengaging neural-net interface...</span>\green<B>Success</B><span class='notice'>.</span>")
if(6)
to_chat(U, "<span class='notice'>Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: <B>FINISHED</B>.</span>")
remove_equip_verbs()
unlock_suit()
U.regenerate_icons()
sleep(delay)
s_busy = 0
return
s_busy = TRUE
addtimer(CALLBACK(src, .proc/deinitialize_two, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_two(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Now de-initializing...</span>")
spideros = 0//Spideros resets.
addtimer(CALLBACK(src, .proc/deinitialize_three, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_three(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Logging off, [U:real_name]. Shutting down <B>SpiderOS</B>.</span>")
remove_ninja_verbs()
addtimer(CALLBACK(src, .proc/deinitialize_four, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_four(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Primary system status: <B>OFFLINE</B>.\nBackup system status: <B>OFFLINE</B>.</span>")
addtimer(CALLBACK(src, .proc/deinitialize_five, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_five(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>VOID-shift device status: <B>OFFLINE</B>.\nCLOAK-tech device status: <B>OFFLINE</B>.</span>")
cancel_stealth()//Shutdowns stealth.
addtimer(CALLBACK(src, .proc/deinitialize_six, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_six(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Disconnecting neural-net interface...</span>\green<B>Success</B><span class='notice'>.</span>")
addtimer(CALLBACK(src, .proc/deinitialize_seven, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_seven(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Disengaging neural-net interface...</span>\green<B>Success</B><span class='notice'>.</span>")
addtimer(CALLBACK(src, .proc/deinitialize_eight, delay, U), delay)
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_eight(delay, mob/living/carbon/human/U)
to_chat(U, "<span class='notice'>Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: <B>FINISHED</B>.</span>")
remove_equip_verbs()
U.regenerate_icons()
s_busy = FALSE
-2
View File
@@ -20,5 +20,3 @@
cancel_stealth()
sleep(10)//Checks every second.
+2 -22
View File
@@ -9,33 +9,20 @@ Contents:
*/
/obj/item/clothing/suit/space/space_ninja/proc/grant_equip_verbs()
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/init
verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit
verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth
n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggled
n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggledrain
s_initialized = 1
/obj/item/clothing/suit/space/space_ninja/proc/remove_equip_verbs()
verbs += /obj/item/clothing/suit/space/space_ninja/proc/init
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth
if(n_gloves)
n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled
n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggledrain
s_initialized = 0
/obj/item/clothing/suit/space/space_ninja/proc/grant_ninja_verbs()
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjaboost
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjastar
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjanet
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall
s_initialized=1
slowdown=0
@@ -43,10 +30,3 @@ Contents:
/obj/item/clothing/suit/space/space_ninja/proc/remove_ninja_verbs()
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjaboost
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjastar
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjanet
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall
+1 -2
View File
@@ -170,8 +170,7 @@
/obj/item/weapon/paper/proc/updateinfolinks()
info_links = info
var/i = 0
for(i=1,i<=fields,i++)
for(var/i in 1 to min(fields, 15))
addtofield(i, "<font face=\"[PEN_FONT]\"><A href='?src=\ref[src];write=[i]'>write</A></font>", 1)
info_links = info_links + "<font face=\"[PEN_FONT]\"><A href='?src=\ref[src];write=end'>write</A></font>"
+11 -10
View File
@@ -304,16 +304,17 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
// Sound the alert if gravity was just enabled or disabled.
var/alert = 0
var/area/A = get_area(src)
if(on && SSticker.IsRoundInProgress()) // If we turned on and the game is live.
if(gravity_in_level() == 0)
alert = 1
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
message_admins("The gravity generator was brought online [A][ADMIN_COORDJMP(src)]")
else
if(gravity_in_level() == 1)
alert = 1
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
message_admins("The gravity generator was brought offline with no backup generator. [A][ADMIN_COORDJMP(src)]")
if(SSticker.IsRoundInProgress())
if(on) // If we turned on and the game is live.
if(gravity_in_level() == 0)
alert = 1
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
message_admins("The gravity generator was brought online [A][ADMIN_COORDJMP(src)]")
else
if(gravity_in_level() == 1)
alert = 1
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
message_admins("The gravity generator was brought offline with no backup generator. [A][ADMIN_COORDJMP(src)]")
update_icon()
update_list()
+53 -5
View File
@@ -34,13 +34,61 @@
var/area/A = get_area(src)
if(A)
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/effects.dmi', "ghostalertsie")
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/cult_effects.dmi', "ghostalertsie")
notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.", source = src, alert_overlay = alert_overlay, action=NOTIFY_ATTACK)
INVOKE_ASYNC(src, .proc/narsie_spawn_animation)
narsie_spawn_animation()
/obj/singularity/narsie/large/cult // For the new cult ending, guaranteed to end the round within 3 minutes
var/list/souls_needed = list()
var/soul_goal = 0
var/souls = 0
var/resolved = FALSE
sleep(19)
SSshuttle.emergency.request(null, set_coefficient = 0) //instantly arrives
/obj/singularity/narsie/large/cult/proc/resize(var/ratio)
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
ntransform.Scale(ratio)
animate(src, transform = ntransform, time = 40, easing = EASE_IN|EASE_OUT)
/obj/singularity/narsie/large/cult/Initialize()
. = ..()
GLOB.cult_narsie = src
GLOB.blood_target = src
resize(0.6)
for(var/datum/mind/cult_mind in SSticker.mode.cult)
if(isliving(cult_mind.current))
var/mob/living/L = cult_mind.current
L.narsie_act()
for(var/mob/living/player in GLOB.player_list)
if(player.stat != DEAD && player.loc.z == ZLEVEL_STATION && !iscultist(player) && isliving(player))
souls_needed[player] = TRUE
soul_goal = round(1 + LAZYLEN(souls_needed) * 0.6)
INVOKE_ASYNC(src, .proc/begin_the_end)
/obj/singularity/narsie/large/cult/proc/begin_the_end()
sleep(50)
priority_announce("An acausal dimensional event has been detected in your sector. Event has been flagged EXTINCTION-CLASS. Directing all available assets toward simulating solutions. SOLUTION ETA: 60 SECONDS.","Central Command Higher Dimensional Affairs", 'sound/misc/airraid.ogg')
sleep(550)
priority_announce("Simulations on acausal dimensional event complete. Deploying solution package now. Deployment ETA: TWO MINUTES. ","Central Command Higher Dimensional Affairs")
sleep(50)
set_security_level("delta")
SSshuttle.registerHostileEnvironment(src)
SSshuttle.lockdown = TRUE
sleep(1150)
if(resolved == FALSE)
resolved = TRUE
world << sound('sound/machines/Alarm.ogg')
addtimer(CALLBACK(GLOBAL_PROC, .proc/cult_ending_helper), 120)
addtimer(CALLBACK(GLOBAL_PROC, .proc/ending_helper), 220)
/obj/singularity/narsie/large/cult/Destroy()
GLOB.cult_narsie = null
return ..()
/proc/ending_helper()
SSticker.force_ending = 1
/proc/cult_ending_helper(var/no_explosion = 0)
SSticker.station_explosion_cinematic(no_explosion, "cult", null)
/obj/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob)
@@ -134,7 +182,7 @@
return
to_chat(target, "<span class='cultsmall'>NAR-SIE HAS LOST INTEREST IN YOU.</span>")
target = food
if(isliving(target))
if(ishuman(target))
to_chat(target, "<span class ='cult'>NAR-SIE HUNGERS FOR YOUR SOUL.</span>")
else
to_chat(target, "<span class ='cult'>NAR-SIE HAS CHOSEN YOU TO LEAD HER TO HER NEXT MEAL.</span>")
@@ -64,6 +64,25 @@
qdel(S)
..()
/obj/item/ammo_casing/dnainjector
name = "rigged syringe gun spring"
desc = "A high-power spring that throws DNA injectors."
projectile_type = /obj/item/projectile/bullet/dnainjector
firing_effect_type = null
/obj/item/ammo_casing/dnainjector/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
if(!BB)
return
if(istype(loc, /obj/item/weapon/gun/syringe/dna))
var/obj/item/weapon/gun/syringe/dna/SG = loc
if(!SG.syringes.len)
return
var/obj/item/weapon/dnainjector/S = popleft(SG.syringes)
var/obj/item/projectile/bullet/dnainjector/D = BB
S.forceMove(D)
D.injector = S
..()
/obj/item/ammo_casing/energy/c3dbullet
projectile_type = /obj/item/projectile/bullet/midbullet3
@@ -5,6 +5,7 @@
item_state = null
w_class = WEIGHT_CLASS_BULKY
force = 10
modifystate = TRUE
flags = CONDUCT
slot_flags = SLOT_BACK
ammo_type = list(/obj/item/ammo_casing/energy/laser/pulse, /obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser)
@@ -39,7 +40,7 @@
w_class = WEIGHT_CLASS_NORMAL
slot_flags = SLOT_BELT
icon_state = "pulse_carbine"
item_state = "pulse"
item_state = null
cell_type = "/obj/item/weapon/stock_parts/cell/pulse/carbine"
can_flashlight = 1
flight_x_offset = 18
+32 -6
View File
@@ -49,18 +49,18 @@
return 1
/obj/item/weapon/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = 1)
/obj/item/weapon/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
if(istype(A, /obj/item/weapon/reagent_containers/syringe))
if(syringes.len < max_syringes)
if(!user.transferItemToLoc(A, src))
return
return FALSE
to_chat(user, "<span class='notice'>You load [A] into \the [src].</span>")
syringes.Add(A)
syringes += A
recharge_newshot()
return 1
return TRUE
else
to_chat(usr, "<span class='warning'>[src] cannot hold more syringes!</span>")
return 0
to_chat(user, "<span class='warning'>[src] cannot hold more syringes!</span>")
return FALSE
/obj/item/weapon/gun/syringe/rapidsyringe
name = "rapid syringe gun"
@@ -78,3 +78,29 @@
force = 2 //Also very weak because it's smaller
suppressed = 1 //Softer fire sound
can_unsuppress = 0 //Permanently silenced
/obj/item/weapon/gun/syringe/dna
name = "modified syringe gun"
desc = "A syringe gun that has been modified to fit DNA injectors instead of normal syringes."
origin_tech = "combat=2;syndicate=2;biotech=3"
/obj/item/weapon/gun/syringe/dna/Initialize()
. = ..()
chambered = new /obj/item/ammo_casing/dnainjector(src)
/obj/item/weapon/gun/syringe/dna/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
if(istype(A, /obj/item/weapon/dnainjector))
var/obj/item/weapon/dnainjector/D = A
if(D.used)
to_chat(user, "<span class='warning'>This injector is used up!</span>")
return
if(syringes.len < max_syringes)
if(!user.transferItemToLoc(D, src))
return FALSE
to_chat(user, "<span class='notice'>You load \the [D] into \the [src].</span>")
syringes += D
recharge_newshot()
return TRUE
else
to_chat(user, "<span class='warning'>[src] cannot hold more syringes!</span>")
return FALSE
+26 -5
View File
@@ -190,7 +190,7 @@
name = "dart"
icon_state = "cbbolt"
damage = 6
var/piercing = 0
var/piercing = FALSE
/obj/item/projectile/bullet/dart/New()
..()
@@ -201,15 +201,15 @@
if(iscarbon(target))
var/mob/living/carbon/M = target
if(blocked != 100) // not completely blocked
if(M.can_inject(null, 0, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
if(M.can_inject(null, FALSE, def_zone, piercing)) // Pass the hit zone to see if it can inject by whether it hit the head or the body.
..()
reagents.reaction(M, INJECT)
reagents.trans_to(M, reagents.total_volume)
return 1
return TRUE
else
blocked = 100
target.visible_message("<span class='danger'>The [name] was deflected!</span>", \
"<span class='userdanger'>You were protected against the [name]!</span>")
target.visible_message("<span class='danger'>\The [src] was deflected!</span>", \
"<span class='userdanger'>You were protected against \the [src]!</span>")
..(target, blocked)
reagents.set_reacting(TRUE)
@@ -240,7 +240,28 @@
nodamage = 1
. = ..() // Execute the rest of the code.
/obj/item/projectile/bullet/dnainjector
name = "\improper DNA injector"
icon_state = "syringeproj"
var/obj/item/weapon/dnainjector/injector
/obj/item/projectile/bullet/dnainjector/on_hit(atom/target, blocked = 0)
if(iscarbon(target))
var/mob/living/carbon/M = target
if(blocked != 100)
if(M.can_inject(null, FALSE, def_zone, FALSE))
if(injector.inject(M, firer))
QDEL_NULL(injector)
return TRUE
else
blocked = 100
target.visible_message("<span class='danger'>\The [src] was deflected!</span>", \
"<span class='userdanger'>You were protected against \the [src]!</span>")
return ..()
/obj/item/projectile/bullet/dnainjector/Destroy()
QDEL_NULL(injector)
return ..()
//// SNIPER BULLETS
+1
View File
@@ -143,6 +143,7 @@
has_id = 1
flavour_text = "<font size=3>You are a syndicate agent, employed in a top secret research facility developing biological weapons. Unfortunately, your hated enemy, Nanotrasen, has begun mining in this sector. <b>Continue your research as best you can, and try to keep a low profile. Do not abandon the base without good cause.</b> The base is rigged with explosives should the worst happen, do not let the base fall into enemy hands!</b>"
id_access_list = list(GLOB.access_syndicate)
faction = list("syndicate")
/obj/effect/mob_spawn/human/lavaland_syndicate/comms
name = "Syndicate Comms Agent"
+1
View File
@@ -24,6 +24,7 @@
if(charge_type == "recharge")
var/refund_percent = current_amount/projectile_amount
charge_counter = charge_max * refund_percent
start_recharge()
remove_ranged_ability(msg)
else
msg = "<span class='notice'>[active_msg]<B>Left-click to shoot it at a target!</B></span>"

Some files were not shown because too many files have changed in this diff Show More