Lay groundwork for megafauna, and add Ashdragon.

Includes a refactor for gun turrets (merged into portable turrets), hostile simple_animal behaviour, spells (sounds have been added) and poi_list items.
This commit is contained in:
Markolie
2016-10-23 23:15:57 +02:00
parent f110b9e6a5
commit 2e711d1337
122 changed files with 1650 additions and 776 deletions

View File

@@ -4,7 +4,7 @@
"aad" = (/obj/docking_port/stationary{dheight = 9; dir = 2; dwidth = 5; height = 22; id = "syndicate_n"; name = "north of station"; width = 18},/turf/space,/area/space)
"aae" = (/turf/simulated/shuttle/wall{tag = "icon-swall12"; icon_state = "swall12"; dir = 2},/area/shuttle/abandoned)
"aaf" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/shuttle/syndicate)
"aag" = (/turf/space,/obj/machinery/gun_turret,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/shuttle/syndicate)
"aag" = (/turf/space,/obj/machinery/porta_turret/syndicate,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/shuttle/syndicate)
"aah" = (/obj/effect/landmark{name = "carpspawn"},/turf/space,/area/space)
"aai" = (/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "syndieshutters"; name = "Blast Shutters"; opacity = 0},/obj/structure/grille,/obj/structure/shuttle/window{tag = "icon-window5_mid"; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_mid"; dir = 2},/turf/simulated/shuttle/plating,/area/shuttle/syndicate)
"aaj" = (/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "syndieshutters"; name = "Blast Shutters"; opacity = 0},/obj/structure/grille,/obj/structure/shuttle/window{tag = "icon-window5_end"; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; dir = 2},/turf/simulated/shuttle/plating,/area/shuttle/syndicate)
@@ -33,7 +33,7 @@
"aaG" = (/obj/structure/stool,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/permabrig)
"aaH" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/permabrig)
"aaI" = (/obj/machinery/biogenerator,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/permabrig)
"aaJ" = (/turf/space,/obj/machinery/gun_turret,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/syndicate)
"aaJ" = (/turf/space,/obj/machinery/porta_turret/syndicate,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/syndicate)
"aaK" = (/obj/effect/spawner/window/reinforced,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "Prison Gate"; name = "Prison Blast Doors"; opacity = 0},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/security/permabrig)
"aaL" = (/obj/structure/reagent_dispensers/watertank,/obj/machinery/camera{c_tag = "Prison Garden"; dir = 4; network = list("SS13")},/obj/machinery/light{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/permabrig)
"aaM" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/security/permabrig)
@@ -8516,7 +8516,7 @@
"dhN" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate)
"dhO" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate)
"dhP" = (/turf/space,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/shuttle/syndicate)
"dhQ" = (/obj/machinery/gun_turret,/turf/simulated/shuttle/wall{dir = 4; icon_state = "wall3"},/area/shuttle/syndicate)
"dhQ" = (/obj/machinery/porta_turret/syndicate,/turf/simulated/shuttle/wall{dir = 4; icon_state = "wall3"},/area/shuttle/syndicate)
"dhR" = (/obj/structure/closet/syndicate/suits,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate)
"dhS" = (/obj/effect/landmark{name = "Syndicate-Uplink"; tag = ""},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate)
"dhT" = (/obj/structure/table,/obj/item/device/aicard,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/syndicate)

View File

@@ -436,7 +436,7 @@
"it" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/syndicate_mothership)
"iu" = (/obj/effect/decal/warning_stripes/southeast,/turf/simulated/floor/plating/airless,/area/syndicate_mothership)
"iv" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/shuttle/assault_pod)
"iw" = (/turf/space,/obj/machinery/gun_turret/assault_pod,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/shuttle/assault_pod)
"iw" = (/turf/space,/obj/machinery/porta_turret/syndicate/pod,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/shuttle/assault_pod)
"ix" = (/turf/unsimulated/floor{dir = 8; icon_state = "carpetside"},/area/wizard_station)
"iy" = (/obj/effect/landmark/start{name = "wizard"},/turf/unsimulated/floor{icon_state = "carpet"; dir = 2},/area/wizard_station)
"iz" = (/turf/unsimulated/floor{dir = 4; icon_state = "carpetside"},/area/wizard_station)
@@ -447,7 +447,7 @@
"iE" = (/turf/space,/turf/unsimulated/wall{dir = 1; icon = 'icons/turf/shuttle.dmi'; icon_state = "diagonalWall3"},/area/space)
"iF" = (/obj/machinery/door/airlock/centcom{aiControlDisabled = 1; name = "Assault Pod"; opacity = 1; req_one_access_txt = "150"},/turf/simulated/floor/plating,/area/shuttle/assault_pod)
"iG" = (/obj/effect/decal/warning_stripes/southwest,/turf/simulated/floor/plating/airless,/area/syndicate_mothership)
"iH" = (/turf/space,/obj/machinery/gun_turret/assault_pod,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/assault_pod)
"iH" = (/turf/space,/obj/machinery/porta_turret/syndicate/pod,/turf/simulated/shuttle/wall{dir = 1; icon_state = "diagonalWall3"},/area/shuttle/assault_pod)
"iI" = (/obj/effect/decal/warning_stripes/east,/turf/simulated/floor/plating/airless,/area/syndicate_mothership)
"iJ" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/assault_pod)
"iK" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/shuttle/assault_pod)
@@ -484,8 +484,8 @@
"jp" = (/turf/simulated/floor/plasteel,/area/tdome/arena_source)
"jq" = (/turf/simulated/floor/plasteel{icon_state = "green"; dir = 4},/area/tdome/arena_source)
"jr" = (/obj/structure/rack,/obj/item/clothing/under/color/green,/obj/item/clothing/shoes/brown,/obj/item/clothing/suit/armor/tdome/green,/obj/item/clothing/head/helmet/thunderdome,/obj/item/weapon/melee/energy/sword/saber/green,/turf/unsimulated/floor{icon_state = "dark"},/area/tdome/arena_source)
"js" = (/turf/space,/obj/machinery/gun_turret/assault_pod,/turf/simulated/shuttle/wall{tag = "icon-diagonalWall3"; icon_state = "diagonalWall3"; dir = 2},/area/shuttle/assault_pod)
"jt" = (/turf/space,/obj/machinery/gun_turret/assault_pod,/turf/simulated/shuttle/wall{dir = 4; icon_state = "diagonalWall3"},/area/shuttle/assault_pod)
"js" = (/turf/space,/obj/machinery/porta_turret/syndicate/pod,/turf/simulated/shuttle/wall{tag = "icon-diagonalWall3"; icon_state = "diagonalWall3"; dir = 2},/area/shuttle/assault_pod)
"jt" = (/turf/space,/obj/machinery/porta_turret/syndicate/pod,/turf/simulated/shuttle/wall{dir = 4; icon_state = "diagonalWall3"},/area/shuttle/assault_pod)
"ju" = (/obj/effect/decal/warning_stripes/northeast,/turf/simulated/floor/plating/airless,/area/syndicate_mothership)
"jv" = (/obj/effect/decal/warning_stripes/northeastcorner,/turf/simulated/floor/plating/airless,/area/syndicate_mothership)
"jw" = (/obj/machinery/door/airlock/centcom{aiControlDisabled = 1; name = "Assault Pod"; opacity = 1; req_one_access_txt = "150"},/obj/docking_port/mobile/assault_pod,/turf/simulated/floor/plating,/area/shuttle/assault_pod)

View File

@@ -620,7 +620,7 @@
"lW" = (/obj/machinery/power/apc/noalarm{dir = 0; name = "Worn-out APC"; pixel_y = -24},/turf/simulated/floor/plasteel/airless,/area/derelict/teleporter)
"lX" = (/turf/simulated/floor/plating/airless/asteroid,/area/syndicate_depot)
"lY" = (/turf/simulated/mineral,/area/syndicate_depot)
"lZ" = (/obj/structure/lattice,/obj/machinery/gun_turret/exterior,/turf/simulated/floor/plating/airless/asteroid,/area/syndicate_depot)
"lZ" = (/obj/structure/lattice,/obj/machinery/porta_turret/syndicate/exterior,/turf/simulated/floor/plating/airless/asteroid,/area/syndicate_depot)
"ma" = (/turf/simulated/mineral/random,/turf/simulated/shuttle/wall{dir = 8; icon_state = "diagonalWall3"},/area/syndicate_depot)
"mb" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/syndicate_depot)
"mc" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/turf/simulated/shuttle/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; icon_state = "window5"; name = "window"; opacity = 0},/area/syndicate_depot)
@@ -633,16 +633,16 @@
"mj" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet/red,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mk" = (/obj/structure/closet/crate{name = "foot locker"},/obj/item/ammo_box/magazine/smgm45{pixel_x = 3},/obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate{pixel_x = -3; pixel_y = -2},/obj/item/weapon/lighter/zippo/gonzofist,/obj/item/clothing/under/syndicate{pixel_x = 3; pixel_y = 3},/obj/item/clothing/suit/armor/vest/combat{pixel_x = -3; pixel_y = -3},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"ml" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 8; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5_end (WEST)"},/area/syndicate_depot)
"mm" = (/obj/machinery/gun_turret/interior,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mm" = (/obj/machinery/porta_turret/syndicate/interior,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mn" = (/obj/item/device/radio/intercom/syndicate{pixel_x = -28},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mo" = (/obj/machinery/space_heater,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mp" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 4; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5 (EAST)"},/area/syndicate_depot)
"mq" = (/turf/simulated/mineral,/turf/simulated/shuttle/wall{icon_state = "diagonalWall3"},/area/syndicate_depot)
"mr" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/turf/simulated/shuttle/wall{dir = 4; icon_state = "diagonalWall3"},/area/syndicate_depot)
"ms" = (/obj/machinery/gun_turret/interior{density = 0; desc = "Syndicate interior defense turret chambered for .45 rounds and mounted on a wall. Designed to down intruders without damaging the hull."; name = "wall mounted machine gun turret (.45)"; pixel_y = -27},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"ms" = (/obj/machinery/porta_turret/syndicate/interior{density = 0; desc = "Syndicate interior defense turret chambered for .45 rounds and mounted on a wall. Designed to down intruders without damaging the hull."; name = "wall mounted machine gun turret (.45)"; pixel_y = -27},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mt" = (/obj/structure/table,/obj/item/weapon/reagent_containers/food/snacks/syndicake,/obj/item/weapon/reagent_containers/food/drinks/cans/beer,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mu" = (/obj/machinery/gun_turret/grenade,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mv" = (/obj/machinery/gun_turret/interior{density = 0; desc = "Syndicate interior defense turret chambered for .45 rounds and mounted on a wall. Designed to down intruders without damaging the hull."; name = "wall mounted machine gun turret (.45)"; pixel_y = 27},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mu" = (/obj/machinery/porta_turret/syndicate/grenade,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mv" = (/obj/machinery/porta_turret/syndicate/interior{density = 0; desc = "Syndicate interior defense turret chambered for .45 rounds and mounted on a wall. Designed to down intruders without damaging the hull."; name = "wall mounted machine gun turret (.45)"; pixel_y = 27},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"mw" = (/turf/simulated/floor/plasteel{icon_state = "dark"},/turf/simulated/shuttle/wall{icon_state = "diagonalWall3"},/area/syndicate_depot)
"mx" = (/obj/structure/table,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/syndicate_depot)
"my" = (/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/engine,/area/syndicate_depot)

1
cfg/admin.txt Normal file
View File

@@ -0,0 +1 @@
markva role=root

View File

@@ -47,3 +47,8 @@
#define ANTAG_HUD_CHANGELING 15
#define ANTAG_HUD_VAMPIRE 16
#define ANTAG_HUD_ABDUCTOR 17 //For Fox
// Notification action types
#define NOTIFY_JUMP "jump"
#define NOTIFY_ATTACK "attack"
#define NOTIFY_FOLLOW "orbit"

View File

@@ -287,3 +287,19 @@
#define SHELTER_DEPLOY_BAD_TURFS "bad turfs"
#define SHELTER_DEPLOY_BAD_AREA "bad area"
#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects"
// Medal names
#define BOSS_KILL_MEDAL "Killer"
#define ALL_KILL_MEDAL "Exterminator" //Killing all of x type
// Score names
#define LEGION_SCORE "Legion Killed"
#define COLOSSUS_SCORE "Colossus Killed"
#define BUBBLEGUM_SCORE "Bubblegum Killed"
#define DRAKE_SCORE "Drakes Killed"
#define BIRD_SCORE "Hierophants Killed"
#define BOSS_SCORE "Bosses Killed"
#define TENDRIL_CLEAR_SCORE "Tendrils Killed"
//Timing controller
#define GLOBAL_PROC "some_magic_bullshit"

View File

@@ -72,6 +72,14 @@
return 0
return L[A.type]
//returns a new list with only atoms that are in typecache L
/proc/typecache_filter_list(list/atoms, list/typecache)
. = list()
for (var/thing in atoms)
var/atom/A = thing
if (typecache[A.type])
. += A
//Like typesof() or subtypesof(), but returns a typecache instead of a list
/proc/typecacheof(path, ignore_root_path)
if(ispath(path))

View File

@@ -1,4 +1,3 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/*
@@ -550,13 +549,19 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
/proc/can_see(var/atom/source, var/atom/target, var/length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate.
var/turf/current = get_turf(source)
var/turf/target_turf = get_turf(target)
var/steps = 0
var/steps = 1
if(current != target_turf)
current = get_step_towards(current, target_turf)
while(current != target_turf)
if(steps > length) return 0
if(current.opacity) return 0
for(var/atom/A in current)
if(A.opacity) return 0
if(steps > length)
return 0
if(current.opacity)
return 0
for(var/thing in current)
var/atom/A = thing
if(A.opacity)
return 0
current = get_step_towards(current, target_turf)
steps++
@@ -1767,3 +1772,46 @@ var/global/list/g_fancy_list_of_types = null
sleep(world.tick_lag*4)
//you might be thinking of adding more steps to this, or making it use a loop and a counter var
// not worth it.
/proc/getpois(mobs_only=0,skip_mindless=0)
var/list/mobs = sortmobs()
var/list/names = list()
var/list/pois = list()
var/list/namecounts = list()
for(var/mob/M in mobs)
if(skip_mindless && (!M.mind && !M.ckey))
if(!isbot(M) && !istype(M, /mob/camera/))
continue
if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins
continue
var/name = M.name
if (name in names)
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
if (M.real_name && M.real_name != M.name)
name += " \[[M.real_name]\]"
if (M.stat == 2)
if(istype(M, /mob/dead/observer/))
name += " \[ghost\]"
else
name += " \[dead\]"
pois[name] = M
if(!mobs_only)
for(var/atom/A in poi_list)
if(!A || !A.loc)
continue
var/name = A.name
if (names.Find(name))
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
pois[name] = A
return pois

View File

@@ -36,3 +36,8 @@ var/eventchance = 10 //% per 5 mins
var/event = 0
var/hadevent = 0
var/blobevent = 0
//Medals hub related variables
var/global/medal_hub = null
var/global/medal_pass = " "
var/global/medals_enabled = TRUE //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls.

View File

@@ -19,3 +19,5 @@ var/list/restricted_camera_networks = list( //Those networks can only be accesse
)
var/list/mineral_turfs = list()
var/list/ruin_landmarks = list()

View File

@@ -34,3 +34,5 @@ var/global/list/tracked_implants = list() //list of all current implants that
var/global/list/pinpointer_list = list() //list of all pinpointers. Used to change stuff they are pointing to all at once.
var/global/list/abductor_equipment = list() //list of all abductor equipment
var/global/list/global_intercoms = list() //list of all intercomms, across all z-levels
var/global/list/poi_list = list() //list of points of interest for observe/follow

View File

@@ -51,5 +51,5 @@ var/list/datum/map_template/map_templates = list()
var/list/datum/map_template/ruins_templates = list()
var/list/datum/map_template/space_ruins_templates = list()
//var/list/datum/map_template/lava_ruins_templates = list()
var/list/datum/map_template/lava_ruins_templates = list()
var/list/datum/map_template/shelter_templates = list()

View File

@@ -334,25 +334,28 @@ so as to remain in compliance with the most up-to-date laws."
var/mob/dead/observer/G = usr
G.reenter_corpse()
/obj/screen/alert/notify_jump
/obj/screen/alert/notify_action
name = "Body created"
desc = "A body was created. You can enter it."
icon_state = "template"
timeout = 300
var/atom/jump_target = null
var/attack_not_jump = null
var/atom/target = null
var/action = NOTIFY_JUMP
/obj/screen/alert/notify_jump/Click()
/obj/screen/alert/notify_action/Click()
if(!usr || !usr.client) return
if(!jump_target) return
if(!target) return
var/mob/dead/observer/G = usr
if(!istype(G)) return
if(attack_not_jump)
jump_target.attack_ghost(G)
else
var/turf/T = get_turf(jump_target)
switch(action)
if(NOTIFY_ATTACK)
target.attack_ghost(G)
if(NOTIFY_JUMP)
var/turf/T = get_turf(target)
if(T && isturf(T))
G.loc = T
if(NOTIFY_FOLLOW)
G.ManualFollow(target)
//OBJECT-BASED

View File

@@ -548,6 +548,12 @@
if("round_abandon_penalty_period")
config.round_abandon_penalty_period = MinutesToTicks(text2num(value))
if("medal_hub_address")
global.medal_hub = value
if("medal_hub_password")
global.medal_pass = value
else
diary << "Unknown setting in configuration: '[name]'"

View File

@@ -1,5 +1,11 @@
// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
/datum
var/var_edited = 0 //Warrenty void if seal is broken
/datum/proc/on_varedit(modified_var) //called whenever a var is edited
var_edited = 1
/client/proc/debug_variables(datum/D in world)
set category = "Debug"
set name = "View Variables"

View File

@@ -55,6 +55,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/action_icon_state = "spell_default"
var/action_background_icon_state = "bg_spell"
var/sound = null //The sound the spell makes when it is cast
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0, mob/living/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
@@ -130,6 +132,9 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
if("emote")
user.visible_message(invocation, invocation_emote_self) //same style as in mob/living/emote.dm
/obj/effect/proc_holder/spell/proc/playMagSound()
playsound(get_turf(usr), sound,50,1)
/obj/effect/proc_holder/spell/New()
..()
action = new(src)
@@ -166,6 +171,10 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
spawn(0)
if(charge_type == "recharge" && recharge)
start_recharge()
if(sound)
playMagSound()
if(prob(critfailchance))
critfail(targets)
else

View File

@@ -4,6 +4,10 @@
var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list
var/invocation_area = 1 //if the invocation appends the selected area
var/sound1 = "sound/weapons/ZapBang.ogg"
var/sound2 = "sound/weapons/ZapBang.ogg"
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1)
var/thearea = before_cast(targets)
if(!thearea || !cast_check(1))
@@ -32,7 +36,8 @@
return thearea
/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea)
/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea,mob/living/user = usr)
playsound(get_turf(user), sound1, 50,1)
for(var/mob/living/target in targets)
var/list/L = list()
for(var/turf/T in get_area_turfs(thearea.type))
@@ -64,7 +69,8 @@
break
if(!success)
target.loc = pick(L)
target.forceMove(pick(L))
playsound(get_turf(user), sound2, 50,1)
return

View File

@@ -14,8 +14,10 @@
//should have format of list("emagged" = 1,"name" = "Wizard's Justicebot"), for example
var/delay = 1//Go Go Gadget Inheritance
/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets)
var/cast_sound = 'sound/items/welder.ogg'
/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets,mob/living/user = usr)
playsound(get_turf(user), cast_sound, 50,1)
for(var/turf/T in targets)
if(T.density && !summon_ignore_density)
targets -= T
@@ -42,6 +44,7 @@
for(var/varName in newVars)
if(varName in summoned_object.vars)
summoned_object.vars[varName] = newVars[varName]
summoned_object.admin_spawned = TRUE
if(summon_lifespan)
spawn(summon_lifespan)

View File

@@ -14,6 +14,7 @@
selection_type = "range"
action_icon_state = "barn"
sound = "sound/magic/HorseHead_curse.ogg"
/obj/effect/proc_holder/spell/targeted/horsemask/cast(list/targets, mob/user = usr)
if(!targets.len)

View File

@@ -11,6 +11,7 @@
cooldown_min = 20 //20 deciseconds reduction per rank
action_icon_state = "knock"
sound = "sound/magic/Knock.ogg"
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets)
for(var/turf/T in targets)

View File

@@ -14,6 +14,7 @@
var/ready = 0
var/image/halo = null
action_icon_state = "lightning"
var/sound/Snd // so far only way i can think of to stop a sound, thank MSO for the idea.
/obj/effect/proc_holder/spell/targeted/lightning/lightnian
clothes_req = 0
@@ -31,8 +32,10 @@
/obj/effect/proc_holder/spell/targeted/lightning/proc/StartChargeup(mob/user = usr)
ready = 1
to_chat(user, "<span class='notice'>You start gathering the power.</span>")
Snd = new/sound('sound/magic/lightning_chargeup.ogg',channel = 7)
halo = image("icon"='icons/effects/effects.dmi',"icon_state" ="electricity","layer" = EFFECTS_LAYER)
user.overlays.Add(halo)
playsound(get_turf(user), Snd, 50, 0)
start_time = world.time
if(do_mob(user,user,100,uninterruptible=1))
if(ready)
@@ -59,11 +62,14 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
/obj/effect/proc_holder/spell/targeted/lightning/cast(list/targets, mob/user = usr)
ready = 0
var/mob/living/carbon/target = targets[1]
Snd=sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck?
playsound(get_turf(user),Snd,50,0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way.
if(get_dist(user,target)>range)
to_chat(user, "<span class='notice'>They are too far away!</span>")
Reset(user)
return
playsound(get_turf(user), 'sound/magic/lightningbolt.ogg', 50, 1)
user.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
var/energy = min(world.time - start_time,100)
@@ -75,10 +81,10 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
var/mob/living/carbon/current = target
if(bounces < 1)
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
playsound(get_turf(current), 'sound/machines/defib_zap.ogg', 50, 1, -1)
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
else
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
playsound(get_turf(current), 'sound/machines/defib_zap.ogg', 50, 1, -1)
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
var/list/possible_targets = new
for(var/mob/living/M in view_or_range(range,target,"view"))
if(user == M || target == M && los_check(current,M)) // || origin == M ? Not sure double shockings is good or not

View File

@@ -10,6 +10,7 @@
charge_max = 300
clothes_req = 0
range = 0
cast_sound = null
action_icon_state = "mime"
action_background_icon_state = "bg_mime"

View File

@@ -102,8 +102,10 @@
if(butterfingers)
item_to_retrive.loc = user.loc
item_to_retrive.loc.visible_message("<span class='caution'>The [item_to_retrive.name] suddenly appears!</span>")
playsound(get_turf(user),"sound/magic/SummonItems_generic.ogg",50,1)
else
item_to_retrive.loc.visible_message("<span class='caution'>The [item_to_retrive.name] suddenly appears in [user]'s hand!</span>")
playsound(get_turf(user),"sound/magic/SummonItems_generic.ogg",50,1)
if(message)
to_chat(user, message)

View File

@@ -8,7 +8,11 @@
var/include_space = 0 //whether it includes space tiles in possible teleport locations
var/include_dense = 0 //whether it includes dense tiles in possible teleport locations
/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets)
var/sound1 = "sound/weapons/ZapBang.ogg"
var/sound2 = "sound/weapons/ZapBang.ogg"
/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets,mob/living/user = usr)
playsound(get_turf(user), sound1, 50,1)
for(var/mob/living/target in targets)
var/list/turfs = new/list()
for(var/turf/T in range(target,outer_tele_radius))
@@ -31,4 +35,5 @@
if(!picked || !isturf(picked))
return
target.loc = picked
target.forceMove(picked)
playsound(get_turf(user), sound2, 50,1)

View File

@@ -26,8 +26,11 @@
action_icon_state = "magicm"
sound = "sound/magic/MAGIC_MISSILE.ogg"
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
amt_weakened = 3
sound = "sound/magic/MM_Hit.ogg"
/obj/effect/proc_holder/spell/noclothes
name = "No Clothes"
@@ -52,6 +55,7 @@
cooldown_min = 300 //25 deciseconds reduction per rank
action_icon_state = "mutate"
sound = "sound/magic/Mutate.ogg"
/obj/effect/proc_holder/spell/targeted/genetic/mutate/cast(list/targets)
for(var/mob/living/target in targets)
@@ -94,6 +98,8 @@
emp_heavy = 6
emp_light = 10
sound = "sound/magic/Disable_Tech.ogg"
/obj/effect/proc_holder/spell/targeted/turf_teleport/blink
name = "Blink"
desc = "This spell randomly teleports you a short distance."
@@ -118,6 +124,9 @@
action_icon_state = "blink"
sound1 = "sound/magic/blink.ogg"
sound2 = "sound/magic/blink.ogg"
/obj/effect/proc_holder/spell/targeted/area_teleport/teleport
name = "Teleport"
desc = "This spell teleports you to a type of area of your selection."
@@ -136,6 +145,9 @@
action_icon_state = "spell_teleport"
sound1="sound/magic/Teleport_diss.ogg"
sound2="sound/magic/Teleport_app.ogg"
/obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall
name = "Forcewall"
desc = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb."
@@ -152,6 +164,7 @@
summon_lifespan = 300
action_icon_state = "shield"
cast_sound = "sound/magic/ForceWall.ogg"
/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
name = "Stop Time"
@@ -180,6 +193,7 @@
summon_type = list(/mob/living/simple_animal/hostile/carp)
cast_sound = "sound/magic/Summon_Karp.ogg"
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct
name = "Artificer"
@@ -195,6 +209,7 @@
summon_type = list(/obj/structure/constructshell)
action_icon_state = "artificer"
cast_sound = "sound/magic/SummonItems_generic.ogg"
/obj/effect/proc_holder/spell/aoe_turf/conjure/creature
name = "Summon Creature Swarm"
@@ -209,6 +224,7 @@
range = 3
summon_type = list(/mob/living/simple_animal/hostile/creature)
cast_sound = "sound/magic/SummonItems_generic.ogg"
/obj/effect/proc_holder/spell/targeted/trigger/blind
name = "Blind"
@@ -229,10 +245,12 @@
/obj/effect/proc_holder/spell/targeted/inflict_handler/blind
amt_eye_blind = 10
amt_eye_blurry = 20
sound="sound/magic/Blind.ogg"
/obj/effect/proc_holder/spell/targeted/genetic/blind
disabilities = BLIND
duration = 300
sound="sound/magic/Blind.ogg"
/obj/effect/proc_holder/spell/dumbfire/fireball
name = "Fireball"
@@ -254,6 +272,7 @@
proj_step_delay = 1
action_icon_state = "fireball"
sound = "sound/magic/Fireball.ogg"
/obj/effect/proc_holder/spell/turf/fireball/cast(var/turf/T)
explosion(T, -1, 0, 2, 3, 0, flame_range = 2)
@@ -282,12 +301,14 @@
var/maxthrow = 5
action_icon_state = "repulse"
sound = 'sound/magic/Repulse.ogg'
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets)
var/mob/user = usr
var/list/thrownatoms = list()
var/atom/throwtarget
var/distfromcaster
playMagSound()
for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously.
for(var/atom/movable/AM in T)
thrownatoms += AM
@@ -314,3 +335,24 @@
M.Weaken(2)
to_chat(M, "<span class='userdanger'>You're thrown back by a mystical force!</span>")
spawn(0) AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
/obj/effect/proc_holder/spell/targeted/sacred_flame
name = "Sacred Flame"
desc = "Makes everyone around you more flammable, and lights yourself on fire."
charge_max = 60
clothes_req = 0
invocation = "FI'RAN DADISKO"
invocation_type = "shout"
max_targets = 0
range = 6
include_user = 1
selection_type = "view"
action_icon_state = "sacredflame"
sound = "sound/magic/Fireball.ogg"
/obj/effect/proc_holder/spell/targeted/sacred_flame/cast(list/targets, mob/user = usr)
for(var/mob/living/L in targets)
L.adjust_fire_stacks(20)
if(isliving(user))
var/mob/living/U = user
U.IgniteMob()

View File

@@ -37,6 +37,8 @@
var/allow_spin = 1 //Set this to 1 for a _target_ that is being thrown at; if an atom has this set to 1 then atoms thrown AT it will not spin; currently used for the singularity. -Fox
var/admin_spawned = 0 //was this spawned by an admin? used for stat tracking stuff.
/atom/proc/onCentcom()
var/turf/T = get_turf(src)
if(!T)
@@ -455,3 +457,7 @@
/atom/proc/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
return
/atom/on_varedit(modified_var)
if(!Debug2)
admin_spawned = TRUE

View File

@@ -213,6 +213,10 @@
if(A.density && !A.throwpass) // **TODO: Better behaviour for windows which are dense, but shouldn't always stop movement
src.throw_impact(A,speed)
/atom/movable/proc/throw_at_fast(atom/target, range, speed, thrower, no_spin)
set waitfor = 0
throw_at(target, range, speed, thrower, no_spin)
/atom/movable/proc/throw_at(atom/target, range, speed, thrower, no_spin)
if(!target || !src || (flags & NODROP))
return 0

View File

@@ -14,6 +14,7 @@
/obj/effect/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, offspring)
blob_cores += src
processing_objects.Add(src)
poi_list |= src
adjustcolors(color) //so it atleast appears
if(!overmind)
create_overmind(new_overmind)
@@ -41,6 +42,7 @@
overmind.blob_core = null
overmind = null
processing_objects.Remove(src)
poi_list.Remove(src)
return ..()
/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)

View File

@@ -73,9 +73,11 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
for(var/mob/living/silicon/ai/AI in player_list)
AI.client.images += blood
cult_viewpoints += src
poi_list |= src
/obj/effect/rune/Destroy()
cult_viewpoints -= src
poi_list.Remove(src)
return ..()
/obj/effect/rune/examine(mob/user)

View File

@@ -6,7 +6,7 @@
icon_state = "swarmer_unactivated"
/obj/item/unactivated_swarmer/New()
notify_ghosts("An unactivated swarmer has been created in [get_area(src)]!", enter_link = "<a href=?src=[UID()];ghostjoin=1>(Click to enter)</a>", source = src, attack_not_jump = 1)
notify_ghosts("An unactivated swarmer has been created in [get_area(src)]!", enter_link = "<a href=?src=[UID()];ghostjoin=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK)
..()
/obj/item/unactivated_swarmer/Topic(href, href_list)
@@ -63,7 +63,7 @@
mob_size = MOB_SIZE_TINY
ventcrawler = 2
ranged = 1
ranged_cooldown_cap = 1
ranged_cooldown_time = 20
universal_speak = 0
universal_understand = 0
projectilesound = 'sound/weapons/taser2.ogg'

View File

@@ -496,7 +496,7 @@
melee_damage_upper = 10
damage_transfer = 0.9
projectiletype = /obj/item/projectile/guardian
ranged_cooldown_cap = 1
ranged_cooldown_time = 1
projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
ranged = 1
rapid = 1

View File

@@ -307,7 +307,7 @@ proc/issyndicate(mob/living/M as mob)
/datum/game_mode/nuclear/declare_completion()
var/disk_rescued = 1
for(var/obj/item/weapon/disk/nuclear/D in world)
for(var/obj/item/weapon/disk/nuclear/D in poi_list)
if(!D.onCentcom())
disk_rescued = 0
break

View File

@@ -32,10 +32,12 @@ var/bomb_set
r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn.
wires = new/datum/wires/nuclearbomb(src)
previous_level = get_security_level()
poi_list |= src
/obj/machinery/nuclearbomb/Destroy()
qdel(wires)
wires = null
poi_list.Remove(src)
return ..()
/obj/machinery/nuclearbomb/process()

View File

@@ -88,6 +88,8 @@
new /obj/item/weapon/gun/projectile/revolver/grenadelauncher(get_turf(H))
if("medibeam")
new /obj/item/weapon/gun/medbeam(get_turf(H))
playsound(get_turf(H),'sound/magic/Summon_guns.ogg', 50, 1)
else
switch(randomizemagic)
if("fireball")
@@ -155,3 +157,5 @@
if("necromantic")
new /obj/item/device/necromantic_stone(get_turf(H))
to_chat(H, "<span class='notice'>You suddenly feel lucky.</span>")
playsound(get_turf(H),'sound/magic/Summon_Magic.ogg', 50, 1)

View File

@@ -854,3 +854,9 @@
spellname = "disintegrate"
icon_state ="bookfireball"
desc = "This book feels like it will rip stuff apart."
/obj/item/weapon/spellbook/oneuse/sacredflame
spell = /obj/effect/proc_holder/spell/targeted/sacred_flame
spellname = "sacred flame"
icon_state ="booksacredflame"
desc = "Become one with the flames that burn within... and invite others to do so as well."

View File

@@ -57,6 +57,12 @@
var/screen = 0 // Screen 0: main control, screen 1: access levels
var/one_access = 0 // Determines if access control is set to req_one_access or req_access
var/faction = "neutral"
var/emp_vulnerable = 1 // Can be empd
var/scan_range = 7
var/always_up = 0 //Will stay active
var/has_cover = 1 //Hides the cover
/obj/machinery/porta_turret/centcom
enabled = 0
ailock = 1
@@ -460,7 +466,7 @@ var/list/turret_icons
take_damage(Proj.damage)
/obj/machinery/porta_turret/emp_act(severity)
if(enabled)
if(enabled && emp_vulnerable)
//if the turret is on, the EMP no matter how severe disables the turret for a while
//and scrambles its settings, with a slight chance of having an emag effect
check_arrest = prob(50)
@@ -502,11 +508,13 @@ var/list/turret_icons
set background = BACKGROUND_ENABLED
if(stat & (NOPOWER|BROKEN))
if(!always_up)
//if the turret has no power or is broken, make the turret pop down if it hasn't already
popDown()
return
if(!enabled)
if(!always_up)
//if the turret is off, make it pop down
popDown()
return
@@ -514,23 +522,29 @@ var/list/turret_icons
var/list/targets = list() //list of primary targets
var/list/secondarytargets = list() //targets that are least important
for(var/obj/mecha/ME in view(7,src))
for(var/obj/mecha/ME in view(scan_range,src))
assess_and_assign(ME.occupant, targets, secondarytargets)
for(var/obj/spacepod/SP in view(7,src))
for(var/obj/spacepod/SP in view(scan_range,src))
assess_and_assign(SP.pilot, targets, secondarytargets)
for(var/obj/vehicle/T in view(7,src))
for(var/obj/vehicle/T in view(scan_range,src))
assess_and_assign(T.buckled_mob, targets, secondarytargets)
for(var/mob/living/C in view(7,src)) //loops through all living lifeforms in view
for(var/mob/living/C in view(scan_range,src)) //loops through all living lifeforms in view
assess_and_assign(C, targets, secondarytargets)
if(!tryToShootAt(targets))
if(!tryToShootAt(secondarytargets)) // if no valid targets, go for secondary targets
if(!always_up)
spawn()
popDown() // no valid targets, close the cover
/obj/machinery/porta_turret/proc/in_faction(mob/living/target)
if(!(faction in target.faction))
return 0
return 1
/obj/machinery/porta_turret/proc/assess_and_assign(var/mob/living/L, var/list/targets, var/list/secondarytargets)
switch(assess_living(L))
if(TURRET_PRIORITY_TARGET)
@@ -557,12 +571,15 @@ var/list/turret_icons
if(L.stat && !emagged) //if the perp is dead/dying, no need to bother really
return TURRET_NOT_TARGET //move onto next potential victim!
if(get_dist(src, L) > 7) //if it's too far away, why bother?
if(get_dist(src, L) > scan_range) //if it's too far away, why bother?
return TURRET_NOT_TARGET
if(emagged) // If emagged not even the dead get a rest
return L.stat ? TURRET_SECONDARY_TARGET : TURRET_PRIORITY_TARGET
if(in_faction(L))
return TURRET_NOT_TARGET
if(lethal && locate(/mob/living/silicon/ai) in get_turf(L)) //don't accidentally kill the AI!
return TURRET_NOT_TARGET
@@ -648,8 +665,8 @@ var/list/turret_icons
return ..()
/obj/machinery/porta_turret/proc/set_raised_raising(var/raised, var/raising)
src.raised = raised
src.raising = raising
raised = raised
raising = raising
density = raised || raising
/obj/machinery/porta_turret/proc/target(var/mob/living/target)
@@ -657,6 +674,7 @@ var/list/turret_icons
return
if(target)
last_target = target
if(has_cover)
spawn()
popUp() //pop the turret up if it's not already up.
dir = get_dir(src, target) //even if you can't shoot, follow the target
@@ -666,7 +684,7 @@ var/list/turret_icons
return
/obj/machinery/porta_turret/proc/shootAt(var/mob/living/target)
if(!raised) //the turret has to be raised in order to fire - makes sense, right?
if(!raised && has_cover) //the turret has to be raised in order to fire - makes sense, right?
return
//any emagged turrets will shoot extremely fast! This not only is deadly, but drains a lot power!
if(!emagged) //if it hasn't been emagged, it has to obey a cooldown rate
@@ -718,9 +736,9 @@ var/list/turret_icons
/obj/machinery/porta_turret/proc/setState(var/datum/turret_checks/TC)
if(controllock)
return
src.enabled = TC.enabled
src.lethal = TC.lethal
src.iconholder = TC.lethal
enabled = TC.enabled
lethal = TC.lethal
iconholder = TC.lethal
check_synth = TC.check_synth
check_access = TC.check_access
@@ -730,7 +748,7 @@ var/list/turret_icons
check_anomalies = TC.check_anomalies
ailock = TC.ailock
src.power_change()
power_change()
/*
Portable turret constructions
@@ -943,3 +961,74 @@ var/list/turret_icons
/atom/movable/porta_turret_cover
icon = 'icons/obj/turrets.dmi'
// Syndicate turrets
/obj/machinery/porta_turret/syndicate
installation = null
always_up = 1
use_power = 0
has_cover = 0
scan_range = 9
projectile = /obj/item/projectile/bullet
eprojectile = /obj/item/projectile/bullet
shot_sound = 'sound/weapons/Gunshot.ogg'
eshot_sound = 'sound/weapons/Gunshot.ogg'
icon_state = "syndieturret0"
var/icon_state_initial = "syndieturret0"
var/icon_state_active = "syndieturret1"
var/icon_state_destroyed = "syndieturret2"
faction = "syndicate"
emp_vulnerable = 0
raised = 1
/obj/machinery/porta_turret/syndicate/New()
..()
if(req_one_access && req_one_access.len)
req_one_access.Cut()
req_access = list(access_syndicate)
one_access = 0
/obj/machinery/porta_turret/syndicate/update_icon()
if(stat & BROKEN)
icon_state = icon_state_destroyed
else if(enabled)
icon_state = icon_state_active
else
icon_state = icon_state_initial
/obj/machinery/porta_turret/syndicate/setup()
return
/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp)
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/pod
health = 40
projectile = /obj/item/projectile/bullet/weakbullet3
eprojectile = /obj/item/projectile/bullet/weakbullet3
/obj/machinery/porta_turret/syndicate/interior
name = "machine gun turret (.45)"
desc = "Syndicate interior defense turret chambered for .45 rounds. Designed to down intruders without damaging the hull."
projectile = /obj/item/projectile/bullet/midbullet
eprojectile = /obj/item/projectile/bullet/midbullet
/obj/machinery/porta_turret/syndicate/exterior
name = "machine gun turret (7.62)"
desc = "Syndicate exterior defense turret chambered for 7.62 rounds. Designed to down intruders with heavy calliber bullets."
projectile = /obj/item/projectile/bullet
eprojectile = /obj/item/projectile/bullet/midbullet
/obj/machinery/porta_turret/syndicate/grenade
name = "mounted grenade launcher (40mm)"
desc = "Syndicate 40mm grenade launcher defense turret. If you've had this much time to look at it, you're probably already dead."
projectile = /obj/item/projectile/bullet/a40mm
eprojectile = /obj/item/projectile/bullet/midbullet
/obj/machinery/porta_turret/syndicate/assault_pod
name = "machine gun turret (4.6x30mm)"
desc = "Syndicate exterior defense turret chambered for 4.6x30mm rounds. Designed to be fitted to assault pods, it uses low calliber bullets to save space."
health = 100
projectile = /obj/item/projectile/bullet/weakbullet3
eprojectile = /obj/item/projectile/bullet/midbullet

View File

@@ -257,6 +257,7 @@
var/obj/machinery/syndicatebomb/B = src.loc
for(var/i = 0; i < amt_summon; i++)
var/atom/movable/X = new summon_path
X.admin_spawned = TRUE
X.loc = get_turf(src)
if(prob(50))
for(var/j = 1, j <= rand(1, 3), j++)

View File

@@ -1,580 +0,0 @@
/area/turret_protected
name = "Turret Protected Area"
var/list/turretTargets = list()
/area/turret_protected/proc/subjectDied(target)
if( isliving(target) )
if( !issilicon(target) )
var/mob/living/L = target
if( L.stat )
if( L in turretTargets )
src.Exited(L)
/area/turret_protected/Entered(O)
..()
if( iscarbon(O) )
turretTargets |= O
else if( istype(O, /obj/mecha) )
var/obj/mecha/Mech = O
if( Mech.occupant )
turretTargets |= Mech
else if( istype(O, /obj/spacepod) )
var/obj/spacepod/Pod = O
if( Pod.pilot )
turretTargets |= Pod
else if(istype(O,/mob/living/simple_animal))
turretTargets |= O
return 1
/area/turret_protected/Exited(O)
if( ismob(O) && !issilicon(O) )
turretTargets -= O
else if( istype(O, /obj/mecha) )
turretTargets -= O
else if( istype(O, /obj/spacepod) )
turretTargets -= O
..()
return 1
/obj/machinery/turret
name = "turret"
icon = 'icons/obj/turrets.dmi'
icon_state = "grey_target_prism"
var/raised = 0
var/enabled = 1
anchored = 1
layer = 3
invisibility = INVISIBILITY_LEVEL_TWO
density = 1
var/lasers = 0
var/lasertype = 1
// 1 = lasers
// 2 = cannons
// 3 = pulse
// 4 = change (HONK)
// 5 = bluetag
// 6 = redtag
var/health = 80
var/obj/machinery/turretcover/cover = null
var/popping = 0
var/wasvalid = 0
var/lastfired = 0
var/shot_delay = 30 //3 seconds between shots
var/datum/effect/system/spark_spread/spark_system
use_power = 1
idle_power_usage = 50
active_power_usage = 300
// var/list/targets
var/atom/movable/cur_target
var/targeting_active = 0
var/area/turret_protected/protected_area
/obj/machinery/turret/New()
spark_system = new /datum/effect/system/spark_spread
spark_system.set_up(5, 0, src)
spark_system.attach(src)
// targets = new
..()
return
/obj/machinery/turretcover
name = "pop-up turret cover"
icon = 'icons/obj/turrets.dmi'
icon_state = "turretCover"
anchored = 1
layer = 3.5
density = 0
var/obj/machinery/turret/host = null
/obj/machinery/turret/proc/isPopping()
return (popping!=0)
/obj/machinery/turret/power_change()
if(stat & BROKEN)
icon_state = "grey_target_prism"
else
if( powered() )
if(src.enabled)
if(src.lasers)
icon_state = "orange_target_prism"
else
icon_state = "target_prism"
else
icon_state = "grey_target_prism"
stat &= ~NOPOWER
else
spawn(rand(0, 15))
src.icon_state = "grey_target_prism"
stat |= NOPOWER
/obj/machinery/turret/proc/setState(var/enabled, var/lethal)
src.enabled = enabled
src.lasers = lethal
src.power_change()
/obj/machinery/turret/proc/get_protected_area()
var/area/turret_protected/TP = get_area(src)
if(istype(TP))
return TP
return
/obj/machinery/turret/proc/check_target(var/atom/movable/T as mob|obj)
if( T && T in protected_area.turretTargets )
var/area/area_T = get_area(T)
if( !area_T || (area_T.type != protected_area.type) )
protected_area.Exited(T)
return 0 //If the guy is somehow not in the turret's area (teleportation), get them out the damn list. --NEO
if( iscarbon(T) )
var/mob/living/carbon/MC = T
if( !MC.stat )
if( !MC.lying || lasers )
return 1
else if( istype(T, /obj/mecha) )
var/obj/mecha/ME = T
if( ME.occupant )
return 1
else if( istype(T, /obj/spacepod) )
var/obj/spacepod/SP = T
if( SP.pilot )
return 1
else if(istype(T,/mob/living/simple_animal))
var/mob/living/simple_animal/A = T
if( !A.stat )
if(lasers)
return 1
return 0
/obj/machinery/turret/proc/get_new_target()
var/list/new_targets = new
var/new_target
for(var/mob/living/carbon/M in protected_area.turretTargets)
if(!M.stat)
if(!M.lying || lasers)
new_targets += M
for(var/obj/mecha/M in protected_area.turretTargets)
if(M.occupant)
new_targets += M
for(var/obj/spacepod/M in protected_area.turretTargets)
if(M.pilot)
new_targets += M.pilot
for(var/mob/living/simple_animal/M in protected_area.turretTargets)
if(!M.stat)
new_targets += M
if(new_targets.len)
new_target = pick(new_targets)
return new_target
/obj/machinery/turret/process()
if(stat & (NOPOWER|BROKEN))
return
if(src.cover==null)
src.cover = new /obj/machinery/turretcover(src.loc)
src.cover.host = src
protected_area = get_protected_area()
if(!enabled || !protected_area || protected_area.turretTargets.len<=0)
if(!isDown() && !isPopping())
popDown()
return
if(!check_target(cur_target)) //if current target fails target check
cur_target = get_new_target() //get new target
if(cur_target) //if it's found, proceed
// to_chat(world, "[cur_target]")
if(!isPopping())
if(isDown())
popUp()
use_power = 2
else
spawn()
if(!targeting_active)
targeting_active = 1
target()
targeting_active = 0
if(prob(15))
if(prob(50))
playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1)
else
playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1)
else if(!isPopping())//else, pop down
if(!isDown())
popDown()
use_power = 1
return
/obj/machinery/turret/proc/target()
while(src && enabled && !stat && check_target(cur_target))
src.dir = get_dir(src, cur_target)
shootAt(cur_target)
sleep(shot_delay)
return
/obj/machinery/turret/proc/shootAt(var/atom/movable/target)
var/turf/T = get_turf(src)
var/turf/U = get_turf(target)
if(!T || !U)
return
var/obj/item/projectile/A
if(src.lasers)
switch(lasertype)
if(1)
A = new /obj/item/projectile/beam(loc)
if(2)
A = new /obj/item/projectile/beam/laser/heavylaser(loc)
if(3)
A = new /obj/item/projectile/beam/pulse(loc)
if(4)
A = new /obj/item/projectile/magic/change(loc)
if(5)
A = new /obj/item/projectile/beam/lasertag/bluetag(loc)
if(6)
A = new /obj/item/projectile/beam/lasertag/redtag(loc)
use_power(500)
else
A = new /obj/item/projectile/energy/electrode( loc )
use_power(200)
if(src.lasers)
playsound(get_turf(src), 'sound/weapons/Laser.ogg', 60, 1)
else
playsound(get_turf(src), 'sound/weapons/Taser.ogg', 60, 1)
A.original = target
A.current = T
A.yo = U.y - T.y
A.xo = U.x - T.x
A.fire()
return A
/obj/machinery/turret/proc/isDown()
return (invisibility!=0)
/obj/machinery/turret/proc/popUp()
if((!isPopping()) || src.popping==-1)
invisibility = 0
popping = 1
playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
if(src.cover!=null)
flick("popup", src.cover)
src.cover.icon_state = "openTurretCover"
spawn(10)
if(popping==1) popping = 0
/obj/machinery/turret/proc/popDown()
if((!isPopping()) || src.popping==1)
popping = -1
playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
if(src.cover!=null)
flick("popdown", src.cover)
src.cover.icon_state = "turretCover"
spawn(10)
if(popping==-1)
invisibility = INVISIBILITY_LEVEL_TWO
popping = 0
/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
src.health -= Proj.damage
..()
if(prob(45) && Proj.damage > 0) src.spark_system.start()
qdel(Proj)
if(src.health <= 0)
src.die()
return
/obj/machinery/turret/attackby(obj/item/weapon/W, mob/user)//I can't believe no one added this before/N
..()
user.changeNext_move(CLICK_CD_MELEE)
playsound(src.loc, 'sound/weapons/smash.ogg', 60, 1)
src.spark_system.start()
src.health -= W.force * 0.5
if(src.health <= 0)
src.die()
return
/obj/machinery/turret/emp_act(severity)
switch(severity)
if(1)
enabled = 0
lasers = 0
power_change()
..()
/obj/machinery/turret/ex_act(severity)
if(severity < 3)
src.die()
/obj/machinery/turret/proc/die()
src.health = 0
src.density = 0
src.stat |= BROKEN
src.icon_state = "destroyed_target_prism"
if(cover!=null)
qdel(cover)
sleep(3)
flick("explosion", src)
spawn(13)
qdel(src)
/obj/machinery/turret/attack_animal(mob/living/simple_animal/M as mob)
M.changeNext_move(CLICK_CD_MELEE)
M.do_attack_animation(src)
if(M.melee_damage_upper == 0) return
if(!(stat & BROKEN))
visible_message("<span class='userdanger'>[M] [M.attacktext] [src]!</span>")
add_logs(src, M, "attacked", admin=0)
//src.attack_log += text("\[[time_stamp()]\] <font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
src.health -= M.melee_damage_upper
if(src.health <= 0)
src.die()
else
to_chat(M, "<span class='danger'>That object is useless to you.</span>")
return
/obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob)
M.changeNext_move(CLICK_CD_MELEE)
M.do_attack_animation(src)
if(!(stat & BROKEN))
playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("<span class='userdanger'>[M] has slashed at [src]!</span>")
src.health -= 15
if(src.health <= 0)
src.die()
else
to_chat(M, "\green That object is useless to you.")
return
/obj/machinery/turretid/Topic(href, href_list, var/nowindow = 0)
if(..(href, href_list))
return 1
if(src.locked)
if(!istype(usr, /mob/living/silicon))
to_chat(usr, "Control panel is locked!")
return
if(href_list["toggleOn"])
src.enabled = !src.enabled
src.updateTurrets()
else if(href_list["toggleLethal"])
src.lethal = !src.lethal
src.updateTurrets()
if(!nowindow)
src.attack_hand(usr)
/obj/machinery/turretid/proc/update_icons()
if(src.enabled)
if(src.lethal)
icon_state = "control_kill"
else
icon_state = "control_stun"
else
icon_state = "control_standby"
//CODE FIXED BUT REMOVED
// if(control_area) //USE: updates other controls in the area
// for(var/obj/machinery/turretid/Turret_Control in world) //I'm not sure if this is what it was
// if( Turret_Control.control_area != src.control_area ) continue //supposed to do. Or whether the person
// Turret_Control.icon_state = icon_state //who coded it originally was just tired
// Turret_Control.enabled = enabled //or something. I don't see any situation
// Turret_Control.lethal = lethal //in which this would be used on the current map.
//If he wants it back he can uncomment it
/obj/machinery/gun_turret //related to turrets but work way differentely because of being mounted on a moving ship.
name = "machine gun turret"
desc = "Syndicate heavy defense turret. It really packs a bunch."
density = 1
anchored = 1
var/state = 0 //Like stat on mobs, 0 is alive, 1 is damaged, 2 is dead
var/faction = "syndicate"
var/atom/cur_target = null
var/scan_range = 9 //You will never see them coming
var/health = 200 //Because it lacks a cover, and is mostly to keep people from touching the syndie shuttle.
var/bullet_type = /obj/item/projectile/bullet
var/firing_sound = 'sound/weapons/Gunshot3.ogg'
var/base_icon = "syndieturret"
icon = 'icons/obj/turrets.dmi'
icon_state = "syndieturret0"
/obj/machinery/gun_turret/New()
..()
take_damage(0) //check your health
/obj/machinery/gun_turret/ex_act(severity)
switch(severity)
if(1)
die()
if(2)
take_damage(100)
if(3)
take_damage(50)
return
/obj/machinery/gun_turret/emp_act() //Can't emp an mechanical turret.
return
/obj/machinery/gun_turret/update_icon()
if(state > 2 || state < 0) //someone fucked up the vars so fix them
take_damage(0)
icon_state = "[base_icon]" + "[state]"
return
/obj/machinery/gun_turret/proc/take_damage(damage)
health -= damage
var/orig_health = initial(health)
var/health_percent = (health/orig_health) * 100
if(health_percent > 50)
state = 0
else
state = 1
if(health_percent <= 0)
if(state != 2)
die()
return
state = 2
update_icon()
/obj/machinery/gun_turret/bullet_act(var/obj/item/projectile/Proj)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
take_damage(Proj.damage)
return
/obj/machinery/gun_turret/proc/die()
state = 2
update_icon()
/obj/machinery/gun_turret/attack_hand(mob/user)
return
/obj/machinery/gun_turret/attack_ai(mob/user)
return attack_hand(user)
/obj/machinery/gun_turret/attack_alien(mob/living/user as mob)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1)
user.visible_message("[user] slashes at [src]", "You slash at [src]")
take_damage(15)
return
/obj/machinery/gun_turret/proc/validate_target(atom/target)
if(get_dist(target, src)>scan_range)
return 0
if(istype(target, /mob))
var/mob/M = target
if(!M.stat)
return 1
else if(istype(target, /obj/mecha))
var/obj/mecha/M = target
if(M.occupant)
return 1
else if(istype(target, /obj/spacepod))
var/obj/spacepod/S = target
if(S.pilot)
return 1
return 0
/obj/machinery/gun_turret/process()
if(state == 2)
return
if(cur_target && !validate_target(cur_target))
cur_target = null
if(!cur_target)
cur_target = get_target()
if(cur_target)
fire(cur_target)
return
/obj/machinery/gun_turret/proc/get_target()
var/list/pos_targets = list()
var/target = null
for(var/mob/living/M in view(scan_range,src))
if(M.stat)
continue
if(faction in M.faction)
continue
if(ispAI(M))
continue
pos_targets += M
for(var/obj/mecha/M in oview(scan_range, src))
if(M.occupant)
if(faction in M.occupant.faction)
continue
if(!M.occupant)
continue //Don't shoot at empty mechs.
pos_targets += M
for(var/obj/spacepod/M in oview(scan_range, src))
if(M.pilot)
var/mob/P = M.pilot
if(faction in P.faction)
continue
if(!M.pilot)
continue //Don't shoot at empty pods.
pos_targets += M
if(pos_targets.len)
target = pick(pos_targets)
return target
/obj/machinery/gun_turret/proc/fire(atom/target)
if(!target)
cur_target = null
return
src.dir = get_dir(src,target)
var/turf/targloc = get_turf(target)
if(!src)
return
var/turf/curloc = get_turf(src)
if(!targloc || !curloc)
return
if(targloc == curloc)
return
playsound(get_turf(src), firing_sound, 60, 1)
var/obj/item/projectile/A = new bullet_type(curloc)
A.original = target
A.current = curloc
A.yo = targloc.y - curloc.y
A.xo = targloc.x - curloc.x
A.fire()
return
/obj/machinery/gun_turret/interior
name = "machine gun turret (.45)"
desc = "Syndicate interior defense turret chambered for .45 rounds. Designed to down intruders without damaging the hull."
bullet_type = /obj/item/projectile/bullet/midbullet
/obj/machinery/gun_turret/exterior
name = "machine gun turret (7.62)"
desc = "Syndicate exterior defense turret chambered for 7.62 rounds. Designed to down intruders with heavy calliber bullets."
bullet_type = /obj/item/projectile/bullet
/obj/machinery/gun_turret/grenade
name = "mounted grenade launcher (40mm)"
desc = "Syndicate 40mm grenade launcher defense turret. If you've had this much time to look at it, you're probably already dead."
bullet_type = /obj/item/projectile/bullet/a40mm
/obj/machinery/gun_turret/assault_pod
name = "machine gun turret (4.6x30mm)"
desc = "Syndicate exterior defense turret chambered for 4.6x30mm rounds. Designed to be fitted to assault pods, it uses low calliber bullets to save space."
health = 100
bullet_type = /obj/item/projectile/bullet/weakbullet3

View File

@@ -92,6 +92,7 @@
processing_objects.Add(src)
removeVerb(/obj/mecha/verb/disconnect_from_port)
poi_list |= src
log_message("[src] created.")
mechas_list += src //global mech list
prepare_huds()
@@ -611,6 +612,7 @@
qdel(internal_tank)
processing_objects.Remove(src)
poi_list.Remove(src)
equipment.Cut()
cell = null
internal_tank = null

View File

@@ -18,6 +18,11 @@
var/new_frequency = sanitize_frequency(rand(PUBLIC_LOW_FREQ, PUBLIC_HIGH_FREQ))
aSignal.set_frequency(new_frequency)
poi_list |= src
/obj/effect/anomaly/Destroy()
poi_list.Remove(src)
return ..()
/obj/effect/anomaly/proc/anomalyEffect()
if(prob(50))

View File

@@ -262,3 +262,17 @@
new /obj/item/clothing/mask/gas/sexymime(src.loc)
new /obj/item/clothing/under/sexymime(src.loc)
qdel(src)
/obj/effect/landmark/ruin
var/datum/map_template/ruin/ruin_template
/obj/effect/landmark/ruin/New(loc, my_ruin_template)
name = "ruin_[ruin_landmarks.len + 1]"
..(loc)
ruin_template = my_ruin_template
ruin_landmarks |= src
/obj/effect/landmark/ruin/Destroy()
ruin_landmarks -= src
ruin_template = null
. = ..()

View File

@@ -1,4 +1,3 @@
/obj/effect/overlay
name = "overlay"
unacidable = 1
@@ -17,8 +16,8 @@
var/tmp/atom/BeamSource
New()
..()
spawn(10) qdel(src)
spawn(10)
qdel(src)
/obj/effect/overlay/temp
anchored = 1
@@ -30,6 +29,9 @@
/obj/effect/overlay/temp/New()
if(randomdir)
dir = pick(cardinal)
flick("[icon_state]", src) //Because we might be pulling it from a pool, flick whatever icon it uses so it starts at the start of the icon's animation.
spawn(duration)
qdel(src)

View File

@@ -102,19 +102,41 @@ var/global/list/datum/stack_recipe/human_recipes = list( \
icon_state = "sheet-leather"
origin_tech = "materials=2"
/obj/item/stack/sheet/sinew
name = "watcher sinew"
icon = 'icons/obj/mining.dmi'
desc = "Long stringy filaments which presumably came from a watcher's wings."
singular_name = "watcher sinew"
icon_state = "sinew"
origin_tech = "biotech=4"
/obj/item/stack/sheet/animalhide/goliath_hide
name = "goliath hide plates"
desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
icon = 'icons/obj/mining.dmi'
icon_state = "goliath_hide"
singular_name = "hide plate"
flags = NOBLUDGEON
w_class = 3
layer = MOB_LAYER
/obj/item/stack/sheet/animalhide/ashdrake
name = "ash drake hide"
desc = "The strong, scaled hide of an ash drake."
icon = 'icons/obj/mining.dmi'
icon_state = "dragon_hide"
singular_name = "drake plate"
flags = NOBLUDGEON
w_class = 3
layer = MOB_LAYER
//Step one - dehairing.
/obj/item/stack/sheet/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if( istype(W, /obj/item/weapon/kitchen/knife) || \
istype(W, /obj/item/weapon/twohanded/fireaxe) || \
istype(W, /obj/item/weapon/hatchet) )
//visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message)
usr.visible_message("\blue \the [usr] starts cutting hair off \the [src]", "\blue You start cutting the hair off \the [src]", "You hear the sound of a knife rubbing against flesh")
if(W.sharp)
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user,50, target = src))
to_chat(usr, "\blue You cut the hair from this [src.singular_name]")
user << "<span class='notice'>You cut the hair from this [src.singular_name].</span>"
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/sheet/hairlesshide/HS in usr.loc)
if(HS.amount < 50)
@@ -128,7 +150,6 @@ var/global/list/datum/stack_recipe/human_recipes = list( \
else
..()
//Step two - washing..... it's actually in washing machine code.
//Step three - drying

View File

@@ -201,3 +201,19 @@ var/global/list/datum/stack_recipe/cardboard_recipes = list (
/obj/item/stack/sheet/cardboard/New(var/loc, var/amt = null)
recipes = cardboard_recipes
return ..()
/*
* Bones
*/
/obj/item/stack/sheet/bone
name = "bones"
icon = 'icons/obj/mining.dmi'
icon_state = "bone"
singular_name = "bone"
desc = "Someone's been drinking their milk."
force = 7
throwforce = 5
w_class = 3
throw_speed = 1
throw_range = 3
origin_tech = "materials=2;biotech=2"

View File

@@ -20,6 +20,7 @@
for(var/i=1, i<=deliveryamt, i++)
var/atom/movable/x = new spawner_type
x.admin_spawned = admin_spawned
x.loc = T
if(prob(50))
for(var/j = 1, j <= rand(1, 3), j++)

View File

@@ -794,7 +794,8 @@ var/global/nologevent = 0
var/turf/T = get_turf(usr.loc)
T.ChangeTurf(chosen)
else
new chosen(usr.loc)
var/atom/A = new chosen(usr.loc)
A.admin_spawned = TRUE
log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])")
feedback_add_details("admin_verb","SA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -163,7 +163,9 @@ var/list/admin_verbs_debug = list(
/client/proc/map_template_upload,
/client/proc/view_runtimes,
/client/proc/admin_serialize,
/client/proc/admin_deserialize
/client/proc/admin_deserialize,
/client/proc/jump_to_ruin,
/client/proc/toggle_medal_disable
)
var/list/admin_verbs_possess = list(
/proc/possess,

View File

@@ -431,7 +431,7 @@
else
dat += "<tr><td><i>Nuclear Operative not found!</i></td></tr>"
dat += "</table><br><table><tr><td><B>Nuclear Disk(s)</B></td></tr>"
for(var/obj/item/weapon/disk/nuclear/N in world)
for(var/obj/item/weapon/disk/nuclear/N in poi_list)
dat += "<tr><td>[N.name], "
var/atom/disk_loc = N.loc
while(!istype(disk_loc, /turf))

View File

@@ -2154,6 +2154,7 @@
else
var/atom/O = new path(target)
if(O)
O.admin_spawned = TRUE
O.dir = obj_dir
if(obj_name)
O.name = obj_name

View File

@@ -1474,3 +1474,57 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return
error_cache.showTo(usr)
/client/proc/jump_to_ruin()
set category = "Debug"
set name = "Jump to Ruin"
set desc = "Displays a list of all placed ruins to teleport to."
if(!check_rights(R_DEBUG))
return
var/list/names = list()
for(var/i in ruin_landmarks)
var/obj/effect/landmark/ruin/ruin_landmark = i
var/datum/map_template/ruin/template = ruin_landmark.ruin_template
var/count = 1
var/name = template.name
var/original_name = name
while(name in names)
count++
name = "[original_name] ([count])"
names[name] = ruin_landmark
var/ruinname = input("Select ruin", "Jump to Ruin") as null|anything in names
var/obj/effect/landmark/ruin/landmark = names[ruinname]
if(istype(landmark))
var/datum/map_template/ruin/template = landmark.ruin_template
admin_forcemove(usr, get_turf(landmark))
usr << "<span class='name'>[template.name]</span>"
usr << "<span class='italics'>[template.description]</span>"
log_admin("[key_name(usr)] jumped to ruin [ruinname]")
if(!isobserver(usr))
message_admins("[key_name_admin(usr)] jumped to ruin [ruinname]", 1)
feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_medal_disable()
set category = "Debug"
set name = "Toggle Medal Disable"
set desc = "Toggles the safety lock on trying to contact the medal hub."
if(!check_rights(R_DEBUG))
return
global.medals_enabled = !global.medals_enabled
message_admins("<span class='adminnotice'>[key_name_admin(src)] [global.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.</span>")
feedback_add_details("admin_verb","TMH") // If...
log_admin("[key_name(src)] [global.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.")

View File

@@ -137,32 +137,38 @@
for(var/mob/M in mob_list)
if( istype(M , O.type) )
M.vars[variable] = O.vars[variable]
M.on_varedit(variable)
else if(istype(O, /obj))
for(var/obj/A in world)
if( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
A.on_varedit(variable)
else if(istype(O, /turf))
for(var/turf/A in world)
if( istype(A , O.type) )
A.vars[variable] = O.vars[variable]
A.on_varedit(variable)
else
if(istype(O, /mob))
for(var/mob/M in mob_list)
if(M.type == O.type)
M.vars[variable] = O.vars[variable]
M.on_varedit(variable)
else if(istype(O, /obj))
for(var/obj/A in world)
if(A.type == O.type)
A.vars[variable] = O.vars[variable]
A.on_varedit(variable)
else if(istype(O, /turf))
for(var/turf/A in world)
if(A.type == O.type)
A.vars[variable] = O.vars[variable]
A.on_varedit(variable)
if("edit referenced object")
return .(O.vars[variable])

View File

@@ -440,6 +440,7 @@ var/list/forbidden_varedit_object_types = list(
if(var_as_text == null)
var_as_text = "[O.vars[variable]]"
O.on_varedit(variable)
log_to_dd("### VarEdit by [src]: [O.type] [variable]=[html_encode("[var_as_text]")]")
log_admin("[key_name(src)] modified [original_name]'s [variable] to [var_as_text]")
message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [var_as_text]", 1)

View File

@@ -205,7 +205,17 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
template = safepick(possible_ruins)
if(!template)
return 0
var/turf/central_turf = get_turf(src)
for(var/i in template.get_affected_turfs(central_turf, 1))
var/turf/T = i
for(var/mob/living/simple_animal/monster in T)
qdel(monster)
for(var/obj/structure/flora/ash/plant in T)
qdel(plant)
template.load(get_turf(src),centered = 1)
template.loaded++
var/datum/map_template/ruin = template
if(istype(ruin))
new /obj/effect/landmark/ruin(central_turf, ruin)
qdel(src)
return 1

View File

@@ -34,9 +34,14 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
loc = start
z_original = z
destination = end
poi_list |= src
if(end && end.z==z_original)
walk_towards(src, destination, 1)
/obj/effect/immovablerod/Destroy()
poi_list.Remove(src)
return ..()
/obj/effect/immovablerod/Move()
if(z != z_original || loc == destination)
qdel(src)

View File

@@ -332,3 +332,10 @@
desc = "A cup with the british flag emblazoned on it."
icon_state = "britcup"
volume = 30
/obj/item/weapon/reagent_containers/food/drinks/mushroom_bowl
name = "mushroom bowl"
desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point."
icon = 'icons/obj/lavaland/ash_flora.dmi'
icon_state = "mushroom_bowl"
w_class = 2

View File

@@ -725,7 +725,7 @@
ranged = 1
sentience_type = SENTIENCE_MINEBOT
ranged_message = "shoots"
ranged_cooldown_cap = 3
ranged_cooldown_time = 30
projectiletype = /obj/item/projectile/kinetic
projectilesound = 'sound/weapons/Gunshot4.ogg'
speak_emote = list("states")
@@ -958,10 +958,10 @@
name = "minebot cooldown upgrade"
/obj/item/device/mine_bot_ugprade/cooldown/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
if(M.ranged_cooldown_cap != initial(M.ranged_cooldown_cap))
if(M.ranged_cooldown_time != initial(M.ranged_cooldown_time))
to_chat(user, "[M] already has a decreased weapon cooldown!")
return
M.ranged_cooldown_cap = 1
M.ranged_cooldown_time = 10
to_chat(user, "You upgrade [M]'s ranged weaponry, reducing its cooldown.")
qdel(src)

View File

@@ -0,0 +1,211 @@
/obj/structure/flora/ash
gender = PLURAL
icon = 'icons/obj/lavaland/ash_flora.dmi'
icon_state = "l_mushroom"
name = "large mushrooms"
desc = "A number of large mushrooms, covered in a faint layer of ash and what can only be spores."
var/harvested_name = "shortened mushrooms"
var/harvested_desc = "Some quickly regrowing mushrooms, formerly known to be quite large."
var/needs_sharp_harvest = TRUE
var/harvest = /obj/item/weapon/reagent_containers/food/snacks/ash_flora/shavings
var/harvest_amount_low = 1
var/harvest_amount_high = 3
var/harvest_time = 60
var/harvest_message_low = "You pick a mushroom, but fail to collect many shavings from its cap."
var/harvest_message_med = "You pick a mushroom, carefully collecting the shavings from its cap."
var/harvest_message_high = "You harvest and collect shavings from several mushroom caps."
var/harvested = FALSE
var/base_icon
var/regrowth_time_low = 4800
var/regrowth_time_high = 8400
/obj/structure/flora/ash/New()
..()
base_icon = "[icon_state][rand(1, 4)]"
icon_state = base_icon
if(prob(15))
harvest(null, TRUE)
/obj/structure/flora/ash/proc/harvest(user, no_drop)
if(harvested)
return 0
if(!no_drop)
var/rand_harvested = rand(harvest_amount_low, harvest_amount_high)
if(rand_harvested)
if(user)
var/msg = harvest_message_med
if(rand_harvested == harvest_amount_low)
msg = harvest_message_low
else if(rand_harvested == harvest_amount_high)
msg = harvest_message_high
user << "<span class='notice'>[msg]</span>"
for(var/i in 1 to rand_harvested)
new harvest(get_turf(src))
icon_state = "[base_icon]p"
name = harvested_name
desc = harvested_desc
harvested = TRUE
addtimer(src, "regrow", rand(regrowth_time_low, regrowth_time_high))
return 1
/obj/structure/flora/ash/proc/regrow()
icon_state = base_icon
name = initial(name)
desc = initial(desc)
harvested = FALSE
/obj/structure/flora/ash/attackby(obj/item/weapon/W, mob/user, params)
if(!harvested && needs_sharp_harvest && W.sharp)
user.visible_message("<span class='notice'>[user] starts to harvest from [src] with [W].</span>","<span class='notice'>You begin to harvest from [src] with [W].</span>")
if(do_after(user, harvest_time, target = src))
harvest(user)
else
return ..()
/obj/structure/flora/ash/attack_hand(mob/user)
if(!harvested && !needs_sharp_harvest)
user.visible_message("<span class='notice'>[user] starts to harvest from [src].</span>","<span class='notice'>You begin to harvest from [src].</span>")
if(do_after(user, harvest_time, target = src))
harvest(user)
else
..()
/obj/structure/flora/ash/tall_shroom //exists only so that the spawning check doesn't allow these spawning near other things
regrowth_time_low = 4200
/obj/structure/flora/ash/leaf_shroom
icon_state = "s_mushroom"
name = "leafy mushrooms"
desc = "A number of mushrooms, each of which surrounds a greenish sporangium with a number of leaf-like structures."
harvested_name = "leafless mushrooms"
harvested_desc = "A bunch of formerly-leafed mushrooms, with their sporangiums exposed. Scandalous?"
harvest = /obj/item/weapon/reagent_containers/food/snacks/ash_flora/mushroom_leaf
needs_sharp_harvest = FALSE
harvest_amount_high = 4
harvest_time = 20
harvest_message_low = "You pluck a single, suitable leaf."
harvest_message_med = "You pluck a number of leaves, leaving a few unsuitable ones."
harvest_message_high = "You pluck quite a lot of suitable leaves."
regrowth_time_low = 2400
regrowth_time_high = 6000
/obj/structure/flora/ash/cap_shroom
icon_state = "r_mushroom"
name = "tall mushrooms"
desc = "Several mushrooms, the larger of which have a ring of conks at the midpoint of their stems."
harvested_name = "small mushrooms"
harvested_desc = "Several small mushrooms near the stumps of what likely were larger mushrooms."
harvest = /obj/item/weapon/reagent_containers/food/snacks/ash_flora/mushroom_cap
harvest_amount_high = 4
harvest_time = 50
harvest_message_low = "You slice the cap off of a mushroom."
harvest_message_med = "You slice off a few conks from the larger mushrooms."
harvest_message_high = "You slice off a number of caps and conks from these mushrooms."
regrowth_time_low = 3000
regrowth_time_high = 5400
/obj/structure/flora/ash/stem_shroom
icon_state = "t_mushroom"
name = "numerous mushrooms"
desc = "A large number of mushrooms, some of which have long, fleshy stems. They're radiating light!"
luminosity = 1
harvested_name = "tiny mushrooms"
harvested_desc = "A few tiny mushrooms around larger stumps. You can already see them growing back."
harvest = /obj/item/weapon/reagent_containers/food/snacks/ash_flora/mushroom_stem
harvest_amount_high = 4
harvest_time = 40
harvest_message_low = "You pick and slice the cap off of a mushroom, leaving the stem."
harvest_message_med = "You pick and decapitate several mushrooms for their stems."
harvest_message_high = "You acquire a number of stems from these mushrooms."
regrowth_time_low = 3000
regrowth_time_high = 6000
/obj/structure/flora/ash/cacti
icon_state = "cactus"
name = "fruiting cacti"
desc = "Several prickly cacti, brimming with ripe fruit and covered in a thin layer of ash."
harvested_name = "cacti"
harvested_desc = "A bunch of prickly cacti. You can see fruits slowly growing beneath the covering of ash."
harvest = /obj/item/weapon/reagent_containers/food/snacks/ash_flora/cactus_fruit
needs_sharp_harvest = FALSE
harvest_amount_high = 2
harvest_time = 10
harvest_message_low = "You pick a cactus fruit."
harvest_message_med = "You pick several cactus fruit." //shouldn't show up, because you can't get more than two
harvest_message_high = "You pick a pair of cactus fruit."
regrowth_time_low = 4800
regrowth_time_high = 7200
/obj/structure/flora/ash/cacti/Crossed(mob/AM)
if(ishuman(AM) && has_gravity(loc) && prob(70))
var/mob/living/carbon/human/H = AM
if(!H.shoes && !H.lying) //ouch, my feet.
var/picked_def_zone = pick("l_leg", "r_leg")
var/obj/item/organ/external/affected = H.get_organ(picked_def_zone)
if(!istype(affected))
return
H.apply_damage(rand(3, 6), BRUTE, picked_def_zone)
H.Weaken(2)
H.visible_message("<span class='danger'>[H] steps on a cactus!</span>", \
"<span class='userdanger'>You step on a cactus!</span>")
/obj/item/weapon/reagent_containers/food/snacks/ash_flora/
name = "mushroom shavings"
desc = "Some shavings from a tall mushroom. With enough, might serve as a bowl."
icon = 'icons/obj/lavaland/ash_flora.dmi'
icon_state = "mushroom_shavings"
list_reagents = list("sugar" = 3, "ethanol" = 2, "stabilizing_agent" = 3, "minttoxin" = 2)
w_class = 1
/obj/item/weapon/reagent_containers/food/snacks/ash_flora/New()
..()
pixel_x = rand(-4, 4)
pixel_y = rand(-4, 4)
/obj/item/weapon/reagent_containers/food/snacks/ash_flora/shavings //for actual crafting
/obj/item/weapon/reagent_containers/food/snacks/ash_flora/mushroom_leaf
name = "mushroom leaf"
desc = "A leaf, from a mushroom."
list_reagents = list("nutriment" = 3, "vitfro" = 2, "nicotine" = 2)
icon_state = "mushroom_leaf"
/obj/item/weapon/reagent_containers/food/snacks/ash_flora/mushroom_cap
name = "mushroom cap"
desc = "The cap of a large mushroom."
list_reagents = list("mindbreaker" = 2, "entpoly" = 4, "mushroomhallucinogen" = 2)
icon_state = "mushroom_cap"
/obj/item/weapon/reagent_containers/food/snacks/ash_flora/mushroom_stem
name = "mushroom stem"
desc = "A long mushroom stem. It's slightly glowing."
list_reagents = list("tinlux" = 2, "vitamin" = 1, "space_drugs" = 1)
icon_state = "mushroom_stem"
luminosity = 1
/obj/item/weapon/reagent_containers/food/snacks/ash_flora/cactus_fruit
name = "cactus fruit"
list_reagents = list("vitamin" = 2, "nutriment" = 2, "vitfro" = 4)
desc = "A cactus fruit covered in a thick, reddish skin. And some ash."
icon_state = "cactus_fruit"
/obj/item/mushroom_bowl
name = "mushroom bowl"
desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point."
icon = 'icons/obj/lavaland/ash_flora.dmi'
icon_state = "mushroom_bowl"
w_class = 2
//what you can craft with these things
/datum/crafting_recipe/mushroom_bowl
name = "Mushroom Bowl"
result = /obj/item/weapon/reagent_containers/food/drinks/mushroom_bowl
reqs = list(/obj/item/weapon/reagent_containers/food/snacks/ash_flora/shavings = 5)
time = 30
category = CAT_PRIMAL

View File

@@ -0,0 +1,229 @@
//The chests dropped by mob spawner tendrils. Also contains associated loot.
/obj/structure/closet/crate/necropolis
name = "necropolis chest"
desc = "It's watching you closely."
icon_state = "necrocrate"
icon_opened = "necrocrateopen"
icon_closed = "necrocrate"
///Bosses
//Dragon
/obj/structure/closet/crate/necropolis/dragon
name = "dragon chest"
/obj/structure/closet/crate/necropolis/dragon/New()
..()
var/loot = rand(1,4)
switch(loot)
if(1)
new /obj/item/weapon/melee/ghost_sword(src)
if(2)
new /obj/item/weapon/lava_staff(src)
if(3)
new /obj/item/weapon/spellbook/oneuse/sacredflame(src)
new /obj/item/weapon/gun/magic/wand/fireball(src)
if(4)
new /obj/item/weapon/dragons_blood(src)
/obj/item/weapon/melee/ghost_sword
name = "spectral blade"
desc = "A rusted and dulled blade. It doesn't look like it'd do much damage. It glows weakly."
icon_state = "spectral"
item_state = "spectral"
flags = CONDUCT
sharp = 1
w_class = 4
force = 1
throwforce = 1
hitsound = 'sound/effects/ghost2.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "rended")
var/summon_cooldown = 0
var/list/mob/dead/observer/spirits
/obj/item/weapon/melee/ghost_sword/New()
..()
spirits = list()
processing_objects.Add(src)
poi_list |= src
/obj/item/weapon/melee/ghost_sword/Destroy()
for(var/mob/dead/observer/G in spirits)
G.invisibility = initial(G.invisibility)
spirits.Cut()
processing_objects.Remove(src)
poi_list -= src
. = ..()
/obj/item/weapon/melee/ghost_sword/attack_self(mob/user)
if(summon_cooldown > world.time)
to_chat(user, "You just recently called out for aid. You don't want to annoy the spirits.")
return
to_chat(user, "You call out for aid, attempting to summon spirits to your side.")
notify_ghosts("[user] is raising their [src], calling for your help!", enter_link="<a href=?src=[UID()];follow=1>(Click to help)</a>", source = user, action = NOTIFY_FOLLOW)
summon_cooldown = world.time + 600
/obj/item/weapon/melee/ghost_sword/Topic(href, href_list)
if(href_list["follow"])
var/mob/dead/observer/ghost = usr
if(istype(ghost))
ghost.ManualFollow(src)
/obj/item/weapon/melee/ghost_sword/process()
ghost_check()
/obj/item/weapon/melee/ghost_sword/proc/ghost_check()
var/ghost_counter = 0
var/turf/T = get_turf(src)
var/list/contents = T.GetAllContents()
var/mob/dead/observer/current_spirits = list()
var/list/followers = list()
for(var/mob/dead/observer/O in player_list)
if(is_type_in_list(O.following, contents))
followers += O
for(var/thing in followers)
if (isobserver(thing))
var/mob/dead/observer/G = thing
ghost_counter++
G.invisibility = 0
current_spirits |= G
for(var/mob/dead/observer/G in spirits - current_spirits)
G.invisibility = initial(G.invisibility)
spirits = current_spirits
return ghost_counter
/obj/item/weapon/melee/ghost_sword/attack(mob/living/target, mob/living/carbon/human/user)
force = 0
var/ghost_counter = ghost_check()
force = Clamp((ghost_counter * 4), 0, 75)
user.visible_message("<span class='danger'>[user] strikes with the force of [ghost_counter] vengeful spirits!</span>")
..()
/obj/item/weapon/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
var/ghost_counter = ghost_check()
final_block_chance += Clamp((ghost_counter * 5), 0, 75)
owner.visible_message("<span class='danger'>[owner] is protected by a ring of [ghost_counter] ghosts!</span>")
return ..()
// Blood
/obj/item/weapon/dragons_blood
name = "bottle of dragons blood"
desc = "You're not actually going to drink this, are you?"
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
/obj/item/weapon/dragons_blood/attack_self(mob/living/carbon/human/user)
if(!istype(user))
return
var/mob/living/carbon/human/H = user
var/random = rand(1,3)
switch(random)
if(1)
to_chat(user, "<span class='danger'>Your flesh begins to melt! Miraculously, you seem fine otherwise.</span>")
H.set_species("Skeleton")
if(2)
to_chat(user, "<span class='danger'>You don't feel so good...</span>")
message_admins("[key_name_admin(user)] has started transforming into a dragon via dragon's blood.")
H.ForceContractDisease(new /datum/disease/transformation/dragon(0))
if(3)
to_chat(user, "<span class='danger'>You feel like you could walk straight through lava now.</span>")
H.weather_immunities |= "lava"
playsound(user.loc,'sound/items/drink.ogg', rand(10,50), 1)
qdel(src)
/datum/disease/transformation/dragon
name = "dragon transformation"
cure_text = "nothing"
cures = list("adminordrazine")
agent = "dragon's blood"
desc = "What do dragons have to do with Space Station 13?"
stage_prob = 20
severity = BIOHAZARD
visibility_flags = 0
stage1 = list("Your bones ache.")
stage2 = list("Your skin feels scaley.")
stage3 = list("<span class='danger'>You have an overwhelming urge to terrorize some peasants.</span>", "<span class='danger'>Your teeth feel sharper.</span>")
stage4 = list("<span class='danger'>Your blood burns.</span>")
stage5 = list("<span class='danger'>You're a fucking dragon. However, any previous allegiances you held still apply. It'd be incredibly rude to eat your still human friends for no reason.</span>")
new_form = /mob/living/simple_animal/hostile/megafauna/dragon/lesser
//Lava Staff
/obj/item/weapon/lava_staff
name = "staff of lava"
desc = "The ability to fill the emergency shuttle with lava. What more could you want out of life?"
icon_state = "staffofstorms"
item_state = "staffofstorms"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
item_state = "staffofstorms"
w_class = 4
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
var/turf_type = /turf/unsimulated/floor/lava // /turf/simulated/floor/plating/lava/smooth once Lavaland turfs are added
var/transform_string = "lava"
var/reset_turf_type = /turf/simulated/floor/plating/airless/asteroid // /turf/simulated/floor/plating/asteroid/basalt once Lavaland turfs are added
var/reset_string = "basalt"
var/create_cooldown = 100
var/create_delay = 30
var/reset_cooldown = 50
var/timer = 0
var/banned_turfs
/obj/item/weapon/lava_staff/New()
. = ..()
banned_turfs = typecacheof(list(/turf/space/transit, /turf/unsimulated))
/obj/item/weapon/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
..()
if(timer > world.time)
return
if(is_type_in_typecache(target, banned_turfs))
return
if(target in view(user.client.view, get_turf(user)))
var/turf/simulated/T = get_turf(target)
if(!istype(T))
return
if(!istype(T, turf_type))
var/obj/effect/overlay/temp/lavastaff/L = PoolOrNew(/obj/effect/overlay/temp/lavastaff, T)
L.alpha = 0
animate(L, alpha = 255, time = create_delay)
user.visible_message("<span class='danger'>[user] points [src] at [T]!</span>")
timer = world.time + create_delay + 1
if(do_after(user, create_delay, target = T))
user.visible_message("<span class='danger'>[user] turns \the [T] into [transform_string]!</span>")
message_admins("[key_name_admin(user)] fired the lava staff at [get_area(target)] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>).")
log_game("[key_name(user)] fired the lava staff at [get_area(target)] ([T.x], [T.y], [T.z]).")
T.ChangeTurf(turf_type)
timer = world.time + create_cooldown
qdel(L)
else
timer = world.time
qdel(L)
return
else
user.visible_message("<span class='danger'>[user] turns \the [T] into [reset_string]!</span>")
T.ChangeTurf(reset_turf_type)
timer = world.time + reset_cooldown
playsound(T,'sound/magic/Fireball.ogg', 200, 1)
/obj/effect/overlay/temp/lavastaff
icon_state = "lavastaff_warn"
duration = 50

View File

@@ -63,6 +63,10 @@
refined_type = /obj/item/stack/sheet/glass
materials = list(MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
/obj/item/weapon/ore/glass/basalt
name = "volcanic ash"
icon_state = "volcanic_sand"
/obj/item/weapon/ore/glass/attack_self(mob/living/user as mob)
to_chat(user, "<span class='notice'>You use the sand to make sandstone.</span>")
var/sandAmt = 1

View File

@@ -1,6 +1,5 @@
/mob/living/simple_animal/hostile
faction = list("hostile")
mouse_opacity = 2 //This makes it easier to hit hostile mobs, you only need to click on their tile, and is set back to 1 when they die
stop_automated_movement_when_pulled = 0
environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls
var/atom/target
@@ -13,7 +12,8 @@
var/list/friends = list()
var/ranged_message = "fires" //Fluff text for ranged mobs
var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks
var/ranged_cooldown_cap = 3 //What ranged attacks, after being used are set to, to go back on cooldown, defaults to 3 life() ticks
var/ranged_cooldown_time = 30 //How long, in deciseconds, the cooldown of ranged attacks is
var/ranged_ignores_vision = FALSE //if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash
var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting
var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance
@@ -31,10 +31,30 @@
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
//typecache of things this mob will attack in DestroySurroundings() if it has environment_smash
var/list/environment_target_typecache = list(
/obj/machinery/door/window,
/obj/structure/window,
/obj/structure/closet,
/obj/structure/table,
/obj/structure/grille,
/obj/structure/girder,
/obj/structure/rack,
/obj/structure/barricade) //turned into a typecache in New()
var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such
/mob/living/simple_animal/hostile/New()
..()
if(!targets_from)
targets_from = src
environment_target_typecache = typecacheof(environment_target_typecache)
/mob/living/simple_animal/hostile/Destroy()
targets_from = null
return ..()
/mob/living/simple_animal/hostile/Life()
. = ..()
if(ranged)
ranged_cooldown--
if(!.)
walk(src, 0)
return 0
@@ -62,20 +82,19 @@
/mob/living/simple_animal/hostile/proc/ListTargets()//Step 1, find out what we can see
var/list/L = list()
. = list()
if(!search_objects)
var/list/Mobs = hearers(vision_range, src) - src //Remove self, so we don't suicide
L += Mobs
for(var/obj/mecha/M in mechas_list)
if(get_dist(M, src) <= vision_range && can_see(src, M, vision_range))
L += M
for(var/obj/spacepod/S in spacepods_list)
if(get_dist(S, src) <= vision_range && can_see(src, S, vision_range))
L += S
var/list/Mobs = hearers(vision_range, targets_from) - src //Remove self, so we don't suicide
. += Mobs
var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha, /obj/spacepod))
for(var/HM in typecache_filter_list(range(vision_range, targets_from), hostile_machines))
if(can_see(targets_from, HM, vision_range))
. += HM
else
var/list/Objects = oview(vision_range, src)
L += Objects
return L
var/list/Objects = oview(vision_range, targets_from)
. += Objects
/mob/living/simple_animal/hostile/proc/FindTarget(var/list/possible_targets, var/HasTargetsList = 0)//Step 2, filter down possible targets to things we actually care about
var/list/Targets = list()
@@ -100,8 +119,8 @@
return
if(target != null)//If we already have a target, but are told to pick again, calculate the lowest distance between all possible, and pick from the lowest distance targets
for(var/atom/A in Targets)
var/target_dist = get_dist(src, target)
var/possible_target_distance = get_dist(src, A)
var/target_dist = get_dist(targets_from, target)
var/possible_target_distance = get_dist(targets_from, A)
if(target_dist < possible_target_distance)
Targets -= A
var/chosen_target = safepick(Targets)//Pick the remaining targets (if any) at random
@@ -111,16 +130,6 @@
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
return 0
if(search_objects < 2)
if(istype(the_target, /obj/mecha))
var/obj/mecha/M = the_target
if(M.occupant)//Just so we don't attack empty mechs
if(CanAttack(M.occupant))
return 1
if(istype(the_target, /obj/spacepod))
var/obj/spacepod/S = the_target
if(S.pilot) //Just so we don't attack empty pods
if(CanAttack(S.pilot))
return 1
if(isliving(the_target))
var/mob/living/L = the_target
var/faction_check = 0
@@ -141,6 +150,28 @@
if(faction_check && !attack_same)
return 0
return 1
if(istype(the_target, /obj/mecha))
var/obj/mecha/M = the_target
if(M.occupant)//Just so we don't attack empty mechs
if(CanAttack(M.occupant))
return 1
if(istype(the_target, /obj/spacepod))
var/obj/spacepod/S = the_target
if(S.pilot) //Just so we don't attack empty pods
if(CanAttack(S.pilot))
return 1
if(istype(the_target, /obj/machinery/porta_turret))
var/obj/machinery/porta_turret/P = the_target
if(P.faction in faction)
return 0
if(!P.raised) //Don't attack invincible turrets
return 0
if(P.stat & BROKEN) //Or turrets that are already broken
return 0
return 1
if(isobj(the_target))
if(is_type_in_list(the_target, wanted_objects))
return 1
@@ -157,9 +188,12 @@
LoseTarget()
return 0
if(target in possible_targets)
var/target_distance = get_dist(src,target)
if(target.z != z)
LoseTarget()
return 0
var/target_distance = get_dist(targets_from,target)
if(ranged)//We ranged? Shoot at em
if(target_distance >= 2 && ranged_cooldown <= 0)//But make sure they're a tile away at least, and our range attack is off cooldown
if(!target.Adjacent(targets_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown
OpenFire(target)
if(retreat_distance != null)//If we have a retreat distance, check if we need to run from our target
if(target_distance <= retreat_distance)//If target's closer than our retreat distance, run
@@ -168,11 +202,15 @@
Goto(target,move_to_delay,minimum_distance)//Otherwise, get to our minimum distance so we chase them
else
Goto(target,move_to_delay,minimum_distance)
if(isturf(loc) && target.Adjacent(src)) //If they're next to us, attack
if(target)
if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
AttackingTarget()
return 1
return 1
if(environment_smash)
if(target.loc != null && get_dist(src, target.loc) <= vision_range)//We can't see our target, but he's in our vision range still
if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range)//We can't see our target, but he's in our vision range still
if(ranged_ignores_vision && ranged_cooldown <= world.time) //we can't see our target... but we can fire at them!
OpenFire(target)
if(environment_smash >= 2)//If we're capable of smashing through walls, forget about vision completely after finding our target
Goto(target,move_to_delay,minimum_distance)
FindHidden()
@@ -221,59 +259,60 @@
/mob/living/simple_animal/hostile/death(gibbed)
LoseAggro()
mouse_opacity = 1
..()
walk(src, 0)
/mob/living/simple_animal/hostile/proc/OpenFire(var/the_target)
var/target = the_target
/mob/living/simple_animal/hostile/proc/summon_backup(distance)
do_alert_animation(src)
playsound(loc, 'sound/machines/chime.ogg', 50, 1, -1)
for(var/mob/living/simple_animal/hostile/M in oview(distance, targets_from))
var/list/L = M.faction&faction
if(L.len)
if(M.AIStatus == AI_OFF)
return
else
M.Goto(src,M.move_to_delay,M.minimum_distance)
/mob/living/simple_animal/hostile/proc/OpenFire(atom/A)
if(check_friendly_fire)
for(var/turf/T in getline(src, target)) // Not 100% reliable but this is faster than simulating actual trajectory
for(var/mob/living/L in T)
if(L == src || L == target)
if(L == src || L == A)
continue
if(faction_check(L) && !attack_same)
return
visible_message("<span class='danger'><b>[src]</b> [ranged_message] at [target]!</span>")
visible_message("<span class='danger'><b>[src]</b> [ranged_message] at [A]!</span>")
if(rapid)
spawn(1)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
Shoot(A)
spawn(4)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
Shoot(A)
spawn(6)
Shoot(target, src.loc, src)
if(casingtype)
new casingtype(get_turf(src))
Shoot(A)
else
Shoot(target, src.loc, src)
if(casingtype)
new casingtype
ranged_cooldown = ranged_cooldown_cap
Shoot(A)
ranged_cooldown = world.time + ranged_cooldown_time
return
/mob/living/simple_animal/hostile/proc/Shoot(var/target, var/start, var/user, var/bullet = 0)
if(target == start)
/mob/living/simple_animal/hostile/proc/Shoot(atom/targeted_atom)
if(targeted_atom == targets_from.loc || targeted_atom == targets_from)
return
var/turf/startloc = get_turf(targets_from)
if(casingtype)
var/obj/item/ammo_casing/casing = new casingtype
var/obj/item/ammo_casing/casing = new casingtype(startloc)
playsound(src, projectilesound, 100, 1)
casing.fire(target, src, zone_override = ran_zone())
casing.loc = loc
casing.fire(targeted_atom, src, zone_override = ran_zone())
else
var/obj/item/projectile/A = new projectiletype(loc)
playsound(user, projectilesound, 100, 1)
playsound(src, projectilesound, 100, 1)
A.current = target
A.firer = src
A.yo = target:y - start:y
A.xo = target:x - start:x
A.yo = targeted_atom.y - startloc.y
A.xo = targeted_atom.x - startloc.x
if(AIStatus == AI_OFF)//Don't want mindless mobs to have their movement screwed up firing in space
newtonian_move(get_dir(target, user))
newtonian_move(get_dir(target, targets_from))
A.original = target
A.fire()
return A
@@ -282,22 +321,22 @@
if(environment_smash)
EscapeConfinement()
for(var/dir in cardinal)
var/turf/T = get_step(src, dir)
var/turf/T = get_step(targets_from, dir)
if(istype(T, /turf/simulated/wall) || istype(T, /turf/simulated/mineral))
if(T.Adjacent(src))
if(T.Adjacent(targets_from))
T.attack_animal(src)
for(var/atom/A in T)
if(!A.Adjacent(src))
if(!A.Adjacent(targets_from))
continue
if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack))
if(is_type_in_typecache(A, environment_target_typecache))
A.attack_animal(src)
return
/mob/living/simple_animal/hostile/proc/EscapeConfinement()
if(buckled)
buckled.attack_animal(src)
if(!isturf(src.loc) && src.loc != null)//Did someone put us in something?
var/atom/A = src.loc
if(!isturf(targets_from.loc) && targets_from.loc != null)//Did someone put us in something?
var/atom/A = get_turf(targets_from)
A.attack_animal(src)//Bang on it till we get out
return
@@ -305,12 +344,12 @@
if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper) || istype(target.loc, /obj/machinery/bodyscanner) || istype(target.loc, /obj/machinery/recharge_station))
var/atom/A = target.loc
Goto(A,move_to_delay,minimum_distance)
if(A.Adjacent(src))
if(A.Adjacent(targets_from))
A.attack_animal(src)
return 1
/mob/living/simple_animal/hostile/RangedAttack(var/atom/A, var/params) //Player firing
if(ranged && ranged_cooldown <= 0)
if(ranged && ranged_cooldown <= world.time)
target = A
OpenFire(A)
..()

View File

@@ -0,0 +1,278 @@
#define MEDAL_PREFIX "Drake"
/*
ASH DRAKE
Ash drakes spawn randomly wherever a lavaland creature is able to spawn. They are the draconic guardians of the Necropolis.
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
Whenever possible, the drake will breathe fire in the four cardinal directions, igniting and heavily damaging anything caught in the blast.
It also often causes fire to rain from the sky - many nearby turfs will flash red as a fireball crashes into them, dealing damage to anything on the turfs.
The drake also utilizes its wings to fly into the sky and crash down onto a specified point. Anything on this point takes tremendous damage.
- Sometimes it will chain these swooping attacks over and over, making swiftness a necessity.
When an ash drake dies, it leaves behind a chest that can contain four things:
1. A spectral blade that allows its wielder to call ghosts to it, enhancing its power
2. A lava staff that allows its wielder to create lava
3. A spellbook and wand of fireballs
4. A bottle of dragon's blood with several effects, including turning its imbiber into a drake themselves.
When butchered, they leave behind diamonds, sinew, bone, and ash drake hide. Ash drake hide can be used to create a hooded cloak that protects its wearer from ash storms.
Difficulty: Medium
*/
/mob/living/simple_animal/hostile/megafauna/dragon
name = "ash drake"
desc = "Guardians of the necropolis."
health = 2500
maxHealth = 2500
attacktext = "chomps"
attack_sound = 'sound/misc/demon_attack1.ogg'
icon_state = "dragon"
icon_living = "dragon"
icon_dead = "dragon_dead"
friendly = "stares down"
icon = 'icons/mob/lavaland/dragon.dmi'
speak_emote = list("roars")
armour_penetration = 40
melee_damage_lower = 40
melee_damage_upper = 40
speed = 1
move_to_delay = 10
ranged = 1
pixel_x = -16
loot = list(/obj/structure/closet/crate/necropolis/dragon)
butcher_results = list(/obj/item/weapon/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
var/swooping = 0
var/swoop_cooldown = 0
medal_type = MEDAL_PREFIX
score_type = DRAKE_SCORE
deathmessage = "collapses into a pile of bones, its flesh sloughing away."
death_sound = 'sound/misc/demon_dies.ogg'
/mob/living/simple_animal/hostile/megafauna/dragon/New()
..()
internal_gps = new/obj/item/device/gps/internal/dragon(src)
/mob/living/simple_animal/hostile/megafauna/dragon/ex_act(severity, target)
if(severity == 3)
return
..()
/mob/living/simple_animal/hostile/megafauna/dragon/adjustHealth(amount)
if(swooping)
return 0
return ..()
/mob/living/simple_animal/hostile/megafauna/dragon/AttackingTarget()
if(!swooping)
..()
/mob/living/simple_animal/hostile/megafauna/dragon/DestroySurroundings()
if(!swooping)
..()
/mob/living/simple_animal/hostile/megafauna/dragon/Move()
if(!swooping)
..()
/mob/living/simple_animal/hostile/megafauna/dragon/Goto(target, delay, minimum_distance)
if(!swooping)
..()
/mob/living/simple_animal/hostile/megafauna/dragon/Process_Spacemove(movement_dir = 0)
return 1
/obj/effect/overlay/temp/fireball
icon = 'icons/obj/wizard.dmi'
icon_state = "fireball"
name = "fireball"
desc = "Get out of the way!"
layer = 6
randomdir = 0
duration = 12
pixel_z = 500
/obj/effect/overlay/temp/fireball/New(loc)
..()
animate(src, pixel_z = 0, time = 12)
/obj/effect/overlay/temp/target
icon = 'icons/mob/actions.dmi'
icon_state = "sniper_zoom"
layer = MOB_LAYER - 0.1
luminosity = 2
duration = 12
/obj/effect/overlay/temp/dragon_swoop
name = "certain death"
desc = "Don't just stand there, move!"
icon = 'icons/effects/96x96.dmi'
icon_state = "landing"
layer = MOB_LAYER - 0.1
pixel_x = -32
pixel_y = -32
color = "#FF0000"
duration = 10
/obj/effect/overlay/temp/target/ex_act()
return
/obj/effect/overlay/temp/target/New(loc)
..()
spawn(0)
fall()
/obj/effect/overlay/temp/target/proc/fall()
var/turf/T = get_turf(src)
playsound(T,'sound/magic/Fireball.ogg', 200, 1)
PoolOrNew(/obj/effect/overlay/temp/fireball,T)
sleep(12)
explosion(T, 0, 0, 1, 0, 0, 0, 1)
/mob/living/simple_animal/hostile/megafauna/dragon/OpenFire()
anger_modifier = Clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + ranged_cooldown_time
if(swooping)
fire_rain()
return
if(prob(15 + anger_modifier) && !client)
if(health < maxHealth/2)
spawn(0)
swoop_attack(1)
else
fire_rain()
else if(prob(10+anger_modifier) && !client)
if(health > maxHealth/2)
spawn(0)
swoop_attack(0)
else
spawn(0)
triple_swoop(0)
else
fire_walls()
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_rain()
visible_message("<span class='boldwarning'>Fire rains from the sky!</span>")
for(var/turf/turf in range(12,get_turf(src)))
if(prob(10))
PoolOrNew(/obj/effect/overlay/temp/target, turf)
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_walls()
playsound(get_turf(src),'sound/magic/Fireball.ogg', 200, 1)
for(var/d in cardinal)
spawn(0)
fire_wall(d)
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_wall(dir)
var/list/hit_things = list(src)
var/turf/E = get_edge_target_turf(src, dir)
var/range = 10
var/turf/previousturf = get_turf(src)
for(var/turf/J in getline(src,E))
if(!range || !previousturf.CanAtmosPass(J))
break
range--
PoolOrNew(/obj/effect/hotspot,J)
J.hotspot_expose(700,50,1)
for(var/mob/living/L in J.contents - hit_things)
L.adjustFireLoss(20)
to_chat(L, "<span class='userdanger'>You're hit by the drake's fire breath!</span>")
hit_things += L
previousturf = J
sleep(1)
/mob/living/simple_animal/hostile/megafauna/dragon/proc/triple_swoop()
swoop_attack()
swoop_attack()
swoop_attack()
/mob/living/simple_animal/hostile/megafauna/dragon/proc/swoop_attack(fire_rain = 0, atom/movable/manual_target)
if(stat || swooping)
return
swoop_cooldown = world.time + 200
var/atom/swoop_target
if(manual_target)
swoop_target = manual_target
else
swoop_target = target
stop_automated_movement = TRUE
swooping = 1
density = 0
icon_state = "swoop"
visible_message("<span class='boldwarning'>[src] swoops up high!</span>")
if(prob(50))
animate(src, pixel_x = 500, pixel_z = 500, time = 10)
else
animate(src, pixel_x = -500, pixel_z = 500, time = 10)
sleep(30)
var/turf/tturf
if(fire_rain)
fire_rain()
icon_state = "dragon"
if(swoop_target && !qdeleted(swoop_target) && swoop_target.z == src.z)
tturf = get_turf(swoop_target)
else
tturf = get_turf(src)
forceMove(tturf)
PoolOrNew(/obj/effect/overlay/temp/dragon_swoop, tturf)
animate(src, pixel_x = initial(pixel_x), pixel_z = 0, time = 10)
sleep(10)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1)
for(var/mob/living/L in orange(1, src))
if(L.stat)
visible_message("<span class='warning'>[src] slams down on [L], crushing them!</span>")
L.gib()
else
L.adjustBruteLoss(75)
if(L && !qdeleted(L)) // Some mobs are deleted on death
var/throw_dir = get_dir(src, L)
if(L.loc == loc)
throw_dir = pick(alldirs)
var/throwtarget = get_edge_target_turf(src, throw_dir)
L.throw_at_fast(throwtarget, 3)
visible_message("<span class='warning'>[L] is thrown clear of [src]!</span>")
for(var/mob/M in range(7, src))
shake_camera(M, 15, 1)
stop_automated_movement = FALSE
swooping = 0
density = 1
/mob/living/simple_animal/hostile/megafauna/dragon/AltClickOn(atom/movable/A)
if(!istype(A))
return
if(swoop_cooldown >= world.time)
to_chat(src, "<span class='warning'>You need to wait 20 seconds between swoop attacks!</span>")
return
swoop_attack(1, A)
/obj/item/device/gps/internal/dragon
icon_state = null
gpstag = "Fiery Signal"
desc = "Here there be dragons."
invisibility = 100
/mob/living/simple_animal/hostile/megafauna/dragon/lesser
name = "lesser ash drake"
maxHealth = 300
health = 300
faction = list("neutral")
melee_damage_upper = 30
melee_damage_lower = 30
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
loot = list()
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
return
#undef MEDAL_PREFIX

View File

@@ -0,0 +1,219 @@
#define MEDAL_PREFIX "Boss"
/mob/living/simple_animal/hostile/megafauna
name = "boss of this gym"
desc = "Attack the weak point for massive damage."
health = 1000
maxHealth = 1000
a_intent = "harm"
sentience_type = SENTIENCE_BOSS
environment_smash = 3
luminosity = 3
faction = list("mining", "boss")
weather_immunities = list("lava","ash")
flying = 1
robust_searching = 1
ranged_ignores_vision = TRUE
stat_attack = 2
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
minbodytemp = 0
maxbodytemp = INFINITY
aggro_vision_range = 18
idle_vision_range = 5
environment_target_typecache = list(
/obj/machinery/door/window,
/obj/structure/window,
/obj/structure/closet,
/obj/structure/table,
/obj/structure/grille,
/obj/structure/girder,
/obj/structure/rack,
/obj/structure/barricade,
/obj/machinery/field,
/obj/machinery/power/emitter)
var/medal_type = MEDAL_PREFIX
var/score_type = BOSS_SCORE
var/elimination = 0
var/anger_modifier = 0
var/obj/item/device/gps/internal_gps
anchored = TRUE
mob_size = MOB_SIZE_LARGE
layer = MOB_LAYER + 0.5 //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = 2 // Easier to click on in melee, they're giant targets anyway
/mob/living/simple_animal/hostile/megafauna/Destroy()
qdel(internal_gps)
. = ..()
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
if(health > 0)
return
else
if(!admin_spawned)
feedback_set_details("megafauna_kills","[initial(name)]")
if(!elimination) //used so the achievment only occurs for the last legion to die.
grant_achievement(medal_type,score_type)
..()
/mob/living/simple_animal/hostile/megafauna/gib()
if(health > 0)
return
else
..()
/mob/living/simple_animal/hostile/megafauna/dust()
if(health > 0)
return
else
..()
/mob/living/simple_animal/hostile/megafauna/AttackingTarget()
..()
if(isliving(target))
var/mob/living/L = target
if(L.stat != DEAD)
if(ranged && ranged_cooldown <= world.time)
OpenFire()
else
devour(L)
/mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L)
if(!L)
return
visible_message(
"<span class='danger'>[src] devours [L]!</span>",
"<span class='userdanger'>You feast on [L], restoring your health!</span>")
adjustBruteLoss(-L.maxHealth/2)
L.gib()
/mob/living/simple_animal/hostile/megafauna/ex_act(severity, target)
switch (severity)
if (1)
adjustBruteLoss(250)
if (2)
adjustBruteLoss(100)
if(3)
adjustBruteLoss(50)
/mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype,scoretype)
if(medal_type == "Boss") //Don't award medals if the medal type isn't set
return
if(admin_spawned)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
for(var/mob/living/L in view(7,src))
if(L.stat)
continue
if(L.client)
var/client/C = L.client
var/suffixm = BOSS_KILL_MEDAL
UnlockMedal("Boss [suffixm]",C)
UnlockMedal("[medaltype] [suffixm]",C)
SetScore(BOSS_SCORE,C,1)
SetScore(score_type,C,1)
/proc/UnlockMedal(medal,client/player)
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
spawn()
var/result = world.SetMedal(medal, player, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to award medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to award [medal] medal to [player.ckey]!")
else if (result)
to_chat(player.mob, "<span class='greenannounce'><B>Achievement unlocked: [medal]!</B></span>")
/proc/SetScore(score,client/player,increment,force)
if(!score || !player)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
spawn()
var/list/oldscore = GetScore(score,player,1)
if(increment)
if(!oldscore[score])
oldscore[score] = 1
else
oldscore[score] = (text2num(oldscore[score]) + 1)
else
oldscore[score] = force
var/newscoreparam = list2params(oldscore)
var/result = world.SetScores(player.ckey, newscoreparam, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to set score. Score:[score] player:[player.ckey]")
message_admins("Error! Failed to contact hub to set [score] score for [player.ckey]!")
/proc/GetScore(score,client/player,returnlist)
if(!score || !player)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
var/scoreget = world.GetScores(player.ckey, score, global.medal_hub, global.medal_pass)
if(isnull(scoreget))
global.medals_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to get score. Score:[score] player:[player.ckey]")
message_admins("Error! Failed to contact hub to get score: [score] for [player.ckey]!")
return
var/list/scoregetlist = params2list(scoreget)
if(returnlist)
return scoregetlist
else
return scoregetlist[score]
/proc/CheckMedal(medal,client/player)
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
var/result = world.GetMedal(medal, player, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to get medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to get [medal] medal for [player.ckey]!")
else if (result)
to_chat(player.mob, "[medal] is unlocked")
/proc/LockMedal(medal,client/player)
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
var/result = world.ClearMedal(medal, player, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to clear medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to clear [medal] medal for [player.ckey]!")
else if (result)
message_admins("Medal: [medal] removed for [player.ckey]")
else
message_admins("Medal: [medal] was not found for [player.ckey]. Unable to clear.")
/proc/ClearScore(client/player)
world.SetScores(player.ckey, "", global.medal_hub, global.medal_pass)
#undef MEDAL_PREFIX

View File

@@ -58,7 +58,7 @@
projectilesound = 'sound/weapons/pierce.ogg'
ranged = 1
ranged_message = "stares"
ranged_cooldown_cap = 20
ranged_cooldown_time = 30
throw_message = "does nothing against the hard shell of"
vision_range = 2
speed = 3
@@ -71,7 +71,6 @@
a_intent = I_HARM
speak_emote = list("chitters")
attack_sound = 'sound/weapons/bladeslice.ogg'
ranged_cooldown_cap = 4
aggro_vision_range = 9
idle_vision_range = 2
turns_per_move = 5
@@ -231,7 +230,7 @@
attack_sound = 'sound/weapons/pierce.ogg'
throw_message = "falls right through the strange body of the"
ranged_cooldown = 0
ranged_cooldown_cap = 0
ranged_cooldown_time = 20
environment_smash = 0
retreat_distance = 3
minimum_distance = 3
@@ -344,7 +343,7 @@
move_to_delay = 40
ranged = 1
ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight
ranged_cooldown_cap = 8
ranged_cooldown_time = 120
friendly = "wails at"
speak_emote = list("bellows")
vision_range = 4
@@ -368,7 +367,7 @@
handle_preattack()
/mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack()
if(ranged_cooldown <= 2 && !pre_attack)
if(ranged_cooldown <= world.time + ranged_cooldown_time * 0.25 && !pre_attack)
pre_attack++
if(!pre_attack || stat || AIStatus == AI_IDLE)
return
@@ -383,7 +382,7 @@
if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen
visible_message("<span class='warning'>The [src.name] digs its tentacles under [target.name]!</span>")
new /obj/effect/goliath_tentacle/original(tturf)
ranged_cooldown = ranged_cooldown_cap
ranged_cooldown = world.time + ranged_cooldown_time
icon_state = icon_aggro
pre_attack = 0
return

View File

@@ -40,6 +40,7 @@
return 0
spawn_delay = world.time + spawn_time
var/mob/living/simple_animal/L = new mob_type(src.loc)
L.admin_spawned = admin_spawned //If we were admin spawned, lets have our children count as that as well.
spawned_mobs += L
L.nest = src
L.faction = src.faction

View File

@@ -440,20 +440,20 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
lname = "<span class='name'>[lname]</span> "
to_chat(M, "<span class='deadsay'>[lname][follow][message]</span>")
/proc/notify_ghosts(var/message, var/ghost_sound = null, var/enter_link = null, var/atom/source = null, var/image/alert_overlay = null, var/attack_not_jump = 0) //Easy notification of ghosts.
/proc/notify_ghosts(var/message, var/ghost_sound = null, var/enter_link = null, var/atom/source = null, var/image/alert_overlay = null, var/action = NOTIFY_JUMP) //Easy notification of ghosts.
for(var/mob/dead/observer/O in player_list)
if(O.client)
to_chat(O, "<span class='ghostalert'>[message][(enter_link) ? " [enter_link]" : ""]<span>")
if(ghost_sound)
O << sound(ghost_sound)
if(source)
var/obj/screen/alert/notify_jump/A = O.throw_alert("\ref[source]_notify_jump", /obj/screen/alert/notify_jump)
var/obj/screen/alert/notify_action/A = O.throw_alert("\ref[source]_notify_action", /obj/screen/alert/notify_action)
if(A)
if(O.client.prefs && O.client.prefs.UI_style)
A.icon = ui_style2icon(O.client.prefs.UI_style)
A.desc = message
A.attack_not_jump = attack_not_jump
A.jump_target = source
A.action = action
A.target = source
if(!alert_overlay)
var/old_layer = source.layer
var/old_plane = source.plane

View File

@@ -19,8 +19,6 @@ and reset all of its vars to their default
You can override your object's destroy to return QDEL_HINT_PUTINPOOL
to ensure its always placed in this pool (this will only be acted on if qdel calls destroy, and destroy will not get called twice)
For almost all pooling purposes, it is better to use the QDEL hint than to pool it directly with PlaceInPool
*/
var/global/list/GlobalPool = list()
@@ -36,7 +34,7 @@ var/global/list/GlobalPool = list()
//Or a list of arguments
//Either way it gets passed to new
/proc/PoolOrNew(get_type,second_arg)
/proc/PoolOrNew(var/get_type,var/second_arg)
if(!get_type)
return
@@ -50,7 +48,7 @@ var/global/list/GlobalPool = list()
. = new get_type (second_arg)
/proc/GetFromPool(get_type,second_arg)
/proc/GetFromPool(var/get_type,var/second_arg)
if(!get_type)
return
@@ -62,6 +60,8 @@ var/global/list/GlobalPool = list()
var/datum/pooled = pop(GlobalPool[get_type])
if(pooled)
pooled.gcDestroyed = null
var/atom/movable/AM
if(istype(pooled, /atom/movable))
AM = pooled
@@ -79,7 +79,7 @@ var/global/list/GlobalPool = list()
return pooled
/proc/PlaceInPool(datum/diver, destroy = 1)
/proc/PlaceInPool(var/datum/diver, destroy = 1)
if(!istype(diver))
return
@@ -94,9 +94,11 @@ var/global/list/GlobalPool = list()
if (destroy)
diver.Destroy()
diver.gcDestroyed = 1
diver.ResetVars()
var/list/exclude = list("animate_movement", "contents", "loc", "locs", "parent_type", "vars", "verbs", "type")
var/list/exclude = list("animate_movement", "contents", "loc", "locs", "parent_type", "vars", "verbs", "type", "gc_destroyed")
var/list/pooledvariables = list()
//thanks to clusterfack @ /vg/station for these two procs
/datum/proc/createVariables()
@@ -106,6 +108,9 @@ var/list/pooledvariables = list()
for(var/key in vars)
if(key in exclude)
continue
if(islist(vars[key]))
pooledvariables[type][key] = list()
else
pooledvariables[type][key] = initial(vars[key])
/datum/proc/ResetVars()
@@ -113,6 +118,9 @@ var/list/pooledvariables = list()
createVariables(args)
for(var/key in pooledvariables[type])
if (islist(pooledvariables[type][key]))
vars[key] = list()
else
vars[key] = pooledvariables[type][key]
/atom/movable/ResetVars()

View File

@@ -30,7 +30,7 @@
var/area/A = get_area(src)
if(A)
var/image/alert_overlay = image('icons/effects/effects.dmi', "ghostalertsie")
notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.", source = src, alert_overlay = alert_overlay, attack_not_jump = 1)
notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.", source = src, alert_overlay = alert_overlay, action=NOTIFY_ATTACK)
narsie_spawn_animation()

View File

@@ -37,6 +37,7 @@
src.energy = starting_energy
..()
processing_objects.Add(src)
poi_list |= src
for(var/obj/machinery/power/singularity_beacon/singubeacon in world)
if(singubeacon.active)
target = singubeacon
@@ -45,6 +46,7 @@
/obj/singularity/Destroy()
processing_objects.Remove(src)
poi_list.Remove(src)
singularities -= src
target = null
return ..()

View File

@@ -64,6 +64,7 @@
/obj/machinery/power/supermatter_shard/New()
. = ..()
poi_list |= src
radio = new(src)
radio.listening = 0
investigate_log("has been created.", "supermatter")
@@ -71,8 +72,10 @@
/obj/machinery/power/supermatter_shard/Destroy()
investigate_log("has been destroyed.", "supermatter")
if(radio)
qdel(radio)
radio = null
poi_list.Remove(src)
return ..()
/obj/machinery/power/supermatter_shard/proc/explode()

View File

@@ -35,6 +35,8 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
var/energy_to_raise = 32
var/energy_to_lower = -20
/obj/singularity/energy_ball/Destroy()
if(orbiting && istype(orbiting, /obj/singularity/energy_ball))
var/obj/singularity/energy_ball/EB = orbiting
@@ -45,6 +47,8 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
var/obj/singularity/energy_ball/EB = ball
qdel(EB)
poi_list.Remove(src)
return ..()
/obj/singularity/energy_ball/process()
@@ -125,6 +129,7 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
/obj/singularity/energy_ball/orbit(obj/singularity/energy_ball/target)
if(istype(target))
target.orbiting_balls += src
poi_list.Remove(src)
. = ..()

View File

@@ -8,6 +8,7 @@
ammo_type = /obj/item/ammo_casing/magic/change
icon_state = "staffofchange"
item_state = "staffofchange"
fire_sound = "sound/magic/Staff_Change.ogg"
/obj/item/weapon/gun/magic/staff/animate
name = "staff of animation"
@@ -15,6 +16,7 @@
ammo_type = /obj/item/ammo_casing/magic/animate
icon_state = "staffofanimation"
item_state = "staffofanimation"
fire_sound = "sound/magic/Staff_animation.ogg"
/obj/item/weapon/gun/magic/staff/healing
name = "staff of healing"
@@ -22,6 +24,7 @@
ammo_type = /obj/item/ammo_casing/magic/heal
icon_state = "staffofhealing"
item_state = "staffofhealing"
fire_sound = "sound/magic/Staff_Healing.ogg"
/obj/item/weapon/gun/magic/staff/healing/handle_suicide() //Stops people trying to commit suicide to heal themselves
return
@@ -35,6 +38,7 @@
max_charges = 10
recharge_rate = 2
no_den_usage = 1
fire_sound = "sound/magic/Staff_Chaos.ogg"
/obj/item/weapon/gun/magic/staff/door
name = "staff of door creation"
@@ -45,16 +49,17 @@
max_charges = 10
recharge_rate = 2
no_den_usage = 1
fire_sound = "sound/magic/Staff_Door.ogg"
/obj/item/weapon/gun/magic/staff/honk
name = "staff of the honkmother"
desc = "Honk"
fire_sound = "sound/items/airhorn.ogg"
ammo_type = /obj/item/ammo_casing/magic/honk
icon_state = "honker"
item_state = "honker"
max_charges = 4
recharge_rate = 8
fire_sound = "sound/items/airhorn.ogg"
/obj/item/weapon/gun/magic/staff/focus
name = "mental focus"

View File

@@ -59,6 +59,7 @@
/obj/item/weapon/gun/magic/wand/death
name = "wand of death"
desc = "This deadly wand overwhelms the victim's body with pure energy, slaying them without fail."
fire_sound = "sound/magic/WandoDeath.ogg"
ammo_type = /obj/item/ammo_casing/magic/death
icon_state = "deathwand"
max_charges = 3 //3, 2, 2, 1
@@ -79,6 +80,7 @@
name = "wand of resurrection"
desc = "This wand uses healing magics to heal and revive. They are rarely utilized within the Wizard Federation for some reason."
ammo_type = /obj/item/ammo_casing/magic/heal
fire_sound = "sound/magic/Staff_Healing.ogg"
icon_state = "revivewand"
max_charges = 3 //3, 2, 2, 1
@@ -96,6 +98,7 @@
name = "wand of polymorph"
desc = "This wand is attuned to chaos and will radically alter the victim's form."
ammo_type = /obj/item/ammo_casing/magic/change
fire_sound = "sound/magic/Staff_Change.ogg"
icon_state = "polywand"
max_charges = 10 //10, 5, 5, 4
@@ -115,6 +118,7 @@
icon_state = "telewand"
max_charges = 10 //10, 5, 5, 4
no_den_usage = 1
fire_sound = "sound/magic/Wand_Teleport.ogg"
/obj/item/weapon/gun/magic/wand/teleport/zap_self(mob/living/user)
do_teleport(user, user, 10)
@@ -132,6 +136,7 @@
name = "wand of door creation"
desc = "This particular wand can create doors in any wall for the unscrupulous wizard who shuns teleportation magics."
ammo_type = /obj/item/ammo_casing/magic/door
fire_sound = "sound/magic/Staff_Door.ogg"
icon_state = "doorwand"
max_charges = 20 //20, 10, 10, 7
@@ -147,6 +152,7 @@
/obj/item/weapon/gun/magic/wand/fireball
name = "wand of fireball"
desc = "This wand shoots scorching balls of fire that explode into destructive flames."
fire_sound = "sound/magic/Fireball.ogg"
ammo_type = /obj/item/ammo_casing/magic/fireball
icon_state = "firewand"
max_charges = 8 //8, 4, 4, 3

View File

@@ -9,45 +9,39 @@
vehicle_move_delay = 1
var/static/image/atvcover = null
/obj/vehicle/atv/New()
..()
if(!atvcover)
atvcover = image("icons/vehicles/4wheeler.dmi", "4wheeler_north")
atvcover.layer = MOB_LAYER + 0.1
obj/vehicle/atv/post_buckle_mob(mob/living/M)
/obj/vehicle/atv/post_buckle_mob(mob/living/M)
if(buckled_mob)
overlays += atvcover
else
overlays -= atvcover
/obj/vehicle/atv/handle_vehicle_layer()
if(dir == SOUTH)
layer = MOB_LAYER+0.1
else
layer = OBJ_LAYER
//TURRETS!
/obj/vehicle/atv/turret
var/obj/machinery/gun_turret/vehicle_turret/turret = null
var/obj/machinery/porta_turret/syndicate/vehicle_turret/turret = null
/obj/machinery/gun_turret/vehicle_turret
/obj/machinery/porta_turret/syndicate/vehicle_turret
name = "mounted turret"
scan_range = 7
emp_vulnerable = 1
density = 0
/obj/vehicle/atv/turret/New()
..()
turret = new(loc)
//turret.base = src
/obj/vehicle/atv/turret/handle_vehicle_layer()
if(dir == SOUTH)
layer = MOB_LAYER+0.1
@@ -60,7 +54,6 @@ obj/vehicle/atv/post_buckle_mob(mob/living/M)
else
turret.layer = OBJ_LAYER
/obj/vehicle/atv/turret/handle_vehicle_offsets()
..()
if(turret)

View File

@@ -309,3 +309,10 @@ DISABLE_SPACE_RUINS
# and still qualify for re-entering the round. Defaults to 30.
# Setting this to 0 will disable the penalty period
#ROUND_ABANDON_PENALTY_PERIOD 30
## Hub address for tracking stats
## example: Hubmakerckey.Hubname
#MEDAL_HUB_ADDRESS
## Password for the hub page
#MEDAL_HUB_PASSWORD

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 59 KiB

BIN
icons/turf/floors/ash.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -539,7 +539,6 @@
#include "code\game\machinery\transformer.dm"
#include "code\game\machinery\turntable.dm"
#include "code\game\machinery\turret_control.dm"
#include "code\game\machinery\turrets.dm"
#include "code\game\machinery\vending.dm"
#include "code\game\machinery\washing_machine.dm"
#include "code\game\machinery\wishgranter.dm"
@@ -1418,6 +1417,8 @@
#include "code\modules\mining\laborcamp\laborminerals.dm"
#include "code\modules\mining\laborcamp\laborshuttle.dm"
#include "code\modules\mining\laborcamp\laborstacker.dm"
#include "code\modules\mining\lavaland\ash_flora.dm"
#include "code\modules\mining\lavaland\necropolis_chests.dm"
#include "code\modules\mob\abilities.dm"
#include "code\modules\mob\death.dm"
#include "code\modules\mob\emote.dm"
@@ -1654,6 +1655,8 @@
#include "code\modules\mob\living\simple_animal\hostile\syndicate.dm"
#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
#include "code\modules\mob\living\simple_animal\hostile\winter_mobs.dm"
#include "code\modules\mob\living\simple_animal\hostile\megafauna\dragon.dm"
#include "code\modules\mob\living\simple_animal\hostile\megafauna\megafauna.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\clown.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\drone.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\fish.dm"

BIN
sound/magic/Blind.ogg Normal file

Binary file not shown.

BIN
sound/magic/CastSummon.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
sound/magic/Fireball.ogg Normal file

Binary file not shown.

BIN
sound/magic/ForceWall.ogg Normal file

Binary file not shown.

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