Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into radsuit
This commit is contained in:
@@ -693,7 +693,7 @@
|
||||
var/prev_dynamic_voting = CONFIG_GET(flag/dynamic_voting)
|
||||
CONFIG_SET(flag/dynamic_voting,!prev_dynamic_voting)
|
||||
if (!prev_dynamic_voting)
|
||||
to_chat(world, "<B>Vote is now between extended and dynamic chaos.</B>")
|
||||
to_chat(world, "<B>Vote is now a ranked choice of dynamic storytellers.</B>")
|
||||
else
|
||||
to_chat(world, "<B>Vote is now between extended and secret.</B>")
|
||||
log_admin("[key_name(usr)] [prev_dynamic_voting ? "disabled" : "enabled"] dynamic voting.")
|
||||
|
||||
@@ -35,6 +35,9 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
|
||||
/client/proc/cmd_admin_grantfullaccess,
|
||||
/client/proc/cmd_admin_areatest_all,
|
||||
/client/proc/cmd_admin_areatest_station,
|
||||
#ifdef TESTING
|
||||
/client/proc/see_dirty_varedits,
|
||||
#endif
|
||||
/client/proc/cmd_admin_test_atmos_controllers,
|
||||
/client/proc/cmd_admin_rejuvenate,
|
||||
/datum/admins/proc/show_traitor_panel,
|
||||
@@ -84,8 +87,24 @@ GLOBAL_PROTECT(admin_verbs_debug_mapping)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range")
|
||||
|
||||
#ifdef TESTING
|
||||
GLOBAL_LIST_EMPTY(dirty_vars)
|
||||
|
||||
|
||||
/client/proc/see_dirty_varedits()
|
||||
set category = "Mapping"
|
||||
set name = "Dirty Varedits"
|
||||
|
||||
var/list/dat = list()
|
||||
dat += "<h3>Abandon all hope ye who enter here</h3><br><br>"
|
||||
for(var/thing in GLOB.dirty_vars)
|
||||
dat += "[thing]<br>"
|
||||
CHECK_TICK
|
||||
var/datum/browser/popup = new(usr, "dirty_vars", "Dirty Varedits", 900, 750)
|
||||
popup.set_content(dat.Join())
|
||||
popup.open()
|
||||
#endif
|
||||
|
||||
/client/proc/sec_camera_report()
|
||||
set category = "Mapping"
|
||||
set name = "Camera Report"
|
||||
|
||||
@@ -484,11 +484,9 @@
|
||||
|
||||
user.do_attack_animation(L)
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
|
||||
playsound(H, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
return FALSE
|
||||
if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
return FALSE
|
||||
|
||||
switch (mode)
|
||||
if(BATON_STUN)
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
var/new_thing_type = fabrication_values["new_obj_type"]
|
||||
if(isturf(target)) //if our target is a turf, we're just going to ChangeTurf it and assume it'll work out.
|
||||
var/turf/T = target
|
||||
T.ChangeTurf(new_thing_type)
|
||||
T.ChangeTurf(new_thing_type, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
if(new_thing_type)
|
||||
if(fabrication_values["dir_in_new"])
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
if(anchored)
|
||||
T.PlaceOnTop(/turf/closed/wall/clockwork)
|
||||
else
|
||||
T.PlaceOnTop(/turf/open/floor/clockwork)
|
||||
T.PlaceOnTop(/turf/open/floor/clockwork, flags = CHANGETURF_INHERIT_AIR)
|
||||
new /obj/structure/falsewall/brass(T)
|
||||
qdel(src)
|
||||
else
|
||||
|
||||
@@ -239,9 +239,9 @@
|
||||
var/turf/T = safepick(validturfs)
|
||||
if(T)
|
||||
if(istype(T, /turf/open/floor/plating))
|
||||
T.PlaceOnTop(/turf/open/floor/engine/cult)
|
||||
T.PlaceOnTop(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
T.ChangeTurf(/turf/open/floor/engine/cult)
|
||||
T.ChangeTurf(/turf/open/floor/engine/cult, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
var/turf/open/floor/engine/cult/F = safepick(cultturfs)
|
||||
if(F)
|
||||
|
||||
@@ -76,9 +76,10 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
|
||||
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_warops_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Nuke ops spent [threat_spent] on war ops.")
|
||||
if(!(mode.storyteller.flags & WAROPS_ALWAYS_ALLOWED))
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_warops_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Nuke ops spent [threat_spent] on war ops.")
|
||||
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
|
||||
|
||||
qdel(src)
|
||||
@@ -101,12 +102,13 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
|
||||
return FALSE
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat_level < CONFIG_GET(number/dynamic_warops_requirement))
|
||||
to_chat(user, "Due to the dynamic space in which the station resides, you are too deep into Nanotrasen territory to reasonably go loud.")
|
||||
return FALSE
|
||||
else if(mode.threat < CONFIG_GET(number/dynamic_warops_cost))
|
||||
to_chat(user, "Due to recent threats on the station, Nanotrasen is looking too closely for a war declaration to be wise.")
|
||||
return FALSE
|
||||
if(!(mode.storyteller.flags & WAROPS_ALWAYS_ALLOWED))
|
||||
if(mode.threat_level < CONFIG_GET(number/dynamic_warops_requirement))
|
||||
to_chat(user, "Due to the dynamic space in which the station resides, you are too deep into Nanotrasen territory to reasonably go loud.")
|
||||
return FALSE
|
||||
else if(mode.threat < CONFIG_GET(number/dynamic_warops_cost))
|
||||
to_chat(user, "Due to recent threats on the station, Nanotrasen is looking too closely for a war declaration to be wise.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/nuclear_challenge/clownops
|
||||
|
||||
@@ -80,6 +80,8 @@
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
mode = SSticker.mode
|
||||
is_dynamic = TRUE
|
||||
if(mode.storyteller.flags & NO_ASSASSIN)
|
||||
is_hijacker = FALSE
|
||||
if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit)
|
||||
is_hijacker = (prob(10) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement))
|
||||
else
|
||||
@@ -180,7 +182,7 @@
|
||||
destroy_objective.owner = owner
|
||||
destroy_objective.find_target()
|
||||
add_objective(destroy_objective)
|
||||
else if(prob(30))
|
||||
else if(prob(30) || (mode.storyteller.flags & NO_ASSASSIN))
|
||||
var/datum/objective/maroon/maroon_objective = new
|
||||
maroon_objective.owner = owner
|
||||
maroon_objective.find_target()
|
||||
|
||||
@@ -57,10 +57,10 @@
|
||||
if(item.parent)
|
||||
var/static/pipenetwarnings = 10
|
||||
if(pipenetwarnings > 0)
|
||||
warning("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) Nearby: ([item.x], [item.y], [item.z])")
|
||||
log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) Nearby: ([item.x], [item.y], [item.z]).")
|
||||
pipenetwarnings -= 1
|
||||
if(pipenetwarnings == 0)
|
||||
warning("build_pipeline(): further messages about pipenets will be suppressed")
|
||||
log_mapping("build_pipeline(): further messages about pipenets will be suppressed")
|
||||
members += item
|
||||
possible_expansions += item
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
pixel_y = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
|
||||
|
||||
/obj/machinery/meter/process_atmos()
|
||||
if(!target)
|
||||
if(!(target?.flags_1 & INITIALIZED_1))
|
||||
icon_state = "meterX"
|
||||
return 0
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
if(istype(object,/turf) && left_click && !alt_click && !ctrl_click)
|
||||
var/turf/T = object
|
||||
if(isspaceturf(object))
|
||||
T.PlaceOnTop(/turf/open/floor/plating)
|
||||
T.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
else if(isplatingturf(object))
|
||||
T.PlaceOnTop(/turf/open/floor/plasteel)
|
||||
T.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
|
||||
else if(isfloorturf(object))
|
||||
T.PlaceOnTop(/turf/closed/wall)
|
||||
else if(iswallturf(object))
|
||||
@@ -35,7 +35,7 @@
|
||||
log_admin("Build Mode: [key_name(c)] deleted [object] at [AREACOORD(object)]")
|
||||
if(isturf(object))
|
||||
var/turf/T = object
|
||||
T.ScrapeAway()
|
||||
T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
|
||||
else if(isobj(object))
|
||||
qdel(object)
|
||||
return
|
||||
|
||||
@@ -13,17 +13,16 @@
|
||||
//////////////////// Paperwork and Writing Supplies //////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* I did it Kevin
|
||||
/datum/supply_pack/misc/abandonedcrate
|
||||
name = "Abandoned Crate"
|
||||
desc = "Someone keeps finding these locked crates out in the boonies. How about you take a crack at it, we've had our fill. WARNING: EXPLOSIVE"
|
||||
name = "Loot Box"
|
||||
desc = "Try your luck with these highly secure loot boxes! Solve the lock, win great prizes! WARNING: EXPLOSIVE FAILURE."
|
||||
contraband = TRUE
|
||||
cost = 12800
|
||||
cost = 15000
|
||||
contains = list(/obj/structure/closet/crate/secure/loot)
|
||||
crate_name = "abandoned crate"
|
||||
crate_type = /obj/structure/closet/crate/large
|
||||
dangerous = TRUE
|
||||
*/
|
||||
|
||||
/datum/supply_pack/misc/artsupply
|
||||
name = "Art Supplies"
|
||||
desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!"
|
||||
|
||||
@@ -195,6 +195,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/auto_fit_viewport = TRUE
|
||||
|
||||
var/uplink_spawn_loc = UPLINK_PDA
|
||||
|
||||
var/sprint_spacebar = FALSE
|
||||
var/sprint_toggle = FALSE
|
||||
|
||||
var/list/exp = list()
|
||||
var/list/menuoptions
|
||||
@@ -889,6 +892,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "</a><br>"
|
||||
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'>[ambientocclusion ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Fit Viewport:</b> <a href='?_src_=prefs;preference=auto_fit_viewport'>[auto_fit_viewport ? "Auto" : "Manual"]</a><br>"
|
||||
dat += "<b>Sprint Key:</b> <a href='?_src_=prefs;preference=sprint_key'>[sprint_spacebar ? "Space" : "Shift"]</a><br>"
|
||||
dat += "<b>Toggle Sprint:</b> <a href='?_src_=prefs;preference=sprint_toggle'>[sprint_toggle ? "Enabled" : "Disabled"]</a><br>"
|
||||
|
||||
if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation))
|
||||
var/p_map = preferred_map
|
||||
@@ -2239,6 +2244,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(auto_fit_viewport && parent)
|
||||
parent.fit_viewport()
|
||||
|
||||
if("sprint_key")
|
||||
sprint_spacebar = !sprint_spacebar
|
||||
|
||||
if("sprint_toggle")
|
||||
sprint_toggle = !sprint_toggle
|
||||
|
||||
if("save")
|
||||
save_preferences()
|
||||
save_character()
|
||||
|
||||
@@ -167,6 +167,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["parallax"] >> parallax
|
||||
S["ambientocclusion"] >> ambientocclusion
|
||||
S["auto_fit_viewport"] >> auto_fit_viewport
|
||||
S["sprint_spacebar"] >> sprint_spacebar
|
||||
S["sprint_toggle"] >> sprint_toggle
|
||||
S["menuoptions"] >> menuoptions
|
||||
S["enable_tips"] >> enable_tips
|
||||
S["tip_delay"] >> tip_delay
|
||||
@@ -204,6 +206,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
|
||||
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
|
||||
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
|
||||
sprint_spacebar = sanitize_integer(sprint_spacebar, 0, 1, initial(sprint_spacebar))
|
||||
sprint_toggle = sanitize_integer(sprint_toggle, 0, 1, initial(sprint_toggle))
|
||||
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
|
||||
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
|
||||
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
|
||||
@@ -264,6 +268,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["parallax"], parallax)
|
||||
WRITE_FILE(S["ambientocclusion"], ambientocclusion)
|
||||
WRITE_FILE(S["auto_fit_viewport"], auto_fit_viewport)
|
||||
WRITE_FILE(S["sprint_spacebar"], sprint_spacebar)
|
||||
WRITE_FILE(S["sprint_toggle"], sprint_toggle)
|
||||
WRITE_FILE(S["menuoptions"], menuoptions)
|
||||
WRITE_FILE(S["enable_tips"], enable_tips)
|
||||
WRITE_FILE(S["tip_delay"], tip_delay)
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
name = "space cola snowcone"
|
||||
desc = "Space Cola drizzled over a snowball in a paper cup."
|
||||
icon_state = "soda_sc"
|
||||
list_reagents = list("nutriment" = 1, "space_cola" = 5)
|
||||
list_reagents = list("nutriment" = 1, "cola" = 5)
|
||||
tastes = list("ice" = 1, "water" = 1, "cola" = 5)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/snowcones/spacemountainwind
|
||||
@@ -248,4 +248,4 @@
|
||||
desc = "A very colorful snowball in a paper cup."
|
||||
icon_state = "rainbow_sc"
|
||||
list_reagents = list("nutriment" = 5, "laughter" = 25)
|
||||
tastes = list("ice" = 1, "water" = 1, "sunlight" = 5, "light" = 5, "slime" = 5, "paint" = 3, "clouds" = 3)
|
||||
tastes = list("ice" = 1, "water" = 1, "sunlight" = 5, "light" = 5, "slime" = 5, "paint" = 3, "clouds" = 3)
|
||||
|
||||
@@ -8,6 +8,8 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
//On client, created on login
|
||||
/datum/chatOutput
|
||||
var/client/owner //client ref
|
||||
var/total_checks = 0
|
||||
var/last_check = 0
|
||||
var/loaded = FALSE // Has the client loaded the browser output area?
|
||||
var/list/messageQueue //If they haven't loaded chat, this is where messages will go until they do
|
||||
var/cookieSent = FALSE // Has the client sent a cookie for analysis
|
||||
@@ -150,6 +152,18 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
|
||||
//Called by client, sent data to investigate (cookie history so far)
|
||||
/datum/chatOutput/proc/analyzeClientData(cookie = "")
|
||||
//Spam check
|
||||
if(world.time > last_check + (3 SECONDS))
|
||||
last_check = world.time
|
||||
total_checks = 0
|
||||
|
||||
total_checks += 1
|
||||
|
||||
if(total_checks > SPAM_TRIGGER_AUTOMUTE)
|
||||
message_admins("[key_name(owner)] kicked for goonchat topic spam")
|
||||
qdel(owner)
|
||||
return
|
||||
|
||||
if(!cookie)
|
||||
return
|
||||
|
||||
@@ -158,13 +172,22 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico
|
||||
if (connData && islist(connData) && connData.len > 0 && connData["connData"])
|
||||
connectionHistory = connData["connData"] //lol fuck
|
||||
var/list/found = new()
|
||||
for(var/i in connectionHistory.len to 1 step -1)
|
||||
if(connectionHistory.len > 5)
|
||||
message_admins("[key_name(src.owner)] was kicked for an invalid ban cookie)")
|
||||
qdel(owner)
|
||||
return
|
||||
|
||||
for(var/i in min(connectionHistory.len, 5) to 1 step -1)
|
||||
if(QDELETED(owner))
|
||||
//he got cleaned up before we were done
|
||||
return
|
||||
var/list/row = src.connectionHistory[i]
|
||||
if (!row || row.len < 3 || (!row["ckey"] || !row["compid"] || !row["ip"])) //Passed malformed history object
|
||||
return
|
||||
if (world.IsBanned(row["ckey"], row["ip"], row["compid"], real_bans_only=TRUE))
|
||||
found = row
|
||||
break
|
||||
CHECK_TICK
|
||||
|
||||
//Uh oh this fucker has a history of playing on a banned account!!
|
||||
if (found.len > 0)
|
||||
|
||||
@@ -421,8 +421,8 @@ function handleClientData(ckey, ip, compid) {
|
||||
return; //Record already exists
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.clientData.length >= opts.clientDataLimit) {
|
||||
//Lets make sure we obey our limit (can connect from server with higher limit)
|
||||
while (opts.clientData.length >= opts.clientDataLimit) {
|
||||
opts.clientData.shift();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -59,9 +59,7 @@
|
||||
return
|
||||
var/area/AS = get_area(src)
|
||||
if(istype(AS, /area/holodeck))
|
||||
log_world("### MAPPING ERROR")
|
||||
log_world("Holodeck computer cannot be in a holodeck.")
|
||||
log_world("This would cause circular power dependency.")
|
||||
log_mapping("Holodeck computer cannot be in a holodeck, This would cause circular power dependency.")
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
|
||||
@@ -58,13 +58,23 @@
|
||||
return
|
||||
switch(_key)
|
||||
if("Shift")
|
||||
sprint_hotkey(TRUE)
|
||||
if(!user.prefs.sprint_spacebar)
|
||||
user.prefs.sprint_toggle ? togglesprint() : sprint_hotkey(TRUE) //Yes, this looks hacky. Yes, this works.
|
||||
return
|
||||
if("Space")
|
||||
if(user.prefs.sprint_spacebar)
|
||||
user.prefs.sprint_toggle ? togglesprint() : sprint_hotkey(TRUE)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/key_up(_key, client/user)
|
||||
switch(_key)
|
||||
if("Shift")
|
||||
sprint_hotkey(FALSE)
|
||||
if(!user.prefs.sprint_spacebar && !user.prefs.sprint_toggle)
|
||||
sprint_hotkey(FALSE)
|
||||
return
|
||||
if("Space")
|
||||
if(user.prefs.sprint_spacebar && !user.prefs.sprint_toggle)
|
||||
sprint_hotkey(FALSE)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
//initialize things that are normally initialized after map load
|
||||
parsed.initTemplateBounds()
|
||||
smooth_zlevel(world.maxz)
|
||||
log_game("Z-level [name] loaded at at [x],[y],[world.maxz]")
|
||||
log_game("Z-level [name] loaded at [x],[y],[world.maxz]")
|
||||
|
||||
return level
|
||||
|
||||
@@ -84,6 +84,13 @@
|
||||
if(T.y+height > world.maxy)
|
||||
return
|
||||
|
||||
var/list/border = block(locate(max(T.x-1, 1), max(T.y-1, 1), T.z),
|
||||
locate(min(T.x+width+1, world.maxx), min(T.y+height+1, world.maxy), T.z))
|
||||
for(var/L in border)
|
||||
var/turf/turf_to_disable = L
|
||||
SSair.remove_from_active(turf_to_disable) //stop processing turfs along the border to prevent runtimes, we return it in initTemplateBounds()
|
||||
turf_to_disable.atmos_adjacent_turfs?.Cut()
|
||||
|
||||
// Accept cached maps, but don't save them automatically - we don't want
|
||||
// ruins clogging up memory for the whole round.
|
||||
var/datum/parsed_map/parsed = cached_map || new(file(mappath))
|
||||
@@ -100,7 +107,7 @@
|
||||
//initialize things that are normally initialized after map load
|
||||
parsed.initTemplateBounds()
|
||||
|
||||
log_game("[name] loaded at at [T.x],[T.y],[T.z]")
|
||||
log_game("[name] loaded at [T.x],[T.y],[T.z]")
|
||||
return bounds
|
||||
|
||||
/datum/map_template/proc/get_affected_turfs(turf/T, centered = FALSE)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
/obj/effect/baseturf_helper/LateInitialize()
|
||||
if(!baseturf_to_replace)
|
||||
baseturf_to_replace = typecacheof(/turf/open/space)
|
||||
baseturf_to_replace = typecacheof(list(/turf/open/space,/turf/baseturf_bottom))
|
||||
else if(!length(baseturf_to_replace))
|
||||
baseturf_to_replace = list(baseturf_to_replace = TRUE)
|
||||
else if(baseturf_to_replace[baseturf_to_replace[1]] != TRUE) // It's not associative
|
||||
@@ -45,7 +45,6 @@
|
||||
thing.PlaceOnBottom(null, baseturf)
|
||||
else if(baseturf_to_replace[thing.baseturfs])
|
||||
thing.assemble_baseturfs(baseturf)
|
||||
return
|
||||
else
|
||||
thing.PlaceOnBottom(null, baseturf)
|
||||
|
||||
@@ -107,16 +106,16 @@
|
||||
/obj/effect/mapping_helpers/airlock/cyclelink_helper/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!mapload)
|
||||
log_world("### MAP WARNING, [src] spawned outside of mapload!")
|
||||
log_mapping("[src] spawned outside of mapload!")
|
||||
return
|
||||
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
|
||||
if(airlock)
|
||||
if(airlock.cyclelinkeddir)
|
||||
log_world("### MAP WARNING, [src] at [AREACOORD(src)] tried to set [airlock] cyclelinkeddir, but it's already set!")
|
||||
log_mapping("[src] at [AREACOORD(src)] tried to set [airlock] cyclelinkeddir, but it's already set!")
|
||||
else
|
||||
airlock.cyclelinkeddir = dir
|
||||
else
|
||||
log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
|
||||
log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
|
||||
|
||||
|
||||
/obj/effect/mapping_helpers/airlock/locked
|
||||
@@ -126,16 +125,16 @@
|
||||
/obj/effect/mapping_helpers/airlock/locked/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!mapload)
|
||||
log_world("### MAP WARNING, [src] spawned outside of mapload!")
|
||||
log_mapping("[src] spawned outside of mapload!")
|
||||
return
|
||||
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
|
||||
if(airlock)
|
||||
if(airlock.locked)
|
||||
log_world("### MAP WARNING, [src] at [AREACOORD(src)] tried to bolt [airlock] but it's already locked!")
|
||||
log_mapping("[src] at [AREACOORD(src)] tried to bolt [airlock] but it's already locked!")
|
||||
else
|
||||
airlock.locked = TRUE
|
||||
else
|
||||
log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
|
||||
log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
|
||||
|
||||
/obj/effect/mapping_helpers/airlock/unres
|
||||
name = "airlock unresctricted side helper"
|
||||
@@ -144,13 +143,13 @@
|
||||
/obj/effect/mapping_helpers/airlock/unres/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!mapload)
|
||||
log_world("### MAP WARNING, [src] spawned outside of mapload!")
|
||||
log_mapping("[src] spawned outside of mapload!")
|
||||
return
|
||||
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
|
||||
if(airlock)
|
||||
airlock.unres_sides ^= dir
|
||||
else
|
||||
log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
|
||||
log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
|
||||
|
||||
|
||||
//needs to do its thing before spawn_rivers() is called
|
||||
@@ -164,17 +163,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
|
||||
var/turf/T = get_turf(src)
|
||||
T.flags_1 |= NO_LAVA_GEN_1
|
||||
|
||||
/// Adds the map it is on to the z_is_planet list
|
||||
/obj/effect/mapping_helpers/planet_z
|
||||
name = "planet z helper"
|
||||
layer = POINT_LAYER
|
||||
|
||||
/obj/effect/mapping_helpers/planet_z/Initialize()
|
||||
. = ..()
|
||||
var/datum/space_level/S = SSmapping.get_level(z)
|
||||
S.traits[ZTRAIT_PLANET] = TRUE
|
||||
|
||||
|
||||
//This helper applies components to things on the map directly.
|
||||
/obj/effect/mapping_helpers/component_injector
|
||||
name = "Component Injector"
|
||||
|
||||
@@ -8,18 +8,26 @@ GLOBAL_DATUM_INIT(_preloader, /datum/map_preloader, new)
|
||||
var/list/attributes
|
||||
var/target_path
|
||||
|
||||
/datum/map_preloader/proc/setup(list/the_attributes, path)
|
||||
/world/proc/preloader_setup(list/the_attributes, path)
|
||||
if(the_attributes.len)
|
||||
GLOB.use_preloader = TRUE
|
||||
attributes = the_attributes
|
||||
target_path = path
|
||||
var/datum/map_preloader/preloader_local = GLOB._preloader
|
||||
preloader_local.attributes = the_attributes
|
||||
preloader_local.target_path = path
|
||||
|
||||
/datum/map_preloader/proc/load(atom/what)
|
||||
/world/proc/preloader_load(atom/what)
|
||||
GLOB.use_preloader = FALSE
|
||||
for(var/attribute in attributes)
|
||||
var/value = attributes[attribute]
|
||||
var/datum/map_preloader/preloader_local = GLOB._preloader
|
||||
for(var/attribute in preloader_local.attributes)
|
||||
var/value = preloader_local.attributes[attribute]
|
||||
if(islist(value))
|
||||
value = deepCopyList(value)
|
||||
#ifdef TESTING
|
||||
if(what.vars[attribute] == value)
|
||||
var/message = "<font color=green>[what.type]</font> at [AREACOORD(what)] - <b>VAR:</b> <font color=red>[attribute] = [isnull(value) ? "null" : (isnum(value) ? value : "\"[value]\"")]</font>"
|
||||
log_mapping("DIRTY VAR: [message]")
|
||||
GLOB.dirty_vars += message
|
||||
#endif
|
||||
what.vars[attribute] = value
|
||||
|
||||
/area/template_noop
|
||||
|
||||
@@ -306,8 +306,8 @@
|
||||
//first instance the /area and remove it from the members list
|
||||
index = members.len
|
||||
if(members[index] != /area/template_noop)
|
||||
GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation
|
||||
var/atype = members[index]
|
||||
world.preloader_setup(members_attributes[index], atype)//preloader for assigning set variables on atom creation
|
||||
var/atom/instance = areaCache[atype]
|
||||
if (!instance)
|
||||
instance = GLOB.areas_by_type[atype]
|
||||
@@ -318,7 +318,7 @@
|
||||
instance.contents.Add(crds)
|
||||
|
||||
if(GLOB.use_preloader && instance)
|
||||
GLOB._preloader.load(instance)
|
||||
world.preloader_load(instance)
|
||||
|
||||
//then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
|
||||
|
||||
@@ -354,7 +354,7 @@
|
||||
|
||||
//Instance an atom at (x,y,z) and gives it the variables in attributes
|
||||
/datum/parsed_map/proc/instance_atom(path,list/attributes, turf/crds, no_changeturf, placeOnTop)
|
||||
GLOB._preloader.setup(attributes, path)
|
||||
world.preloader_setup(attributes, path)
|
||||
|
||||
if(crds)
|
||||
if(ispath(path, /turf))
|
||||
@@ -368,7 +368,7 @@
|
||||
. = create_atom(path, crds)//first preloader pass
|
||||
|
||||
if(GLOB.use_preloader && .)//second preloader pass, for those atoms that don't ..() in New()
|
||||
GLOB._preloader.load(.)
|
||||
world.preloader_load(.)
|
||||
|
||||
//custom CHECK_TICK here because we don't want things created while we're sleeping to not initialize
|
||||
if(TICK_CHECK)
|
||||
|
||||
@@ -926,7 +926,7 @@
|
||||
timer = world.time + create_delay + 1
|
||||
if(do_after(user, create_delay, target = T))
|
||||
var/old_name = T.name
|
||||
if(T.TerraformTurf(turf_type))
|
||||
if(T.TerraformTurf(turf_type, flags = CHANGETURF_INHERIT_AIR))
|
||||
user.visible_message("<span class='danger'>[user] turns \the [old_name] into [transform_string]!</span>")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] fired the lava staff at [ADMIN_VERBOSEJMP(T)]")
|
||||
log_game("[key_name(user)] fired the lava staff at [AREACOORD(T)].")
|
||||
@@ -937,7 +937,7 @@
|
||||
qdel(L)
|
||||
else
|
||||
var/old_name = T.name
|
||||
if(T.TerraformTurf(reset_turf_type))
|
||||
if(T.TerraformTurf(reset_turf_type, flags = CHANGETURF_INHERIT_AIR))
|
||||
user.visible_message("<span class='danger'>[user] turns \the [old_name] into [reset_string]!</span>")
|
||||
timer = world.time + reset_cooldown
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, 1)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
/obj/machinery/mineral/ore_redemption/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
. += "<span class='notice'>The status display reads: Smelting <b>[sheet_per_ore]</b> sheet(s) per piece of ore.<br>Ore pickup speed at <b>[ore_pickup_rate]</b>.</span>"
|
||||
. += "<span class='notice'>The status display reads: Smelting <b>[sheet_per_ore]</b> sheet(s) per piece of ore.<br>Reward point generation at <b>[point_upgrade*100]%</b>.<br>Ore pickup speed at <b>[ore_pickup_rate]</b>.</span>"
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/proc/smelt_ore(obj/item/stack/ore/O)
|
||||
var/datum/component/material_container/mat_container = materials.mat_container
|
||||
@@ -63,7 +63,7 @@
|
||||
ore_buffer -= O
|
||||
|
||||
if(O && O.refined_type)
|
||||
points += O.points * O.amount
|
||||
points += O.points * point_upgrade * O.amount
|
||||
|
||||
var/material_amount = mat_container.get_item_material_amount(O)
|
||||
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
return 2 //no ears
|
||||
|
||||
/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush)
|
||||
..(AM, skipcatch = TRUE, hitpush = FALSE)
|
||||
return ..(AM, skipcatch = TRUE, hitpush = FALSE)
|
||||
|
||||
/mob/living/carbon/alien/can_embed(obj/item/I)
|
||||
return FALSE
|
||||
|
||||
/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other.
|
||||
As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
|
||||
In all, this is a lot like the monkey code. /N
|
||||
*/
|
||||
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
|
||||
if(isturf(loc) && istype(loc.loc, /area/start))
|
||||
to_chat(M, "No attacking people at spawn, you jackass.")
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
|
||||
switch(M.a_intent)
|
||||
|
||||
if ("help")
|
||||
if (INTENT_HELP)
|
||||
if(!recoveringstam)
|
||||
resting = 0
|
||||
AdjustStun(-60)
|
||||
@@ -28,11 +28,7 @@ In all, this is a lot like the monkey code. /N
|
||||
AdjustUnconscious(-60)
|
||||
AdjustSleeping(-100)
|
||||
visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake [p_them()] up!</span>")
|
||||
|
||||
if ("grab")
|
||||
grabbedby(M)
|
||||
|
||||
else
|
||||
if(INTENT_DISARM, INTENT_HARM)
|
||||
if(health > 0)
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
|
||||
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
|
||||
@@ -50,28 +46,31 @@ In all, this is a lot like the monkey code. /N
|
||||
|
||||
|
||||
/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
|
||||
if(..()) //to allow surgery to return properly.
|
||||
return 0
|
||||
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
help_shake_act(M)
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
if ("harm")
|
||||
if (INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return TRUE
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
return 1
|
||||
if("disarm")
|
||||
if(INTENT_DISARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return TRUE
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(..())
|
||||
if (stat != DEAD)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(rand(1, 3), BRUTE, affecting)
|
||||
. = ..()
|
||||
if(.) //successful monkey bite.
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(rand(1, 3), BRUTE, affecting)
|
||||
|
||||
|
||||
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
|
||||
@@ -93,13 +92,15 @@ In all, this is a lot like the monkey code. /N
|
||||
adjustStaminaLoss(damage)
|
||||
|
||||
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 40)
|
||||
adjustBruteLoss(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
updatehealth()
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime attack
|
||||
return
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 40)
|
||||
adjustBruteLoss(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/alien/ex_act(severity, target, origin)
|
||||
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
|
||||
|
||||
@@ -63,12 +63,7 @@
|
||||
if(A)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
var/blocked = FALSE
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
|
||||
blocked = TRUE
|
||||
if(!blocked)
|
||||
if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
|
||||
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
|
||||
L.Knockdown(100)
|
||||
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
adjustBruteLoss(15)
|
||||
var/hitverb = "punched"
|
||||
if(mob_size < MOB_SIZE_LARGE)
|
||||
@@ -21,46 +23,46 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
|
||||
if(..())
|
||||
switch(M.a_intent)
|
||||
if ("harm")
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down.
|
||||
Unconscious(40)
|
||||
visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \
|
||||
"<span class='userdanger'>[M] has knocked [src] down!</span>")
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
log_combat(M, src, "attacked")
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if (INTENT_HARM)
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down.
|
||||
Unconscious(40)
|
||||
visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \
|
||||
"<span class='userdanger'>[M] has knocked [src] down!</span>")
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
log_combat(M, src, "attacked")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
if (INTENT_DISARM)
|
||||
if (!lying)
|
||||
if (prob(5))
|
||||
Unconscious(40)
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
log_combat(M, src, "pushed")
|
||||
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has pushed down [src]!</span>")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='userdanger'>[M] has attempted to punch [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
if ("disarm")
|
||||
if (!lying)
|
||||
if (prob(5))
|
||||
Unconscious(40)
|
||||
if (prob(50))
|
||||
dropItemToGround(get_active_held_item())
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
log_combat(M, src, "pushed")
|
||||
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has pushed down [src]!</span>")
|
||||
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
if (prob(50))
|
||||
dropItemToGround(get_active_held_item())
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='userdanger'>[M] has attempted to disarm [src]!</span>",\
|
||||
"<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to disarm [src]!</span>",\
|
||||
"<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
|
||||
if(!no_effect && !visual_effect_icon)
|
||||
|
||||
@@ -1,26 +1,33 @@
|
||||
|
||||
|
||||
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
|
||||
if(..())
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
log_combat(M, src, "attacked")
|
||||
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 4.9))
|
||||
Unconscious(rand(100,200))
|
||||
. = ..()
|
||||
if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB)
|
||||
return
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
log_combat(M, src, "attacked")
|
||||
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 4.9))
|
||||
Unconscious(rand(100,200))
|
||||
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to kick [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to kick [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[user] has pummeled [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has pummeled [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
adjustBruteLoss(5 + rand(1,9))
|
||||
new /datum/forced_movement(src, get_step_away(user,src, 30), 1)
|
||||
return 1
|
||||
|
||||
@@ -48,41 +48,42 @@
|
||||
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
|
||||
affecting.dismember(P.damtype)
|
||||
|
||||
/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check)
|
||||
. = FALSE
|
||||
if(mind)
|
||||
if(mind.martial_art && mind.martial_art.dodge_chance == 100)
|
||||
return TRUE
|
||||
if(!skip_throw_mode_check && !in_throw_mode)
|
||||
/mob/living/carbon/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
. = ..()
|
||||
if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !in_throw_mode)
|
||||
return
|
||||
if(get_active_held_item())
|
||||
if(get_active_held_item() || restrained())
|
||||
return
|
||||
if(restrained())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
|
||||
if(!skipcatch) //ugly, but easy
|
||||
if(can_catch_item())
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if (mind)
|
||||
if (mind.martial_art && mind.martial_art.dodge_chance == 100) //autocatch for rising bass
|
||||
if (get_active_held_item())
|
||||
visible_message("<span class='warning'>[I] falls to the ground as [src] chops it out of the air!</span>")
|
||||
return 1
|
||||
if(!in_throw_mode)
|
||||
throw_mode_on()
|
||||
if(isturf(I.loc))
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
return 1
|
||||
..()
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/embed_item(obj/item/I)
|
||||
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
|
||||
var/obj/item/bodypart/L = pick(bodyparts)
|
||||
L.embedded_objects |= I
|
||||
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
|
||||
I.forceMove(src)
|
||||
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
|
||||
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
|
||||
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user)
|
||||
//CIT CHANGES START HERE - combatmode and resting checks
|
||||
var/totitemdamage = I.force
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/tempcarb = user
|
||||
if(!tempcarb.combatmode)
|
||||
totitemdamage *= 0.5
|
||||
if(user.resting)
|
||||
totitemdamage *= 0.5
|
||||
if(!combatmode)
|
||||
totitemdamage *= 1.5
|
||||
//CIT CHANGES END HERE
|
||||
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
|
||||
return FALSE
|
||||
var/obj/item/bodypart/affecting
|
||||
if(user == src)
|
||||
affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay!
|
||||
@@ -93,17 +94,6 @@
|
||||
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
|
||||
send_item_attack_message(I, user, affecting.name)
|
||||
if(I.force)
|
||||
//CIT CHANGES START HERE - combatmode and resting checks
|
||||
var/totitemdamage = I.force
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/tempcarb = user
|
||||
if(!tempcarb.combatmode)
|
||||
totitemdamage *= 0.5
|
||||
if(user.resting)
|
||||
totitemdamage *= 0.5
|
||||
if(!combatmode)
|
||||
totitemdamage *= 1.5
|
||||
//CIT CHANGES END HERE
|
||||
apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
|
||||
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
|
||||
var/basebloodychance = affecting.brute_dam + totitemdamage
|
||||
@@ -137,7 +127,9 @@
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
|
||||
|
||||
. = ..()
|
||||
if(.) //was the attack blocked?
|
||||
return
|
||||
for(var/thing in diseases)
|
||||
var/datum/disease/D = thing
|
||||
if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
|
||||
@@ -152,8 +144,7 @@
|
||||
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
|
||||
for(var/datum/surgery/S in surgeries)
|
||||
if(S.next_step(user, user.a_intent))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
|
||||
@@ -173,7 +164,8 @@
|
||||
help_shake_act(M)
|
||||
return 0
|
||||
|
||||
if(..()) //successful monkey bite.
|
||||
. = ..()
|
||||
if(.) //successful monkey bite.
|
||||
for(var/thing in M.diseases)
|
||||
var/datum/disease/D = thing
|
||||
ForceContractDisease(D)
|
||||
@@ -181,26 +173,27 @@
|
||||
|
||||
|
||||
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
if(M.powerlevel > 0)
|
||||
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
|
||||
if(prob(stunprob))
|
||||
M.powerlevel -= 3
|
||||
if(M.powerlevel < 0)
|
||||
M.powerlevel = 0
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(M.powerlevel > 0)
|
||||
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
|
||||
if(prob(stunprob))
|
||||
M.powerlevel -= 3
|
||||
if(M.powerlevel < 0)
|
||||
M.powerlevel = 0
|
||||
|
||||
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
|
||||
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
|
||||
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
|
||||
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
|
||||
|
||||
do_sparks(5, TRUE, src)
|
||||
var/power = M.powerlevel + rand(0,3)
|
||||
Knockdown(power*20)
|
||||
if(stuttering < power)
|
||||
stuttering = power
|
||||
if (prob(stunprob) && M.powerlevel >= 8)
|
||||
adjustFireLoss(M.powerlevel * rand(6,10))
|
||||
updatehealth()
|
||||
return 1
|
||||
do_sparks(5, TRUE, src)
|
||||
var/power = M.powerlevel + rand(0,3)
|
||||
Knockdown(power*20)
|
||||
if(stuttering < power)
|
||||
stuttering = power
|
||||
if (prob(stunprob) && M.powerlevel >= 8)
|
||||
adjustFireLoss(M.powerlevel * rand(6,10))
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone)
|
||||
if(!attacker.limb_destroyer)
|
||||
@@ -332,12 +325,12 @@
|
||||
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
else if(check_zone(M.zone_selected) == "r_arm" || check_zone(M.zone_selected) == "l_arm")
|
||||
M.visible_message( \
|
||||
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
|
||||
"<span class='notice'>You shake [src]'s hand.</span>", )
|
||||
|
||||
|
||||
else
|
||||
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
|
||||
"<span class='notice'>You hug [src] to make [p_them()] feel better!</span>")
|
||||
|
||||
@@ -67,66 +67,36 @@
|
||||
P.setAngle(rand(0, 360))//SHING
|
||||
return FALSE
|
||||
|
||||
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
|
||||
if(P.is_reflectable)
|
||||
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
|
||||
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
|
||||
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
|
||||
// Find a turf near or on the original location to bounce to
|
||||
if(P.starting)
|
||||
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(src)
|
||||
return ..()
|
||||
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
var/new_angle_s = P.Angle + rand(120,240)
|
||||
while(new_angle_s > 180) // Translate to regular projectile degrees
|
||||
new_angle_s -= 360
|
||||
P.setAngle(new_angle_s)
|
||||
/mob/living/carbon/human/check_reflect(def_zone)
|
||||
if(wear_suit?.IsReflect(def_zone))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
return -1 // complete projectile permutation
|
||||
|
||||
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return 2
|
||||
|
||||
return (..(P , def_zone))
|
||||
|
||||
/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object
|
||||
if(wear_suit)
|
||||
if(wear_suit.IsReflect(def_zone) == 1)
|
||||
return 1
|
||||
for(var/obj/item/I in held_items)
|
||||
if(I.IsReflect(def_zone) == 1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/check_shields(atom/AM, var/damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
|
||||
/mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/block_chance_modifier = round(damage / -3)
|
||||
|
||||
for(var/obj/item/I in held_items)
|
||||
if(!istype(I, /obj/item/clothing))
|
||||
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
|
||||
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
if(wear_suit)
|
||||
var/final_block_chance = wear_suit.block_chance - (CLAMP((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
|
||||
if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
return TRUE
|
||||
if(w_uniform)
|
||||
var/final_block_chance = w_uniform.block_chance - (CLAMP((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
|
||||
if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
return TRUE
|
||||
if(wear_neck)
|
||||
var/final_block_chance = wear_neck.block_chance - (CLAMP((armour_penetration-wear_neck.armour_penetration)/2,0,100)) + block_chance_modifier
|
||||
if(wear_neck.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/can_embed(obj/item/I)
|
||||
if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/check_block()
|
||||
if(mind)
|
||||
@@ -135,39 +105,7 @@
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE)
|
||||
if(dna && dna.species)
|
||||
var/spec_return = dna.species.spec_hitby(AM, src)
|
||||
if(spec_return)
|
||||
return spec_return
|
||||
var/obj/item/I
|
||||
var/throwpower = 30
|
||||
if(istype(AM, /obj/item))
|
||||
I = AM
|
||||
throwpower = I.throwforce
|
||||
if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions
|
||||
return ..()
|
||||
if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
else if(I)
|
||||
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && !(mind.martial_art && mind.martial_art.dodge_chance == 100))
|
||||
if(can_embed(I))
|
||||
if(prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))
|
||||
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
|
||||
var/obj/item/bodypart/L = pick(bodyparts)
|
||||
L.embedded_objects |= I
|
||||
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
|
||||
I.forceMove(src)
|
||||
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
|
||||
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE //can't catch the now embedded item
|
||||
if (mind)
|
||||
if (mind.martial_art && mind.martial_art.dodge_chance == 100)
|
||||
skipcatch = FALSE
|
||||
return ..()
|
||||
return dna?.species?.spec_hitby(AM, src) || ..()
|
||||
|
||||
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (HAS_TRAIT(src, TRAIT_FAT)) && ismonkey(pulling))
|
||||
@@ -201,12 +139,12 @@
|
||||
return dna.species.spec_attacked_by(I, user, affecting, a_intent, src)
|
||||
|
||||
|
||||
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
if(check_shields(user, 15, "the [hulk_verb]ing"))
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
..(user, 1)
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
|
||||
var/message = "[user] has [hulk_verb]ed [src]!"
|
||||
visible_message("<span class='danger'>[message]</span>", \
|
||||
@@ -215,7 +153,8 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/attack_hand(mob/user)
|
||||
if(..()) //to allow surgery to return properly.
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -227,8 +166,7 @@
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(M.a_intent == INTENT_HELP)
|
||||
..() //shaking
|
||||
return 0
|
||||
return ..() //shaking
|
||||
|
||||
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead.
|
||||
var/obj/item/I = get_active_held_item()
|
||||
@@ -249,78 +187,69 @@
|
||||
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
|
||||
if(..()) //successful monkey bite, this handles disease contraction.
|
||||
var/damage = rand(1, 3)
|
||||
if(check_shields(M, damage, "the [M.name]"))
|
||||
return 0
|
||||
if(stat != DEAD)
|
||||
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
|
||||
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(check_shields(M, 0, "the M.name"))
|
||||
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
|
||||
return 0
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
if (w_uniform)
|
||||
w_uniform.add_fingerprint(M)
|
||||
var/damage = prob(90) ? 20 : 0
|
||||
if(!damage)
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has lunged at [src]!</span>")
|
||||
return 0
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee", null, null,10)
|
||||
|
||||
if(..())
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
if (w_uniform)
|
||||
w_uniform.add_fingerprint(M)
|
||||
var/damage = prob(90) ? 20 : 0
|
||||
if(!damage)
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has lunged at [src]!</span>")
|
||||
return 0
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee", null, null,10)
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>")
|
||||
log_combat(M, src, "attacked")
|
||||
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>")
|
||||
log_combat(M, src, "attacked")
|
||||
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I && dropItemToGround(I))
|
||||
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] disarmed [src]!</span>")
|
||||
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I && dropItemToGround(I))
|
||||
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] disarmed [src]!</span>")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(!lying) //CITADEL EDIT
|
||||
Knockdown(100, TRUE, FALSE, 30, 25)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(!lying) //CITADEL EDIT
|
||||
Knockdown(100, TRUE, FALSE, 30, 25)
|
||||
else
|
||||
Knockdown(100)
|
||||
log_combat(M, src, "tackled")
|
||||
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [src]!</span>")
|
||||
|
||||
Knockdown(100)
|
||||
log_combat(M, src, "tackled")
|
||||
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [src]!</span>")
|
||||
|
||||
/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
|
||||
if(..()) //successful larva bite.
|
||||
var/damage = rand(1, 3)
|
||||
if(check_shields(L, damage, "the [L.name]"))
|
||||
return 0
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful larva bite.
|
||||
return
|
||||
var/damage = rand(1, 3)
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
|
||||
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(check_shields(M, damage, "the [M.name]", MELEE_ATTACK, M.armour_penetration))
|
||||
return FALSE
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return TRUE
|
||||
@@ -332,23 +261,22 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
var/damage = rand(5, 25)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 35)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime attack
|
||||
return
|
||||
var/damage = rand(5, 25)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 35)
|
||||
|
||||
if(check_shields(M, damage, "the [M.name]"))
|
||||
return 0
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
|
||||
if(M.occupant.a_intent == INTENT_HARM)
|
||||
|
||||
@@ -1685,11 +1685,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
attacker_style = M.mind.martial_art
|
||||
if(attacker_style?.pacifism_check && HAS_TRAIT(M, TRAIT_PACIFISM)) // most martial arts are quite harmful, alas.
|
||||
attacker_style = null
|
||||
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
|
||||
log_combat(M, H, "attempted to touch")
|
||||
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
|
||||
return 0
|
||||
SEND_SIGNAL(M, COMSIG_MOB_ATTACK_HAND, M, H, attacker_style)
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
help(M, H, attacker_style)
|
||||
|
||||
@@ -369,6 +369,23 @@
|
||||
retaliate(L)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(M.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(M)
|
||||
else if(M.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
|
||||
retaliate(M)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(L)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(user)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_paw(mob/living/L)
|
||||
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(L)
|
||||
|
||||
@@ -6,37 +6,55 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_paw(mob/living/M)
|
||||
if(..()) //successful monkey bite.
|
||||
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(M.limb_destroyer)
|
||||
dismembering_strike(M, affecting.body_zone)
|
||||
if(stat != DEAD)
|
||||
var/dmg = rand(1, 5)
|
||||
apply_damage(dmg, BRUTE, affecting)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful monkey bite.
|
||||
return
|
||||
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(M.limb_destroyer)
|
||||
dismembering_strike(M, affecting.body_zone)
|
||||
var/dmg = rand(1, 5)
|
||||
apply_damage(dmg, BRUTE, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(..()) //successful larva bite.
|
||||
var/damage = rand(1, 3)
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful larva bite
|
||||
return
|
||||
var/damage = rand(1, 3)
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
|
||||
var/message = "[user] has [hulk_verb]ed [src]!"
|
||||
visible_message("<span class='danger'>[message]</span>", \
|
||||
"<span class='userdanger'>[message]</span>")
|
||||
adjustBruteLoss(15)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
|
||||
if(..()) //To allow surgery to return properly.
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
help_shake_act(M)
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
if (prob(75))
|
||||
visible_message("<span class='danger'>[M] has punched [name]!</span>", \
|
||||
@@ -60,7 +78,7 @@
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to punch [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to punch [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if("disarm")
|
||||
if(INTENT_DISARM)
|
||||
if(!IsUnconscious())
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
if (prob(25))
|
||||
@@ -74,50 +92,51 @@
|
||||
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", "<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent.
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if ((prob(95) && health > 0))
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
var/damage = rand(15, 30)
|
||||
if (damage >= 25)
|
||||
damage = rand(20, 40)
|
||||
if(AmountUnconscious() < 300)
|
||||
Unconscious(rand(200, 300))
|
||||
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
log_combat(M, src, "attacked")
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if ((prob(95) && health > 0))
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
var/damage = rand(15, 30)
|
||||
if (damage >= 25)
|
||||
damage = rand(20, 40)
|
||||
if(AmountUnconscious() < 300)
|
||||
Unconscious(rand(200, 300))
|
||||
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
if (M.a_intent == INTENT_DISARM)
|
||||
var/obj/item/I = null
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(prob(95))
|
||||
Knockdown(20)
|
||||
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
log_combat(M, src, "attacked")
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
else
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
else
|
||||
var/obj/item/I = null
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(prob(95))
|
||||
Knockdown(20)
|
||||
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = get_active_held_item()
|
||||
if(dropItemToGround(I))
|
||||
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = get_active_held_item()
|
||||
if(dropItemToGround(I))
|
||||
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = null
|
||||
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
updatehealth()
|
||||
|
||||
I = null
|
||||
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
|
||||
. = ..()
|
||||
@@ -132,17 +151,19 @@
|
||||
apply_damage(damage, M.melee_damage_type, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime attack
|
||||
return
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit)
|
||||
. = 1
|
||||
|
||||
@@ -36,7 +36,50 @@
|
||||
/mob/living/proc/on_hit(obj/item/projectile/P)
|
||||
return
|
||||
|
||||
/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
|
||||
var/block_chance_modifier = round(damage / -3)
|
||||
for(var/obj/item/I in held_items)
|
||||
if(!istype(I, /obj/item/clothing))
|
||||
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
|
||||
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/check_reflect(def_zone) //Reflection checks for anything in your hands, based on the reflection chance of the object(s)
|
||||
for(var/obj/item/I in held_items)
|
||||
if(I.IsReflect(def_zone))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/reflect_bullet_check(obj/item/projectile/P, def_zone)
|
||||
if(P.is_reflectable && check_reflect(def_zone)) // Checks if you've passed a reflection% check
|
||||
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
|
||||
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
|
||||
// Find a turf near or on the original location to bounce to
|
||||
if(P.starting)
|
||||
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(src)
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
var/new_angle_s = P.Angle + rand(120,240)
|
||||
while(new_angle_s > 180) // Translate to regular projectile degrees
|
||||
new_angle_s -= 360
|
||||
P.setAngle(new_angle_s)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
|
||||
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
|
||||
if(reflect_bullet_check(P, def_zone))
|
||||
return -1 // complete projectile permutation
|
||||
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return 2
|
||||
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
|
||||
if(!P.nodamage)
|
||||
apply_damage(P.damage, P.damage_type, def_zone, armor)
|
||||
@@ -55,9 +98,32 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/embed_item(obj/item/I)
|
||||
return
|
||||
|
||||
/mob/living/proc/can_embed(obj/item/I)
|
||||
return FALSE
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
var/obj/item/I
|
||||
var/throwpower = 30
|
||||
if(isitem(AM))
|
||||
I = AM
|
||||
throwpower = I.throwforce
|
||||
if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
else if(I && I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && can_embed(I, src) && prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE) && (!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) || incapacitated() || get_active_held_item()))
|
||||
embed_item(I)
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE //can't catch the now embedded item
|
||||
if(I)
|
||||
if(!skipcatch && isturf(I.loc) && catch_item(I))
|
||||
return TRUE
|
||||
var/zone = ran_zone(BODY_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()
|
||||
@@ -214,6 +280,24 @@
|
||||
Move(user.loc)
|
||||
return 1
|
||||
|
||||
/mob/living/attack_hand(mob/user)
|
||||
..() //Ignoring parent return value here.
|
||||
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user)
|
||||
if((user != src) && user.a_intent != INTENT_HELP && check_shields(user, 0, user.name, attack_type = UNARMED_ATTACK))
|
||||
log_combat(user, src, "attempted to touch")
|
||||
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>")
|
||||
return TRUE
|
||||
|
||||
/mob/living/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return TRUE
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
if(user != src && check_shields(user, 15, "the [hulk_verb]ing"))
|
||||
return TRUE
|
||||
..()
|
||||
return FALSE
|
||||
|
||||
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(!SSticker.HasRoundStarted())
|
||||
@@ -229,6 +313,12 @@
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
if(check_shields(M, damage, "the [M.name]"))
|
||||
return FALSE
|
||||
|
||||
if (stat != DEAD)
|
||||
log_combat(M, src, "attacked")
|
||||
M.do_attack_animation(src)
|
||||
@@ -245,7 +335,8 @@
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
|
||||
if(check_shields(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", MELEE_ATTACK, M.armour_penetration))
|
||||
return FALSE
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
M.do_attack_animation(src)
|
||||
@@ -256,10 +347,6 @@
|
||||
|
||||
|
||||
/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 FALSE
|
||||
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
@@ -268,6 +355,8 @@
|
||||
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 FALSE
|
||||
if(check_shields(M, 0, "the [M.name]"))
|
||||
return FALSE
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
|
||||
if (prob(75))
|
||||
log_combat(M, src, "attacked")
|
||||
@@ -282,15 +371,16 @@
|
||||
|
||||
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
switch(L.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
|
||||
return FALSE
|
||||
|
||||
else
|
||||
if(HAS_TRAIT(L, TRAIT_PACIFISM))
|
||||
to_chat(L, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return
|
||||
|
||||
return FALSE
|
||||
if(L != src && check_shields(L, rand(1, 3), "the [L.name]"))
|
||||
return FALSE
|
||||
L.do_attack_animation(src)
|
||||
if(prob(90))
|
||||
log_combat(L, src, "attacked")
|
||||
@@ -301,24 +391,29 @@
|
||||
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 FALSE
|
||||
|
||||
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if((M != src) && M.a_intent != INTENT_HELP && check_shields(M, 0, "the [M.name]"))
|
||||
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
|
||||
return FALSE
|
||||
switch(M.a_intent)
|
||||
if ("help")
|
||||
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
|
||||
if (INTENT_HELP)
|
||||
if(!isalien(src)) //I know it's ugly, but the alien vs alien attack_alien behaviour is a bit different.
|
||||
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
|
||||
return FALSE
|
||||
if ("grab")
|
||||
if (INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
return FALSE
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
M.do_attack_animation(src)
|
||||
if(!isalien(src))
|
||||
M.do_attack_animation(src)
|
||||
return TRUE
|
||||
if("disarm")
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
if(INTENT_DISARM)
|
||||
if(!isalien(src))
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
return TRUE
|
||||
|
||||
/mob/living/ex_act(severity, target, origin)
|
||||
|
||||
@@ -260,15 +260,6 @@
|
||||
viewalerts = 1
|
||||
src << browse(dat, "window=aialerts&can_close=0")
|
||||
|
||||
/mob/living/silicon/ai/proc/ai_roster()
|
||||
var/dat = "<html><head><title>Crew Roster</title></head><body><b>Crew Roster:</b><br><br>"
|
||||
|
||||
dat += GLOB.data_core.get_manifest()
|
||||
dat += "</body></html>"
|
||||
|
||||
src << browse(dat, "window=airoster")
|
||||
onclose(src, "airoster")
|
||||
|
||||
/mob/living/silicon/ai/proc/ai_call_shuttle()
|
||||
if(control_disabled)
|
||||
to_chat(usr, "<span class='warning'>Wireless control is disabled!</span>")
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
|
||||
/mob/living/silicon/ai/attacked_by(obj/item/I, mob/living/user, def_zone)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
|
||||
spark_system.start()
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(!SSticker.HasRoundStarted())
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
|
||||
return //immune to slimes
|
||||
|
||||
@@ -26,13 +26,14 @@
|
||||
fold_in(force = 1)
|
||||
Knockdown(200)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user)
|
||||
switch(user.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
visible_message("<span class='notice'>[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.</span>")
|
||||
if("disarm")
|
||||
if(INTENT_DISARM)
|
||||
visible_message("<span class='notice'>[user] boops [src] on the head!</span>")
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
user.do_attack_animation(src)
|
||||
if (user.name == master)
|
||||
visible_message("<span class='notice'>Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.</span>")
|
||||
@@ -41,14 +42,19 @@
|
||||
if(user.put_in_hands(card))
|
||||
user.visible_message("<span class='notice'>[user] promptly scoops up [user.p_their()] pAI's card.</span>")
|
||||
else
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return
|
||||
visible_message("<span class='danger'>[user] stomps on [src]!.</span>")
|
||||
take_holo_damage(2)
|
||||
else
|
||||
grabbedby(user)
|
||||
|
||||
/mob/living/silicon/pai/bullet_act(obj/item/projectile/Proj)
|
||||
if(Proj.stun)
|
||||
/mob/living/silicon/pai/bullet_act(obj/item/projectile/P, def_zone)
|
||||
if(P.stun)
|
||||
fold_in(force = TRUE)
|
||||
src.visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
|
||||
. = ..(Proj)
|
||||
visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
|
||||
. = ..()
|
||||
|
||||
/mob/living/silicon/pai/stripPanelUnequip(obj/item/what, mob/who, where) //prevents stripping
|
||||
to_chat(src, "<span class='warning'>Your holochassis stutters and warps intensely as you attempt to interact with the object, forcing you to cease lest the field fail.</span>")
|
||||
|
||||
@@ -1298,4 +1298,12 @@
|
||||
|
||||
/mob/living/silicon/robot/adjustStaminaLossBuffered(amount, updating_health = 1)
|
||||
if(istype(cell))
|
||||
cell.charge -= amount*5
|
||||
cell.charge -= amount*5
|
||||
|
||||
/mob/living/silicon/robot/verb/viewmanifest()
|
||||
set category = "Robot Commands"
|
||||
set name = "View Crew Manifest"
|
||||
|
||||
if(usr.stat == DEAD)
|
||||
return //won't work if dead
|
||||
ai_roster()
|
||||
@@ -13,7 +13,19 @@
|
||||
spark_system.start()
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
spark_system.start()
|
||||
spawn(0)
|
||||
step_away(src,user,15)
|
||||
sleep(3)
|
||||
step_away(src,user,15)
|
||||
|
||||
/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if (M.a_intent == INTENT_DISARM)
|
||||
if(!(lying))
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
@@ -30,24 +42,19 @@
|
||||
visible_message("<span class='danger'>[M] has forced back [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has forced back [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1)
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime shock
|
||||
flash_act()
|
||||
var/stunprob = M.powerlevel * 7 + 10
|
||||
if(prob(stunprob) && M.powerlevel >= 8)
|
||||
adjustBruteLoss(M.powerlevel * rand(6,10))
|
||||
|
||||
var/damage = rand(1, 3)
|
||||
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime shock
|
||||
return
|
||||
var/stunprob = M.powerlevel * 7 + 10
|
||||
var/damage = M.powerlevel * rand(6,10)
|
||||
if(prob(stunprob) && M.powerlevel >= 8)
|
||||
flash_act(affect_silicon = TRUE) //my borg eyes!
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
damage += rand(10, 20)
|
||||
else
|
||||
damage = rand(5, 35)
|
||||
damage = round(damage / 2) // borgs receive half damage
|
||||
damage += rand(2, 17)
|
||||
adjustBruteLoss(damage)
|
||||
updatehealth()
|
||||
|
||||
@@ -56,23 +63,17 @@
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user)
|
||||
add_fingerprint(user)
|
||||
if(opened && !wiresexposed && !issilicon(user))
|
||||
if(cell)
|
||||
cell.update_icon()
|
||||
cell.add_fingerprint(user)
|
||||
user.put_in_active_hand(cell)
|
||||
to_chat(user, "<span class='notice'>You remove \the [cell].</span>")
|
||||
cell = null
|
||||
update_icons()
|
||||
diag_hud_set_borgcell()
|
||||
if(opened && !wiresexposed && cell && !issilicon(user))
|
||||
cell.update_icon()
|
||||
cell.add_fingerprint(user)
|
||||
user.put_in_active_hand(cell)
|
||||
to_chat(user, "<span class='notice'>You remove \the [cell].</span>")
|
||||
cell = null
|
||||
update_icons()
|
||||
diag_hud_set_borgcell()
|
||||
|
||||
if(!opened)
|
||||
if(..()) // hulk attack
|
||||
spark_system.start()
|
||||
spawn(0)
|
||||
step_away(src,user,15)
|
||||
sleep(3)
|
||||
step_away(src,user,15)
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/fire_act()
|
||||
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
|
||||
@@ -182,9 +183,9 @@
|
||||
if (stat != DEAD)
|
||||
adjustBruteLoss(30)
|
||||
|
||||
/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj)
|
||||
..(Proj)
|
||||
/mob/living/silicon/robot/bullet_act(obj/item/projectile/P, def_zone)
|
||||
..()
|
||||
updatehealth()
|
||||
if(prob(75) && Proj.damage > 0)
|
||||
if(prob(75) && P.damage > 0)
|
||||
spark_system.start()
|
||||
return 2
|
||||
|
||||
@@ -389,6 +389,15 @@
|
||||
if (aicamera)
|
||||
return aicamera.selectpicture(user)
|
||||
|
||||
/mob/living/silicon/proc/ai_roster()
|
||||
var/dat = "<html><head><title>Crew Roster</title></head><body><b>Crew Roster:</b><br><br>"
|
||||
|
||||
dat += GLOB.data_core.get_manifest()
|
||||
dat += "</body></html>"
|
||||
|
||||
src << browse(dat, "window=airoster")
|
||||
onclose(src, "airoster")
|
||||
|
||||
/mob/living/silicon/update_transform()
|
||||
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
|
||||
var/changed = 0
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
return 2
|
||||
|
||||
/mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
var/damage = 20
|
||||
if (prob(90))
|
||||
log_combat(M, src, "attacked")
|
||||
@@ -49,34 +52,33 @@
|
||||
/mob/living/silicon/attack_paw(mob/living/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(L.a_intent == INTENT_HELP)
|
||||
visible_message("[L.name] rubs its head against [src].")
|
||||
|
||||
/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
adjustBruteLoss(rand(10, 15))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[user] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has punched [src]!</span>")
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/silicon/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
if(.) //the attack was blocked
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if ("help")
|
||||
if (INTENT_HELP)
|
||||
M.visible_message("[M] pets [src].", \
|
||||
"<span class='notice'>You pet [src].</span>")
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
else
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
playsound(src.loc, 'sound/effects/bang.ogg', 10, 1)
|
||||
visible_message("<span class='danger'>[M] punches [src], but doesn't leave a dent.</span>", \
|
||||
"<span class='warning'>[M] punches [src], but doesn't leave a dent.</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 0
|
||||
|
||||
/mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M)
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
@@ -108,19 +110,25 @@
|
||||
M.visible_message("<span class='boldwarning'>[M] is thrown off of [src]!</span>")
|
||||
flash_act(affect_silicon = 1)
|
||||
|
||||
/mob/living/silicon/bullet_act(obj/item/projectile/Proj)
|
||||
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
|
||||
adjustBruteLoss(Proj.damage)
|
||||
if(prob(Proj.damage*1.5))
|
||||
/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
|
||||
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
|
||||
if(reflect_bullet_check(P, def_zone))
|
||||
return -1 // complete projectile permutation
|
||||
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return 2
|
||||
if((P.damage_type == BRUTE || P.damage_type == BURN))
|
||||
adjustBruteLoss(P.damage)
|
||||
if(prob(P.damage*1.5))
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>")
|
||||
unbuckle_mob(M)
|
||||
M.Knockdown(40)
|
||||
if(Proj.stun || Proj.knockdown)
|
||||
if(P.stun || P.knockdown)
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
unbuckle_mob(M)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [Proj]!</span>")
|
||||
Proj.on_hit(src)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [P]!</span>")
|
||||
P.on_hit(src)
|
||||
return 2
|
||||
|
||||
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/static)
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
|
||||
|
||||
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
|
||||
..()
|
||||
. = ..()
|
||||
if(.) //the attack was blocked
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
if (health > 0)
|
||||
visible_message("<span class='notice'>[M] [response_help] [src].</span>")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
|
||||
vore_attack(M, pulling)
|
||||
else
|
||||
grabbedby(M)
|
||||
|
||||
if("harm", "disarm")
|
||||
if(INTENT_HARM, INTENT_DISARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return
|
||||
@@ -27,12 +29,11 @@
|
||||
updatehealth()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return FALSE
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[user] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
@@ -40,32 +41,32 @@
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(..()) //successful monkey bite.
|
||||
if(stat != DEAD)
|
||||
var/damage = rand(1, 3)
|
||||
attack_threshold_check(damage)
|
||||
return 1
|
||||
. = ..()
|
||||
if(.) //successful larva bite
|
||||
var/damage = rand(1, 3)
|
||||
attack_threshold_check(damage)
|
||||
return 1
|
||||
if (M.a_intent == INTENT_HELP)
|
||||
if (health > 0)
|
||||
visible_message("<span class='notice'>[M.name] [response_help] [src].</span>")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
|
||||
/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent.
|
||||
if(M.a_intent == INTENT_DISARM)
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
|
||||
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(M, src, "disarmed")
|
||||
else
|
||||
var/damage = rand(15, 30)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
attack_threshold_check(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
return 1
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if(M.a_intent == INTENT_DISARM)
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
|
||||
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(M, src, "disarmed")
|
||||
else
|
||||
var/damage = rand(15, 30)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
attack_threshold_check(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
|
||||
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
. = ..()
|
||||
@@ -82,7 +83,8 @@
|
||||
return attack_threshold_check(damage, M.melee_damage_type)
|
||||
|
||||
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
. = ..()
|
||||
if(.) //successful slime shock
|
||||
var/damage = rand(15, 25)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 35)
|
||||
|
||||
@@ -318,9 +318,9 @@
|
||||
sleep(50)
|
||||
if(mode == BOT_REPAIRING && src.loc == target_turf)
|
||||
if(autotile) //Build the floor and include a tile.
|
||||
target_turf.PlaceOnTop(/turf/open/floor/plasteel)
|
||||
target_turf.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
|
||||
else //Build a hull plating without a floor tile.
|
||||
target_turf.PlaceOnTop(/turf/open/floor/plating)
|
||||
target_turf.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
|
||||
else
|
||||
var/turf/open/floor/F = target_turf
|
||||
@@ -334,7 +334,7 @@
|
||||
if(mode == BOT_REPAIRING && F && src.loc == F)
|
||||
F.broken = 0
|
||||
F.burnt = 0
|
||||
F.PlaceOnTop(/turf/open/floor/plasteel)
|
||||
F.PlaceOnTop(/turf/open/floor/plasteel, flags = CHANGETURF_INHERIT_AIR)
|
||||
|
||||
if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F))
|
||||
anchored = TRUE
|
||||
@@ -345,7 +345,7 @@
|
||||
if(mode == BOT_REPAIRING && F && src.loc == F)
|
||||
F.broken = 0
|
||||
F.burnt = 0
|
||||
F.PlaceOnTop(initial(tiletype.turf_type))
|
||||
F.PlaceOnTop(initial(tiletype.turf_type), flags = CHANGETURF_INHERIT_AIR)
|
||||
specialtiles -= 1
|
||||
if(specialtiles == 0)
|
||||
speak("Requesting refill of custom floortiles to continue replacing.")
|
||||
|
||||
@@ -113,7 +113,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
mode = BOT_HUNT
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
|
||||
if(H.a_intent == "harm")
|
||||
if(H.a_intent == INTENT_HARM)
|
||||
retaliate(H)
|
||||
addtimer(CALLBACK(src, .proc/react_buzz), 5)
|
||||
return ..()
|
||||
|
||||
@@ -232,9 +232,9 @@
|
||||
/mob/living/simple_animal/pet/cat/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
wuv(1, M)
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
wuv(-1, M)
|
||||
|
||||
/mob/living/simple_animal/pet/cat/proc/wuv(change, mob/M)
|
||||
@@ -290,7 +290,9 @@
|
||||
D.decorate_donut()
|
||||
|
||||
/mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L)
|
||||
..()
|
||||
. = ..()
|
||||
if(.) //the attack was blocked
|
||||
return
|
||||
if(L.a_intent == INTENT_HARM && L.reagents && !stat)
|
||||
L.reagents.add_reagent("nutriment", 0.4)
|
||||
L.reagents.add_reagent("vitamin", 0.4)
|
||||
|
||||
@@ -643,9 +643,9 @@
|
||||
/mob/living/simple_animal/pet/dog/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
wuv(1,M)
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
wuv(-1,M)
|
||||
|
||||
/mob/living/simple_animal/pet/dog/proc/wuv(change, mob/M)
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
|
||||
//picky up the drone c:
|
||||
/mob/living/simple_animal/drone/attack_hand(mob/user)
|
||||
..()
|
||||
if(user.a_intent == INTENT_HELP)
|
||||
mob_try_pickup(user)
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return ..() // TODO: convert picking up mobs into an element or component.
|
||||
mob_try_pickup(user)
|
||||
|
||||
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
|
||||
var/mob/dead/observer/G = get_ghost()
|
||||
|
||||
@@ -54,10 +54,8 @@
|
||||
var/blocked = FALSE
|
||||
if(hasmatchingsummoner(A)) //if the summoner matches don't hurt them
|
||||
blocked = TRUE
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(H.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
|
||||
blocked = TRUE
|
||||
if(L.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
|
||||
blocked = TRUE
|
||||
if(!blocked)
|
||||
L.drop_all_held_items()
|
||||
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] slams into you!</span>")
|
||||
|
||||
@@ -486,10 +486,7 @@ Difficulty: Very Hard
|
||||
if(isturf(Stuff))
|
||||
var/turf/T = Stuff
|
||||
if((isspaceturf(T) || isfloorturf(T)) && NewTerrainFloors)
|
||||
var/turf/open/O = T.ChangeTurf(NewTerrainFloors)
|
||||
if(O.air)
|
||||
var/datum/gas_mixture/G = O.air
|
||||
G.copy_from_turf(O)
|
||||
var/turf/open/O = T.ChangeTurf(NewTerrainFloors, flags = CHANGETURF_INHERIT_AIR)
|
||||
if(prob(florachance) && NewFlora.len && !is_blocked_turf(O, TRUE))
|
||||
var/atom/Picked = pick(NewFlora)
|
||||
new Picked(O)
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
|
||||
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
||||
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
|
||||
var/list/crusher_loot
|
||||
var/medal_type
|
||||
var/score_type = BOSS_SCORE
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
var/icon_aggro = null
|
||||
var/crusher_drop_mod = 5
|
||||
var/crusher_drop_mod = 25
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -58,7 +58,7 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/death(gibbed)
|
||||
SSblackbox.record_feedback("tally", "mobs_killed_mining", 1, type)
|
||||
var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
|
||||
if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 20 creatures before getting the item
|
||||
if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 4 creatures before getting the item
|
||||
spawn_crusher_loot()
|
||||
..(gibbed)
|
||||
|
||||
|
||||
@@ -91,5 +91,5 @@
|
||||
visible_message("<span class='boldannounce'>The tendril falls inward, the ground around it widening into a yawning chasm!</span>")
|
||||
for(var/turf/T in range(2,src))
|
||||
if(!T.density)
|
||||
T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland)
|
||||
T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland, flags = CHANGETURF_INHERIT_AIR)
|
||||
qdel(src)
|
||||
|
||||
@@ -166,7 +166,9 @@
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M)
|
||||
..()
|
||||
. = ..()
|
||||
if(.) // the attack was blocked
|
||||
return
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
Bruise()
|
||||
|
||||
|
||||
@@ -253,33 +253,34 @@
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
if(M == src)
|
||||
return
|
||||
if(buckled)
|
||||
Feedstop(silent = TRUE)
|
||||
visible_message("<span class='danger'>[M] pulls [src] off!</span>")
|
||||
return
|
||||
attacked += 5
|
||||
if(nutrition >= 100) //steal some nutrition. negval handled in life()
|
||||
nutrition -= (50 + (40 * M.is_adult))
|
||||
M.add_nutrition(50 + (40 * M.is_adult))
|
||||
if(health > 0)
|
||||
M.adjustBruteLoss(-10 + (-10 * M.is_adult))
|
||||
M.updatehealth()
|
||||
. = ..()
|
||||
if(!. || M == src) //unsuccessful slime shock
|
||||
return
|
||||
if(buckled)
|
||||
Feedstop(silent = TRUE)
|
||||
visible_message("<span class='danger'>[M] pulls [src] off!</span>")
|
||||
return
|
||||
attacked += 5
|
||||
if(nutrition >= 100) //steal some nutrition. negval handled in life()
|
||||
nutrition -= (50 + (40 * M.is_adult))
|
||||
M.add_nutrition(50 + (40 * M.is_adult))
|
||||
if(health > 0)
|
||||
M.adjustBruteLoss(-10 + (-10 * M.is_adult))
|
||||
M.updatehealth()
|
||||
|
||||
/mob/living/simple_animal/slime/attack_animal(mob/living/simple_animal/M)
|
||||
. = ..()
|
||||
if(.)
|
||||
attacked += 10
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(..()) //successful monkey bite.
|
||||
. = ..()
|
||||
if(.)//successful monkey bite.
|
||||
attacked += 10
|
||||
|
||||
/mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(..()) //successful larva bite.
|
||||
. = ..()
|
||||
if(.) //successful larva bite.
|
||||
attacked += 10
|
||||
|
||||
/mob/living/simple_animal/slime/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
@@ -321,9 +322,11 @@
|
||||
attacked += 10
|
||||
|
||||
/mob/living/simple_animal/slime/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent.
|
||||
attacked += 10
|
||||
discipline_slime(M)
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
attacked += 10
|
||||
discipline_slime(M)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/attackby(obj/item/W, mob/living/user, params)
|
||||
|
||||
@@ -26,10 +26,9 @@ Contents:
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/enable_signals()
|
||||
if(!affecting)
|
||||
return
|
||||
RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth)
|
||||
RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth)
|
||||
RegisterSignal(affecting, COMSIG_MOVABLE_BUMP, .proc/bumping_stealth)
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/reduce_stealth(datum/source)
|
||||
affecting.alpha = min(affecting.alpha + 40, 100)
|
||||
|
||||
@@ -42,7 +41,7 @@ Contents:
|
||||
return FALSE
|
||||
stealth = !stealth
|
||||
stealth_cooldown = world.time + 5 SECONDS
|
||||
UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE))
|
||||
UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE))
|
||||
animate(affecting, alpha = 255, time = 3 SECONDS)
|
||||
affecting.visible_message("<span class='warning'>[affecting.name] appears from thin air!</span>", \
|
||||
"<span class='notice'>You are now visible.</span>")
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
/obj/item/paperplane/throw_impact(atom/hit_atom)
|
||||
if(iscarbon(hit_atom))
|
||||
var/mob/living/carbon/C = hit_atom
|
||||
if(C.can_catch_item(TRUE))
|
||||
if(!C.get_active_held_item() && !C.restrained())
|
||||
var/datum/action/innate/origami/origami_action = locate() in C.actions
|
||||
if(origami_action?.active) //if they're a master of origami and have the ability turned on, force throwmode on so they'll automatically catch the plane.
|
||||
C.throw_mode_on()
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
var/burst_spread = 0 //Spread induced by the gun itself during burst fire per iteration. Only checked if spread is 0.
|
||||
var/randomspread = 1 //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once.
|
||||
var/inaccuracy_modifier = 1
|
||||
var/pb_knockback = 0
|
||||
|
||||
lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
|
||||
@@ -125,6 +126,10 @@
|
||||
if(message)
|
||||
if(pointblank)
|
||||
user.visible_message("<span class='danger'>[user] fires [src] point blank at [pbtarget]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
if(pb_knockback > 0)
|
||||
var/atom/throw_target = get_edge_target_turf(pbtarget, user.dir)
|
||||
pbtarget.throw_at(throw_target, pb_knockback, 2)
|
||||
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user] fires [src]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
|
||||
@@ -267,6 +267,7 @@
|
||||
fire_delay = 0
|
||||
pin = /obj/item/firing_pin/implant/pindicate
|
||||
actions_types = list()
|
||||
pb_knockback = 2
|
||||
|
||||
/obj/item/gun/ballistic/automatic/shotgun/bulldog/unrestricted
|
||||
pin = /obj/item/firing_pin
|
||||
|
||||
@@ -273,6 +273,7 @@
|
||||
"Maple" = "dshotgun-l",
|
||||
"Rosewood" = "dshotgun-p"
|
||||
)
|
||||
pb_knockback = 3 // it's a super shotgun!
|
||||
|
||||
/obj/item/gun/ballistic/revolver/doublebarrel/attackby(obj/item/A, mob/user, params)
|
||||
..()
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
var/recentpump = 0 // to prevent spammage
|
||||
weapon_weight = WEAPON_MEDIUM
|
||||
|
||||
pb_knockback = 2
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/attackby(obj/item/A, mob/user, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
item_flags = NONE
|
||||
casing_ejector = FALSE
|
||||
can_suppress = FALSE
|
||||
pb_knockback = 0
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/toy/process_chamber(empty_chamber = 0)
|
||||
..()
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
/obj/item/projectile/magic/door/proc/CreateDoor(turf/T)
|
||||
var/door_type = pick(door_types)
|
||||
var/obj/structure/mineral_door/D = new door_type(T)
|
||||
T.ChangeTurf(/turf/open/floor/plating)
|
||||
T.ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
D.Open()
|
||||
|
||||
/obj/item/projectile/magic/door/proc/OpenDoor(var/obj/machinery/door/D)
|
||||
|
||||
@@ -1870,133 +1870,82 @@
|
||||
reagent_state = LIQUID
|
||||
color = "#b51d05"
|
||||
taste_description = "carpet" // Your tounge feels furry.
|
||||
var/carpet_type = /turf/open/floor/carpet
|
||||
|
||||
/datum/reagent/carpet/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet)
|
||||
F.PlaceOnTop(carpet_type, flags = CHANGETURF_INHERIT_AIR)
|
||||
..()
|
||||
|
||||
/datum/reagent/carpet/black
|
||||
name = "Liquid Black Carpet"
|
||||
id = "blackcarpet"
|
||||
color = "#363636"
|
||||
|
||||
/datum/reagent/carpet/black/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/black)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/black
|
||||
|
||||
/datum/reagent/carpet/blackred
|
||||
name = "Liquid Red Black Carpet"
|
||||
id = "blackredcarpet"
|
||||
color = "#342125"
|
||||
|
||||
/datum/reagent/carpet/blackred/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/blackred)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/blackred
|
||||
|
||||
/datum/reagent/carpet/monochrome
|
||||
name = "Liquid Monochrome Carpet"
|
||||
id = "monochromecarpet"
|
||||
color = "#b4b4b4"
|
||||
|
||||
/datum/reagent/carpet/monochrome/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/monochrome)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/monochrome
|
||||
|
||||
/datum/reagent/carpet/blue
|
||||
name = "Liquid Blue Carpet"
|
||||
id = "bluecarpet"
|
||||
color = "#1256ff"
|
||||
|
||||
/datum/reagent/carpet/blue/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/blue)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/blue
|
||||
|
||||
/datum/reagent/carpet/cyan
|
||||
name = "Liquid Cyan Carpet"
|
||||
id = "cyancarpet"
|
||||
color = "#3acfb9"
|
||||
|
||||
/datum/reagent/carpet/cyan/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/cyan)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/cyan
|
||||
|
||||
/datum/reagent/carpet/green
|
||||
name = "Liquid Green Carpet"
|
||||
id = "greencarpet"
|
||||
color = "#619b62"
|
||||
|
||||
/datum/reagent/carpet/green/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/green)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/green
|
||||
|
||||
/datum/reagent/carpet/orange
|
||||
name = "Liquid Orange Carpet"
|
||||
id = "orangecarpet"
|
||||
color = "#cc7900"
|
||||
|
||||
/datum/reagent/carpet/orange/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/orange)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/orange
|
||||
|
||||
/datum/reagent/carpet/purple
|
||||
name = "Liquid Purple Carpet"
|
||||
id = "purplecarpet"
|
||||
color = "#6d3392"
|
||||
carpet_type = /turf/open/floor/carpet/purple
|
||||
|
||||
/datum/reagent/carpet/purple/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/purple)
|
||||
..()
|
||||
|
||||
/datum/reagent/carpet/red
|
||||
name = "Liquid Red Carpet"
|
||||
id = "redcarpet"
|
||||
color = "#871515"
|
||||
carpet_type = /turf/open/floor/carpet/red
|
||||
|
||||
/datum/reagent/carpet/red/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/red)
|
||||
..()
|
||||
|
||||
/datum/reagent/carpet/royalblack
|
||||
name = "Liquid Royal Black Carpet"
|
||||
id = "royalblackcarpet"
|
||||
color = "#483d05"
|
||||
carpet_type = /turf/open/floor/carpet/royalblack
|
||||
|
||||
/datum/reagent/carpet/royalblack/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/royalblack)
|
||||
..()
|
||||
|
||||
/datum/reagent/carpet/royalblue
|
||||
name = "Liquid Royal Blue Carpet"
|
||||
id = "royalbluecarpet"
|
||||
color = "#24227e"
|
||||
|
||||
/datum/reagent/carpet/royalblue/reaction_turf(turf/T, reac_volume)
|
||||
if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel))
|
||||
var/turf/open/floor/F = T
|
||||
F.PlaceOnTop(/turf/open/floor/carpet/royalblue)
|
||||
..()
|
||||
carpet_type = /turf/open/floor/carpet/royalblue
|
||||
|
||||
|
||||
// Virology virus food chems.
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
if(isplatingturf(T))
|
||||
var/turf/open/floor/plating/F = T
|
||||
if(prob(10 + F.burnt + 5*F.broken)) //broken or burnt plating is more susceptible to being destroyed
|
||||
F.ScrapeAway()
|
||||
F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
|
||||
if(isfloorturf(T))
|
||||
var/turf/open/floor/F = T
|
||||
if(prob(reac_volume))
|
||||
|
||||
@@ -123,24 +123,11 @@ GLOBAL_LIST_INIT(food_reagents, build_reagents_to_food()) //reagentid = related
|
||||
|
||||
/datum/chemical_reaction/randomized/proc/LoadOldRecipe(recipe_data)
|
||||
created = text2num(recipe_data["timestamp"])
|
||||
|
||||
var/req_reag = unwrap_reagent_list(recipe_data["required_reagents"])
|
||||
if(!req_reag)
|
||||
return FALSE
|
||||
required_reagents = req_reag
|
||||
|
||||
var/req_catalysts = unwrap_reagent_list(recipe_data["required_catalysts"])
|
||||
if(!req_catalysts)
|
||||
return FALSE
|
||||
required_catalysts = req_catalysts
|
||||
|
||||
required_reagents = SANITIZE_LIST(recipe_data["required_reagents"])
|
||||
required_catalysts = SANITIZE_LIST(recipe_data["required_catalysts"])
|
||||
required_temp = recipe_data["required_temp"]
|
||||
is_cold_recipe = recipe_data["is_cold_recipe"]
|
||||
|
||||
var/temp_results = unwrap_reagent_list(recipe_data["results"])
|
||||
if(!temp_results)
|
||||
return FALSE
|
||||
results = temp_results
|
||||
results = SANITIZE_LIST(recipe_data["results"])
|
||||
var/containerpath = text2path(recipe_data["required_container"])
|
||||
if(!containerpath)
|
||||
return FALSE
|
||||
|
||||
@@ -109,11 +109,13 @@
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker
|
||||
name = "beaker"
|
||||
desc = "A beaker. It can hold up to 50 units. Unable to withstand extreme pHes"
|
||||
desc = "A beaker. It can hold up to 60 units. Unable to withstand extreme pHes."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
volume = 60
|
||||
icon_state = "beaker"
|
||||
item_state = "beaker"
|
||||
materials = list(MAT_GLASS=500)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,60)
|
||||
beaker_weakness_bitflag = PH_WEAK
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/Initialize()
|
||||
@@ -156,28 +158,28 @@
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/jar
|
||||
name = "honey jar"
|
||||
desc = "A jar for honey. It can hold up to 50 units of sweet delight. Unable to withstand reagents of an extreme pH."
|
||||
desc = "A jar for honey. It can hold up to 60 units of sweet delight. Unable to withstand reagents of an extreme pH."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "vapour"
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/large
|
||||
name = "large beaker"
|
||||
desc = "A large beaker. Can hold up to 100 units. Unable to withstand reagents of an extreme pH."
|
||||
desc = "A large beaker. Can hold up to 120 units. Unable to withstand reagents of an extreme pH."
|
||||
icon_state = "beakerlarge"
|
||||
materials = list(MAT_GLASS=2500)
|
||||
volume = 100
|
||||
volume = 120
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,40,60,120)
|
||||
container_HP = 3
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/plastic
|
||||
name = "x-large beaker"
|
||||
desc = "An extra-large beaker. Can hold up to 150 units. Is able to resist acid and alkaline solutions, but melts at 444K"
|
||||
desc = "An extra-large beaker. Can hold up to 180 units. Is able to resist acid and alkaline solutions, but melts at 444 K."
|
||||
icon_state = "beakerwhite"
|
||||
materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000)
|
||||
volume = 150
|
||||
volume = 180
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,150)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,40,60,120,180)
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/plastic/Initialize()
|
||||
beaker_weakness_bitflag &= ~PH_WEAK
|
||||
@@ -191,14 +193,14 @@
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/meta
|
||||
name = "metamaterial beaker"
|
||||
desc = "A large beaker. Can hold up to 200 units. Is able to withstand all chemical situations."
|
||||
desc = "A large beaker. Can hold up to 240 units, and is able to withstand all chemical situations."
|
||||
icon_state = "beakergold"
|
||||
materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000, MAT_GOLD=1000, MAT_TITANIUM=1000)
|
||||
volume = 200
|
||||
volume = 240
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,200)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,40,60,120,200,240)
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/meta/Initialize()
|
||||
/obj/item/reagent_containers/glass/beaker/meta/Initialize() // why the fuck can't you just set the beaker weakness bitflags to nothing? fuck you
|
||||
beaker_weakness_bitflag &= ~PH_WEAK
|
||||
. = ..()
|
||||
|
||||
@@ -228,7 +230,7 @@
|
||||
volume = 300
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,300)
|
||||
container_HP = 4
|
||||
container_HP = 5
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/cryoxadone
|
||||
list_reagents = list("cryoxadone" = 30)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//hypovials used with the MkII hypospray. See hypospray.dm.
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial
|
||||
/obj/item/reagent_containers/glass/bottle/vial // these have literally no fucking right to just be better beakers that you can shit out of a chemmaster
|
||||
name = "broken hypovial"
|
||||
desc = "A hypovial compatible with most hyposprays."
|
||||
icon_state = "hypovial"
|
||||
@@ -27,6 +27,8 @@
|
||||
for(var/R in comes_with)
|
||||
reagents.add_reagent(R,comes_with[R])
|
||||
update_icon()
|
||||
// beaker_weakness_bitflag |= PH_WEAK // fuck you if you're using these like beakers
|
||||
// beaker_weakness_bitflag |= TEMP_WEAK
|
||||
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial/on_reagent_change()
|
||||
@@ -60,11 +62,11 @@
|
||||
/obj/item/reagent_containers/glass/bottle/vial/small
|
||||
name = "hypovial"
|
||||
volume = 60
|
||||
possible_transfer_amounts = list(5,10)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30)
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial/small/bluespace
|
||||
volume = 120
|
||||
possible_transfer_amounts = list(5,10)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30,40)
|
||||
name = "bluespace hypovial"
|
||||
icon_state = "hypovialbs"
|
||||
unique_reskin = null
|
||||
@@ -74,7 +76,7 @@
|
||||
desc = "A large hypovial, for deluxe hypospray models."
|
||||
icon_state = "hypoviallarge"
|
||||
volume = 120
|
||||
possible_transfer_amounts = list(5,10,15,20)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30,40,60)
|
||||
unique_reskin = list("large hypovial" = "hypoviallarge",
|
||||
"large red hypovial" = "hypoviallarge-b",
|
||||
"large blue hypovial" = "hypoviallarge-d",
|
||||
@@ -106,7 +108,7 @@
|
||||
add_overlay(filling)
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial/large/bluespace
|
||||
possible_transfer_amounts = list(5,10,15,20)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30,40,60)
|
||||
name = "bluespace large hypovial"
|
||||
volume = 240
|
||||
icon_state = "hypoviallargebs"
|
||||
|
||||
@@ -31,7 +31,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id)
|
||||
/obj/machinery/conveyor/inverted/Initialize(mapload)
|
||||
. = ..()
|
||||
if(mapload && !(dir in GLOB.diagonals))
|
||||
log_game("### MAPPING ERROR: [src] at [AREACOORD(src)] spawned without using a diagonal dir. Please replace with a normal version.")
|
||||
log_mapping("[src] at [AREACOORD(src)] spawned without using a diagonal dir. Please replace with a normal version.")
|
||||
|
||||
// Auto conveyour is always on unless unpowered
|
||||
|
||||
|
||||
@@ -25,6 +25,20 @@
|
||||
program_type = /datum/nanite_program/viral
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/research
|
||||
name = "Distributed Computing"
|
||||
desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
|
||||
id = "research_nanites"
|
||||
program_type = /datum/nanite_program/research
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/researchplus
|
||||
name = "Neural Network"
|
||||
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts. Can be overloaded to increase research output."
|
||||
id = "researchplus_nanites"
|
||||
program_type = /datum/nanite_program/researchplus
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/monitoring
|
||||
name = "Monitoring"
|
||||
desc = "The nanites monitor the host's vitals and location, sending them to the suit sensor network."
|
||||
@@ -39,6 +53,13 @@
|
||||
program_type = /datum/nanite_program/triggered/self_scan
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/dermal_button
|
||||
name = "Dermal Button"
|
||||
desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
|
||||
id = "dermal_button_nanites"
|
||||
program_type = /datum/nanite_program/dermal_button
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/stealth
|
||||
name = "Stealth"
|
||||
desc = "The nanites hide their activity and programming from superficial scans."
|
||||
@@ -46,6 +67,15 @@
|
||||
program_type = /datum/nanite_program/stealth
|
||||
category = list("Utility Nanites")
|
||||
|
||||
|
||||
/datum/design/nanites/reduced_diagnostics
|
||||
name = "Reduced Diagnostics"
|
||||
desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
|
||||
Doing so saves some power, slightly increasing their replication speed."
|
||||
id = "red_diag_nanites"
|
||||
program_type = /datum/nanite_program/reduced_diagnostics
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/access
|
||||
name = "Subdermal ID"
|
||||
desc = "The nanites store the host's ID access rights in a subdermal magnetic strip. Updates when triggered, copying the host's current access."
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
|
||||
/datum/nanite_program/stealth
|
||||
name = "Stealth"
|
||||
desc = "The nanites hide their activity and programming from superficial scans."
|
||||
desc = "The nanites mask their activity from superficial scans, becoming undetectable by HUDs and non-specialized scanners."
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
use_rate = 0.2
|
||||
|
||||
@@ -142,6 +142,22 @@
|
||||
. = ..()
|
||||
nanites.stealth = FALSE
|
||||
|
||||
/datum/nanite_program/reduced_diagnostics
|
||||
name = "Reduced Diagnostics"
|
||||
desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
|
||||
Doing so saves some power, slightly increasing their replication speed."
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
use_rate = -0.1
|
||||
|
||||
/datum/nanite_program/reduced_diagnostics/enable_passive_effect()
|
||||
. = ..()
|
||||
nanites.diagnostics = FALSE
|
||||
|
||||
/datum/nanite_program/reduced_diagnostics/disable_passive_effect()
|
||||
. = ..()
|
||||
nanites.diagnostics = TRUE
|
||||
|
||||
|
||||
/datum/nanite_program/relay
|
||||
name = "Relay"
|
||||
desc = "The nanites receive and relay long-range nanite signals."
|
||||
@@ -271,3 +287,138 @@
|
||||
if(fault == src)
|
||||
return
|
||||
fault.software_error()
|
||||
|
||||
/datum/nanite_program/dermal_button
|
||||
name = "Dermal Button"
|
||||
desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
|
||||
extra_settings = list("Sent Code","Button Name","Icon","Color")
|
||||
unique = FALSE
|
||||
var/datum/action/innate/nanite_button/button
|
||||
var/button_name = "Button"
|
||||
var/icon = "power"
|
||||
var/color = "green"
|
||||
var/sent_code = 0
|
||||
|
||||
/datum/nanite_program/dermal_button/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Button Name")
|
||||
var/new_button_name = stripped_input(user, "Choose the name for the button.", "Button Name", button_name, MAX_NAME_LEN)
|
||||
if(!new_button_name)
|
||||
return
|
||||
button_name = new_button_name
|
||||
if(setting == "Icon")
|
||||
var/new_icon = input("Select the icon to display on the button:", name) as null|anything in list("one","two","three","four","five","plus","minus","power")
|
||||
if(!new_icon)
|
||||
return
|
||||
icon = new_icon
|
||||
if(setting == "Color")
|
||||
var/new_color = input("Select the color of the button's icon:", name) as null|anything in list("green","red","yellow","blue")
|
||||
if(!new_color)
|
||||
return
|
||||
color = new_color
|
||||
|
||||
/datum/nanite_program/dermal_button/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Button Name")
|
||||
return button_name
|
||||
if(setting == "Icon")
|
||||
return capitalize(icon)
|
||||
if(setting == "Color")
|
||||
return capitalize(color)
|
||||
|
||||
/datum/nanite_program/dermal_button/copy_extra_settings_to(datum/nanite_program/dermal_button/target)
|
||||
target.sent_code = sent_code
|
||||
target.button_name = button_name
|
||||
target.icon = icon
|
||||
target.color = color
|
||||
|
||||
/datum/nanite_program/dermal_button/enable_passive_effect()
|
||||
. = ..()
|
||||
if(!button)
|
||||
button = new(src, button_name, icon, color)
|
||||
button.target = host_mob
|
||||
button.Grant(host_mob)
|
||||
|
||||
/datum/nanite_program/dermal_button/disable_passive_effect()
|
||||
. = ..()
|
||||
if(button)
|
||||
button.Remove(host_mob)
|
||||
|
||||
/datum/nanite_program/dermal_button/on_mob_remove()
|
||||
. = ..()
|
||||
qdel(button)
|
||||
|
||||
/datum/nanite_program/dermal_button/proc/press()
|
||||
if(activated)
|
||||
host_mob.visible_message("<span class='notice'>[host_mob] presses a button on [host_mob.p_their()] forearm.</span>",
|
||||
"<span class='notice'>You press the nanite button on your forearm.</span>", null, 2)
|
||||
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, sent_code, "a [name] program")
|
||||
|
||||
/datum/action/innate/nanite_button
|
||||
name = "Button"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "power_green"
|
||||
var/datum/nanite_program/dermal_button/program
|
||||
|
||||
/datum/action/innate/nanite_button/New(datum/nanite_program/dermal_button/_program, _name, _icon, _color)
|
||||
..()
|
||||
program = _program
|
||||
name = _name
|
||||
button_icon_state = "[_icon]_[_color]"
|
||||
|
||||
/datum/action/innate/nanite_button/Activate()
|
||||
program.press()
|
||||
|
||||
/datum/nanite_program/research
|
||||
name = "Distributed Computing"
|
||||
desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
|
||||
use_rate = 0.2
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/research/active_effect()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
var/points = 1
|
||||
if(!host_mob.client) //less brainpower
|
||||
points *= 0.25
|
||||
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
|
||||
|
||||
/datum/nanite_program/researchplus
|
||||
name = "Neural Network"
|
||||
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts."
|
||||
use_rate = 0.3
|
||||
rogue_types = list(/datum/nanite_program/brain_decay)
|
||||
|
||||
/datum/nanite_program/researchplus/enable_passive_effect()
|
||||
. = ..()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
if(host_mob.client)
|
||||
SSnanites.neural_network_count++
|
||||
else
|
||||
SSnanites.neural_network_count += 0.25
|
||||
|
||||
/datum/nanite_program/researchplus/disable_passive_effect()
|
||||
. = ..()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
if(host_mob.client)
|
||||
SSnanites.neural_network_count--
|
||||
else
|
||||
SSnanites.neural_network_count -= 0.25
|
||||
|
||||
/datum/nanite_program/researchplus/active_effect()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
var/mob/living/carbon/C = host_mob
|
||||
var/points = round(SSnanites.neural_network_count / 12, 0.1)
|
||||
if(!C.client) //less brainpower
|
||||
points *= 0.25
|
||||
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
|
||||
|
||||
|
||||
@@ -130,4 +130,16 @@
|
||||
program_type = /datum/nanite_program/pacifying
|
||||
|
||||
/obj/item/disk/nanite_program/stun
|
||||
program_type = /datum/nanite_program/triggered/stun
|
||||
program_type = /datum/nanite_program/triggered/stun
|
||||
|
||||
/obj/item/disk/nanite_program/dermal_button
|
||||
program_type = /datum/nanite_program/dermal_button
|
||||
|
||||
/obj/item/disk/nanite_program/research
|
||||
program_type = /datum/nanite_program/research
|
||||
|
||||
/obj/item/disk/nanite_program/researchplus
|
||||
program_type = /datum/nanite_program/researchplus
|
||||
|
||||
/obj/item/disk/nanite_program/reduced_diagnostics
|
||||
program_type = /datum/nanite_program/reduced_diagnostics
|
||||
@@ -960,7 +960,7 @@
|
||||
prereq_ids = list("datatheory","robotics")
|
||||
design_ids = list("nanite_disk","nanite_remote","nanite_scanner",\
|
||||
"nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\
|
||||
"relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites")
|
||||
"relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
@@ -969,7 +969,7 @@
|
||||
display_name = "Smart Nanite Programming"
|
||||
description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets."
|
||||
prereq_ids = list("nanite_base","adv_robotics")
|
||||
design_ids = list("purging_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
|
||||
design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000)
|
||||
export_price = 4000
|
||||
|
||||
@@ -978,7 +978,7 @@
|
||||
display_name = "Mesh Nanite Programming"
|
||||
description = "Nanite programs that require static structures and membranes."
|
||||
prereq_ids = list("nanite_base","engineering")
|
||||
design_ids = list("hardening_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
|
||||
design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
@@ -1015,7 +1015,7 @@
|
||||
display_name = "Harmonic Nanite Programming"
|
||||
description = "Nanite programs that require seamless integration between nanites and biology."
|
||||
prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh")
|
||||
design_ids = list("fakedeath_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
|
||||
design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000)
|
||||
export_price = 8000
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
if (levels.len)
|
||||
dest = locate(T.x, T.y, pick(levels))
|
||||
|
||||
T.ChangeTurf(/turf/open/chasm)
|
||||
T.ChangeTurf(/turf/open/chasm, flags = CHANGETURF_INHERIT_AIR)
|
||||
var/turf/open/chasm/C = T
|
||||
C.set_target(dest)
|
||||
C.drop(user)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
if(ispath(summoned_object_type, /turf))
|
||||
var/turf/O = spawn_place
|
||||
var/N = summoned_object_type
|
||||
O.ChangeTurf(N)
|
||||
O.ChangeTurf(N, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
var/atom/summoned_object = new summoned_object_type(spawn_place)
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
dancefloor_exists = FALSE
|
||||
for(var/i in 1 to dancefloor_turfs.len)
|
||||
var/turf/T = dancefloor_turfs[i]
|
||||
T.ChangeTurf(dancefloor_turfs_types[i])
|
||||
T.ChangeTurf(dancefloor_turfs_types[i], flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
var/list/funky_turfs = RANGE_TURFS(1, user)
|
||||
for(var/turf/closed/solid in funky_turfs)
|
||||
@@ -248,7 +248,7 @@
|
||||
var/turf/T = t
|
||||
dancefloor_turfs[i] = T
|
||||
dancefloor_turfs_types[i] = T.type
|
||||
T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b)
|
||||
T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b, flags = CHANGETURF_INHERIT_AIR)
|
||||
i++
|
||||
|
||||
/datum/effect_system/smoke_spread/transparent/dancefloor_devil
|
||||
|
||||
Reference in New Issue
Block a user