fixes some amtag bugs (#19032)

* new

* 2

* e²

* e³

* e£

* glang

* e¢

* e¬

* e

* e12
This commit is contained in:
tattax
2023-05-29 01:11:26 -03:00
committed by GitHub
parent 0605c0e634
commit 169d32074e
51 changed files with 430 additions and 388 deletions

View File

@@ -0,0 +1,15 @@
/// Heretic signals
/// From /obj/item/melee/touch_attack/mansus_fist/on_mob_hit : (mob/living/source, mob/living/target)
#define COMSIG_HERETIC_MANSUS_GRASP_ATTACK "mansus_grasp_attack"
/// Default behavior is to use the hand, so return this to blocks the mansus fist from being consumed after use.
#define COMPONENT_BLOCK_HAND_USE (1<<0)
/// From /obj/item/melee/touch_attack/mansus_fist/afterattack_secondary : (mob/living/source, atom/target)
#define COMSIG_HERETIC_MANSUS_GRASP_ATTACK_SECONDARY "mansus_grasp_attack_secondary"
/// Default behavior is to continue attack chain and do nothing else, so return this to use up the hand after use.
#define COMPONENT_USE_HAND (1<<0)
/// From /obj/item/melee/sickly_blade/afterattack (with proximity) : (mob/living/source, mob/living/target)
#define COMSIG_HERETIC_BLADE_ATTACK "blade_attack"
/// From /obj/item/melee/sickly_blade/afterattack (without proximity) : (mob/living/source, mob/living/target)
#define COMSIG_HERETIC_RANGED_BLADE_ATTACK "ranged_blade_attack"

View File

@@ -124,8 +124,8 @@
//Middle right (status indicators) //Middle right (status indicators)
#define ui_healthdoll "EAST-1:28,CENTER-2:13" #define ui_healthdoll "EAST-1:28,CENTER-2:13"
#define ui_health "EAST-1:28,CENTER-1:15" #define ui_health "EAST-1:28,CENTER-1:15"
#define ui_internal "EAST-1:28,CENTER:17" #define ui_internal "EAST-1:28,CENTER+1:17"
#define ui_mood "EAST-1:28,CENTER-4:10" #define ui_mood "EAST-1:28,CENTER:17"
#define ui_stamina "EAST-1:28,CENTER-3:10" #define ui_stamina "EAST-1:28,CENTER-3:10"
//living //living
@@ -208,7 +208,7 @@
//Ghosts //Ghosts
#define ui_ghost_jumptomob "SOUTH:6,CENTER-3:24" #define ui_ghost_jump_to_mob "SOUTH:6,CENTER-3:24"
#define ui_ghost_orbit "SOUTH:6,CENTER-2:24" #define ui_ghost_orbit "SOUTH:6,CENTER-2:24"
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24" #define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24"
#define ui_ghost_teleport "SOUTH:6,CENTER:24" #define ui_ghost_teleport "SOUTH:6,CENTER:24"

View File

@@ -31,19 +31,37 @@
#define LIBCALL call_ext #define LIBCALL call_ext
#endif #endif
// So we want to have compile time guarantees these procs exist on local type, unfortunately 515 killed the .proc/procname syntax so we have to use nameof() // So we want to have compile time guarantees these methods exist on local type, unfortunately 515 killed the .proc/procname and .verb/verbname syntax so we have to use nameof()
// For the record: GLOBAL_VERB_REF would be useless as verbs can't be global.
#if DM_VERSION < 515 #if DM_VERSION < 515
/// Call by name proc reference, checks if the proc exists on this type or as a global proc /// Call by name proc reference, checks if the proc exists on this type or as a global proc
#define PROC_REF(X) (.proc/##X) #define PROC_REF(X) (.proc/##X)
/// Call by name verb references, checks if the verb exists on either this type or as a global verb.
#define VERB_REF(X) (.verb/##X)
/// Call by name proc reference, checks if the proc exists on given type or as a global proc /// Call by name proc reference, checks if the proc exists on given type or as a global proc
#define TYPE_PROC_REF(TYPE, X) (##TYPE.proc/##X) #define TYPE_PROC_REF(TYPE, X) (##TYPE.proc/##X)
/// Call by name verb reference, checks if the verb exists on either the given type or as a global verb
#define TYPE_VERB_REF(TYPE, X) (##TYPE.verb/##X)
/// Call by name proc reference, checks if the proc is existing global proc /// Call by name proc reference, checks if the proc is existing global proc
#define GLOBAL_PROC_REF(X) (/proc/##X) #define GLOBAL_PROC_REF(X) (/proc/##X)
#else #else
/// Call by name proc reference, checks if the proc exists on this type or as a global proc
/// Call by name proc references, checks if the proc exists on either this type or as a global proc.
#define PROC_REF(X) (nameof(.proc/##X)) #define PROC_REF(X) (nameof(.proc/##X))
/// Call by name proc reference, checks if the proc exists on given type or as a global proc /// Call by name verb references, checks if the verb exists on either this type or as a global verb.
#define VERB_REF(X) (nameof(.verb/##X))
/// Call by name proc reference, checks if the proc exists on either the given type or as a global proc
#define TYPE_PROC_REF(TYPE, X) (nameof(##TYPE.proc/##X)) #define TYPE_PROC_REF(TYPE, X) (nameof(##TYPE.proc/##X))
/// Call by name proc reference, checks if the proc is existing global proc /// Call by name verb reference, checks if the verb exists on either the given type or as a global verb
#define TYPE_VERB_REF(TYPE, X) (nameof(##TYPE.verb/##X))
/// Call by name proc reference, checks if the proc is an existing global proc
#define GLOBAL_PROC_REF(X) (/proc/##X) #define GLOBAL_PROC_REF(X) (/proc/##X)
#endif #endif

View File

@@ -4,13 +4,13 @@
/atom/movable/screen/ghost/MouseEntered() /atom/movable/screen/ghost/MouseEntered()
flick(icon_state + "_anim", src) flick(icon_state + "_anim", src)
/atom/movable/screen/ghost/jumptomob /atom/movable/screen/ghost/jump_to_mob
name = "Jump to mob" name = "Jump to mob"
icon_state = "jumptomob" icon_state = "jump_to_mob"
/atom/movable/screen/ghost/jumptomob/Click() /atom/movable/screen/ghost/jump_to_mob/Click()
var/mob/dead/observer/G = usr var/mob/dead/observer/G = usr
G.jumptomob() G.jump_to_mob()
/atom/movable/screen/ghost/orbit /atom/movable/screen/ghost/orbit
name = "Orbit" name = "Orbit"
@@ -48,8 +48,8 @@
..() ..()
var/atom/movable/screen/using var/atom/movable/screen/using
using = new /atom/movable/screen/ghost/jumptomob() using = new /atom/movable/screen/ghost/jump_to_mob()
using.screen_loc = ui_ghost_jumptomob using.screen_loc = ui_ghost_jump_to_mob
static_inventory += using static_inventory += using
using = new /atom/movable/screen/ghost/orbit() using = new /atom/movable/screen/ghost/orbit()

View File

@@ -61,7 +61,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
var/atom/movable/screen/healths var/atom/movable/screen/healths
var/atom/movable/screen/healthdoll var/atom/movable/screen/healthdoll
var/atom/movable/screen/internals
var/atom/movable/screen/stamina var/atom/movable/screen/stamina
// subtypes can override this to force a specific UI style // subtypes can override this to force a specific UI style
@@ -115,7 +114,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
healths = null healths = null
stamina = null stamina = null
healthdoll = null healthdoll = null
internals = null
devilsouldisplay = null devilsouldisplay = null
blobpwrdisplay = null blobpwrdisplay = null
alien_plasma_display = null alien_plasma_display = null

View File

@@ -276,9 +276,6 @@
rest_icon.screen_loc = ui_above_movement rest_icon.screen_loc = ui_above_movement
static_inventory += rest_icon static_inventory += rest_icon
internals = new /atom/movable/screen/internals()
infodisplay += internals
healths = new /atom/movable/screen/healths() healths = new /atom/movable/screen/healths()
infodisplay += healths infodisplay += healths

View File

@@ -78,9 +78,6 @@
throw_icon.screen_loc = ui_drop_throw throw_icon.screen_loc = ui_drop_throw
hotkeybuttons += throw_icon hotkeybuttons += throw_icon
internals = new /atom/movable/screen/internals()
infodisplay += internals
healths = new /atom/movable/screen/healths() healths = new /atom/movable/screen/healths()
infodisplay += healths infodisplay += healths

View File

@@ -324,59 +324,6 @@
icon = 'icons/mob/screen_cyborg.dmi' icon = 'icons/mob/screen_cyborg.dmi'
screen_loc = ui_borg_intents screen_loc = ui_borg_intents
/atom/movable/screen/internals
name = "toggle internals"
icon_state = "internal0"
screen_loc = ui_internal
/atom/movable/screen/internals/Click()
if(!iscarbon(usr))
return
var/mob/living/carbon/C = usr
if(C.incapacitated())
return
if(C.internal)
C.close_internals()
to_chat(C, span_notice("You are no longer running on internals."))
icon_state = "internal0"
else
if (!C.can_breathe_internals())
to_chat(C, span_warning("You are not wearing a suitable internals mask!"))
return
var/obj/item/I = C.is_holding_item_of_type(/obj/item/tank)
if(I)
to_chat(C, span_notice("You are now running on internals from [I] in your [C.get_held_index_name(C.get_held_index_of_item(I))]."))
C.open_internals(I)
else if(ishuman(C))
var/mob/living/carbon/human/H = C
if(istype(H.s_store, /obj/item/tank))
to_chat(H, span_notice("You are now running on internals from [H.s_store] on your [H.wear_suit.name]."))
H.open_internals(H.s_store)
else if(istype(H.belt, /obj/item/tank))
to_chat(H, span_notice("You are now running on internals from [H.belt] on your belt."))
H.open_internals(H.belt)
else if(istype(H.l_store, /obj/item/tank))
to_chat(H, span_notice("You are now running on internals from [H.l_store] in your left pocket."))
H.open_internals(H.l_store)
else if(istype(H.r_store, /obj/item/tank))
to_chat(H, span_notice("You are now running on internals from [H.r_store] in your right pocket."))
H.open_internals(H.r_store)
//Separate so CO2 jetpacks are a little less cumbersome.
if(!C.internal && istype(C.back, /obj/item/tank))
to_chat(C, span_notice("You are now running on internals from [C.back] on your back."))
C.open_internals(C.back)
if(C.internal)
icon_state = "internal1"
else
to_chat(C, span_warning("You don't have a suitable tank!"))
return
C.update_mob_action_buttons()
/atom/movable/screen/mov_intent /atom/movable/screen/mov_intent
name = "run/walk toggle" name = "run/walk toggle"
icon = 'icons/mob/screen_midnight.dmi' icon = 'icons/mob/screen_midnight.dmi'

View File

@@ -55,7 +55,7 @@
RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE) RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE)
if(isatom(target)) if(isatom(target))
RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, PROC_REF(update_status_on_signal)) RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, PROC_REF(on_target_icon_update))
if(istype(target, /datum/mind)) if(istype(target, /datum/mind))
RegisterSignal(target, COMSIG_MIND_TRANSFERRED, PROC_REF(on_target_mind_swapped)) RegisterSignal(target, COMSIG_MIND_TRANSFERRED, PROC_REF(on_target_mind_swapped))

View File

@@ -8,19 +8,6 @@
return FALSE return FALSE
return ..() return ..()
/datum/action/item_action/clock/toggle_visor
name = "Create Judicial Marker"
desc = "Allows you to create a stunning Judicial Marker at any location in view. Click again to disable."
/datum/action/item_action/clock/toggle_visor/IsAvailable(feedback = FALSE)
if(!is_servant_of_ratvar(owner))
return FALSE
if(istype(target, /obj/item/clothing/glasses/judicial_visor))
var/obj/item/clothing/glasses/judicial_visor/visor = target
if(visor.recharging)
return FALSE
return ..()
/datum/action/item_action/clock/hierophant /datum/action/item_action/clock/hierophant
name = "Hierophant Network" name = "Hierophant Network"
desc = "Lets you discreetly talk with all other servants. Nearby listeners can hear you whispering, so make sure to do this privately." desc = "Lets you discreetly talk with all other servants. Nearby listeners can hear you whispering, so make sure to do this privately."

View File

@@ -173,11 +173,13 @@
var/icon/I = icon(host_mob.icon, host_mob.icon_state, host_mob.dir) var/icon/I = icon(host_mob.icon, host_mob.icon_state, host_mob.dir)
holder.pixel_y = I.Height() - world.icon_size holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = null holder.icon_state = null
host_mob.set_hud_image_inactive(DIAG_NANITE_FULL_HUD)
if(remove || stealth) if(remove || stealth)
return //bye icon return //bye icon
var/nanite_percent = (nanite_volume / max_nanites) * 100 var/nanite_percent = (nanite_volume / max_nanites) * 100
nanite_percent = clamp(CEILING(nanite_percent, 10), 10, 100) nanite_percent = clamp(CEILING(nanite_percent, 10), 10, 100)
holder.icon_state = "nanites[nanite_percent]" holder.icon_state = "nanites[nanite_percent]"
host_mob.set_hud_image_active(DIAG_NANITE_FULL_HUD)
/datum/component/nanites/proc/on_emp(datum/source, severity) /datum/component/nanites/proc/on_emp(datum/source, severity)
var/datum/component/empprotection/empproof = host_mob.GetExactComponent(/datum/component/empprotection) var/datum/component/empprotection/empproof = host_mob.GetExactComponent(/datum/component/empprotection)

View File

@@ -32,6 +32,7 @@
name = "Cryobeam" name = "Cryobeam"
desc = "This power fires a frozen bolt at a target." desc = "This power fires a frozen bolt at a target."
button_icon_state = "icebeam" button_icon_state = "icebeam"
active_icon_state = "icebeam_active"
base_icon_state = "icebeam" base_icon_state = "icebeam"
active_overlay_icon_state = "bg_spell_border_active_blue" active_overlay_icon_state = "bg_spell_border_active_blue"
cooldown_time = 16 SECONDS cooldown_time = 16 SECONDS

View File

@@ -26,7 +26,7 @@
/datum/action/cooldown/spell/cone/staggered/fire_breath /datum/action/cooldown/spell/cone/staggered/fire_breath
name = "Fire Breath" name = "Fire Breath"
desc = "You breathe a cone of fire directly in front of you." desc = "You breathe a cone of fire directly in front of you."
button_icon_state = "fireball0" button_icon_state = "fireball"
sound = 'sound/magic/demon_dies.ogg' //horrifying lizard noises sound = 'sound/magic/demon_dies.ogg' //horrifying lizard noises
school = SCHOOL_EVOCATION school = SCHOOL_EVOCATION

View File

@@ -1390,7 +1390,6 @@
* Override this if you want custom behaviour in whatever gets hit by the rust * Override this if you want custom behaviour in whatever gets hit by the rust
*/ */
/atom/proc/rust_heretic_act() /atom/proc/rust_heretic_act()
return
/** /**
* Used to set something as 'open' if it's being used as a supplypod * Used to set something as 'open' if it's being used as a supplypod

View File

@@ -18,7 +18,7 @@
/datum/atom_hud/data /datum/atom_hud/data
/datum/atom_hud/data/human/medical /datum/atom_hud/data/human/medical
hud_icons = list(STATUS_HUD, HEALTH_HUD) hud_icons = list(STATUS_HUD, HEALTH_HUD, NANITE_HUD)
/datum/atom_hud/data/human/medical/basic /datum/atom_hud/data/human/medical/basic
@@ -55,10 +55,10 @@
/datum/atom_hud/data/diagnostic /datum/atom_hud/data/diagnostic
/datum/atom_hud/data/diagnostic/basic /datum/atom_hud/data/diagnostic/basic
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD) hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD, DIAG_NANITE_FULL_HUD)
/datum/atom_hud/data/diagnostic/advanced /datum/atom_hud/data/diagnostic/advanced
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD, DIAG_PATH_HUD) hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD, DIAG_PATH_HUD, DIAG_NANITE_FULL_HUD)
/datum/atom_hud/data/bot_path /datum/atom_hud/data/bot_path
// This hud exists so the bot can see itself, that's all // This hud exists so the bot can see itself, that's all
@@ -248,7 +248,6 @@ Security HUDs! Basic mode shows only the job.
set_hud_image_inactive(WANTED_HUD) set_hud_image_inactive(WANTED_HUD)
return return
var/datum/data/record/target = find_record("name", perp_name, GLOB.data_core.security) var/datum/data/record/target = find_record("name", perp_name, GLOB.data_core.security)
if(!target || target.fields["criminal"] == WANTED_NONE) if(!target || target.fields["criminal"] == WANTED_NONE)
holder.icon_state = null holder.icon_state = null
@@ -278,8 +277,10 @@ Diagnostic HUDs!
var/icon/I = icon(icon, icon_state, dir) var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = null holder.icon_state = null
set_hud_image_inactive(NANITE_HUD)
if(src in SSnanites.nanite_monitored_mobs) if(src in SSnanites.nanite_monitored_mobs)
holder.icon_state = "nanite_ping" holder.icon_state = "nanite_ping"
set_hud_image_active(NANITE_HUD)
//For Diag health and cell bars! //For Diag health and cell bars!
/proc/RoundDiagBar(value) /proc/RoundDiagBar(value)

View File

@@ -332,6 +332,7 @@
if(QDELETED(target) || !(ishuman(owner) || iscyborg(owner)) || !owner.canUseTopic(target)) if(QDELETED(target) || !(ishuman(owner) || iscyborg(owner)) || !owner.canUseTopic(target))
return return
if(!GLOB.servants_active) //No leaving unless there's servants from the get-go if(!GLOB.servants_active) //No leaving unless there's servants from the get-go
to_chat(owner, "[span_sevtug_small("The Ark doesn't let you leave!")]")
return return
if(warping) if(warping)
cancel = TRUE cancel = TRUE

View File

@@ -61,7 +61,7 @@ GLOBAL_PROTECT(admin_verbs_admin)
// /client/proc/sendmob, /*sends a mob somewhere*/ -Removed due to it needing two sorting procs to work, which were executed every time an admin right-clicked. ~Errorage // /client/proc/sendmob, /*sends a mob somewhere*/ -Removed due to it needing two sorting procs to work, which were executed every time an admin right-clicked. ~Errorage
/client/proc/jumptoarea, /client/proc/jumptoarea,
/client/proc/jumptokey, /*allows us to jump to the location of a mob with a certain ckey*/ /client/proc/jumptokey, /*allows us to jump to the location of a mob with a certain ckey*/
/client/proc/jumptomob, /*allows us to jump to a specific mob*/ /client/proc/jump_to_mob, /*allows us to jump to a specific mob*/
/client/proc/jumptoturf, /*allows us to jump to a specific turf*/ /client/proc/jumptoturf, /*allows us to jump to a specific turf*/
/client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/ /client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/
/client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcom*/ /client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcom*/

View File

@@ -1457,7 +1457,7 @@
return return
var/mob/M = locate(href_list["jumpto"]) var/mob/M = locate(href_list["jumpto"])
usr.client.jumptomob(M) usr.client.jump_to_mob(M)
else if(href_list["getmob"]) else if(href_list["getmob"])
if(!check_rights(R_ADMIN)) if(!check_rights(R_ADMIN))

View File

@@ -37,7 +37,7 @@
SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Turf") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Turf") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return return
/client/proc/jumptomob(mob/M in GLOB.mob_list) /client/proc/jump_to_mob(mob/M in GLOB.mob_list)
set category = "Admin" set category = "Admin"
set name = "Jump to Mob" set name = "Jump to Mob"

View File

@@ -1,7 +1,4 @@
/datum/antagonist/bloodsucker/proc/assign_clan_and_bane(tzimisce = FALSE) /datum/antagonist/bloodsucker/proc/assign_clan_and_bane()
if(tzimisce)
my_clan = new /datum/bloodsucker_clan/tzimisce(owner.current)
return
if(my_clan) if(my_clan)
return return
var/list/options = list() var/list/options = list()

View File

@@ -13,11 +13,6 @@
/datum/action/innate/slab/IsAvailable(feedback = FALSE) /datum/action/innate/slab/IsAvailable(feedback = FALSE)
return TRUE return TRUE
/datum/action/innate/slab/unset_ranged_ability(mob/living/on_who)
. = ..()
finished = TRUE
QDEL_IN(src, 1 SECONDS)
/datum/action/innate/slab/InterceptClickOn(mob/living/caller, params, atom/clicked_on) /datum/action/innate/slab/InterceptClickOn(mob/living/caller, params, atom/clicked_on)
if(in_progress) if(in_progress)
return FALSE return FALSE
@@ -26,8 +21,15 @@
return FALSE return FALSE
. = ..() . = ..()
if(.) if(!.)
unset_ranged_ability(caller || usr) return FALSE
var/mob/living/i_hate_this = caller || owner || usr
i_hate_this?.client?.mouse_override_icon = initial(caller?.client?.mouse_override_icon)
i_hate_this?.update_mouse_pointer()
i_hate_this?.click_intercept = null
finished = TRUE
QDEL_IN(src, 0.1 SECONDS)
return TRUE
//For the Hateful Manacles scripture; applies replicant handcuffs to the clicked_on. //For the Hateful Manacles scripture; applies replicant handcuffs to the clicked_on.
/datum/action/innate/slab/hateful_manacles /datum/action/innate/slab/hateful_manacles
@@ -242,7 +244,7 @@
//For the cyborg Judicial Marker scripture, places a judicial marker //For the cyborg Judicial Marker scripture, places a judicial marker
/datum/action/innate/slab/judicial /datum/action/innate/slab/judicial
ranged_mousepointer = 'icons/effects/visor_reticule.dmi' ranged_mousepointer = 'icons/effects/mouse_pointers/visor_reticule.dmi'
/datum/action/innate/slab/judicial/do_ability(mob/living/caller, params, atom/clicked_on) /datum/action/innate/slab/judicial/do_ability(mob/living/caller, params, atom/clicked_on)
var/turf/T = caller.loc var/turf/T = caller.loc

View File

@@ -98,13 +98,13 @@
slab_ability = null slab_ability = null
return ..() return ..()
/obj/item/clockwork/slab/dropped(mob/user) /obj/item/clockwork/slab/dropped(mob/user, slot)
. = ..() . = ..()
addtimer(CALLBACK(src, PROC_REF(check_on_mob), user), 1) //dropped is called before the item is out of the slot, so we need to check slightly later addtimer(CALLBACK(src, PROC_REF(check_on_mob), user, slot), 0.1 SECONDS) //dropped is called before the item is out of the slot, so we need to check slightly later
/obj/item/clockwork/slab/equipped(mob/user) /obj/item/clockwork/slab/equipped(mob/user, slot)
. = ..() . = ..()
update_quickbind() update_quickbind(user)
/obj/item/clockwork/slab/worn_overlays(isinhands = FALSE, icon_file) /obj/item/clockwork/slab/worn_overlays(isinhands = FALSE, icon_file)
. = list() . = list()
@@ -112,10 +112,13 @@
var/mutable_appearance/M = mutable_appearance(icon_file, "slab_[inhand_overlay]") var/mutable_appearance/M = mutable_appearance(icon_file, "slab_[inhand_overlay]")
. += M . += M
/obj/item/clockwork/slab/proc/check_on_mob(mob/user) /obj/item/clockwork/slab/proc/check_on_mob(mob/user, slot)
if(user && !(src in user.held_items) && slab_ability?.owner) //if we happen to check and we AREN'T in user's hands, remove whatever ability we have if(!user)
CRASH("No user on dropped slab.")
if(slab_ability?.owner) //if we happen to check and we AREN'T in user's hands, remove whatever ability we have
slab_ability.unset_ranged_ability(user) slab_ability.unset_ranged_ability(user)
update_quickbind(user, TRUE) if(!LAZYFIND(user.held_items, src))
update_quickbind(user, TRUE)
//Power generation //Power generation
/obj/item/clockwork/slab/process() /obj/item/clockwork/slab/process()

View File

@@ -10,14 +10,13 @@
var/active = FALSE //If the visor is online var/active = FALSE //If the visor is online
var/recharging = FALSE //If the visor is currently recharging var/recharging = FALSE //If the visor is currently recharging
var/datum/action/cooldown/judicial_visor/blaster var/datum/action/cooldown/judicial_visor/blaster
var/recharge_cooldown = 300 //divided by 10 if ratvar is alive var/recharge_cooldown = 30 SECONDS //divided by 10 if ratvar is alive
actions_types = list(/datum/action/item_action/clock/toggle_visor) actions_types = list(/datum/action/cooldown/judicial_visor)
/obj/item/clothing/glasses/judicial_visor/Initialize() /obj/item/clothing/glasses/judicial_visor/Initialize()
. = ..() . = ..()
GLOB.all_clockwork_objects += src GLOB.all_clockwork_objects += src
blaster = new(src) blaster = new(src)
blaster.visor = src
/obj/item/clothing/glasses/judicial_visor/Destroy() /obj/item/clothing/glasses/judicial_visor/Destroy()
GLOB.all_clockwork_objects -= src GLOB.all_clockwork_objects -= src
@@ -99,43 +98,54 @@
user.update_inv_glasses() user.update_inv_glasses()
/datum/action/cooldown/judicial_visor /datum/action/cooldown/judicial_visor
ranged_mousepointer = 'icons/effects/visor_reticule.dmi' name = "Create Judicial Marker"
desc = "Allows you to create a stunning Judicial Marker at any location in view. Click again to disable."
ranged_mousepointer = 'icons/effects/mouse_pointers/visor_reticule.dmi'
button_icon = 'icons/obj/clothing/clockwork_garb.dmi'
button_icon_state = "judicial_visor_1"
background_icon_state = "bg_clock"
click_to_activate = TRUE
var/judgment_range = 7
var/obj/item/clothing/glasses/judicial_visor/visor var/obj/item/clothing/glasses/judicial_visor/visor
/datum/action/cooldown/judicial_visor/InterceptClickOn(mob/living/caller, params, atom/target) /datum/action/cooldown/judicial_visor/link_to(Target)
if(!..()) . = ..()
visor = Target
/datum/action/cooldown/judicial_visor/IsAvailable(feedback = FALSE)
if(!is_servant_of_ratvar(owner))
return FALSE
if(visor.recharging)
return FALSE return FALSE
if(owner.incapacitated() || !visor || visor != owner.get_item_by_slot(SLOT_GLASSES)) if(owner.incapacitated() || !visor || visor != owner.get_item_by_slot(SLOT_GLASSES))
unset_click_ability(owner)
return FALSE return FALSE
if(!isturf(owner.loc))
var/turf/T = owner.loc
if(!isturf(T))
return FALSE return FALSE
if(target in view(7, get_turf(owner)))
visor.recharging = TRUE
visor.update_status()
for(var/obj/item/clothing/glasses/judicial_visor/V in caller.get_all_contents())
if(V == visor)
continue
V.recharging = TRUE //To prevent exploiting multiple visors to bypass the cooldown
V.update_status()
addtimer(CALLBACK(V, TYPE_PROC_REF(/obj/item/clothing/glasses/judicial_visor, recharge_visor), owner), (GLOB.ratvar_awakens ? visor.recharge_cooldown*0.1 : visor.recharge_cooldown) * 2)
clockwork_say(owner, text2ratvar("Kneel, heathens!"))
owner.visible_message(span_warning("[owner]'s judicial visor fires a stream of energy at [target], creating a strange mark!"), "[span_heavy_brass("You direct [visor]'s power to [target]. You must wait for some time before doing this again.")]")
var/turf/targetturf = get_turf(target)
new/obj/effect/clockwork/judicial_marker(targetturf, owner)
log_combat(owner, targetturf, "created a judicial marker")
owner.update_mob_action_buttons()
owner.update_inv_glasses()
addtimer(CALLBACK(visor, TYPE_PROC_REF(/obj/item/clothing/glasses/judicial_visor, recharge_visor), owner), GLOB.ratvar_awakens ? visor.recharge_cooldown*0.1 : visor.recharge_cooldown)//Cooldown is reduced by 10x if Ratvar is up
unset_click_ability(owner)
return FALSE
return TRUE return TRUE
/datum/action/cooldown/judicial_visor/Activate(atom/target_atom)
var/mob/living/living_owner = owner
if(owner && get_dist(get_turf(owner), get_turf(target_atom)) > judgment_range)
target_atom.balloon_alert(owner, "too far away!")
return
visor.recharging = TRUE
visor.update_status()
for(var/obj/item/clothing/glasses/judicial_visor/V in living_owner.get_all_contents())
if(V == visor)
continue
V.recharging = TRUE //To prevent exploiting multiple visors to bypass the cooldown
V.update_status()
addtimer(CALLBACK(V, TYPE_PROC_REF(/obj/item/clothing/glasses/judicial_visor, recharge_visor), owner), (GLOB.ratvar_awakens ? visor.recharge_cooldown*0.1 : visor.recharge_cooldown) * 2)
clockwork_say(owner, text2ratvar("Kneel, heathens!"))
owner.visible_message(span_warning("[owner]'s judicial visor fires a stream of energy at [target_atom], creating a strange mark!"), "[span_heavy_brass("You direct [visor]'s power to [target_atom]. You must wait for some time before doing this again.")]")
var/turf/target_turf = get_turf(target_atom)
new /obj/effect/clockwork/judicial_marker(target_turf, owner)
log_combat(owner, target_turf, "created a judicial marker")
owner.update_mob_action_buttons()
owner.update_inv_glasses()
addtimer(CALLBACK(visor, TYPE_PROC_REF(/obj/item/clothing/glasses/judicial_visor, recharge_visor), owner), GLOB.ratvar_awakens ? visor.recharge_cooldown*0.1 : visor.recharge_cooldown)//Cooldown is reduced by 10x if Ratvar is up
unset_click_ability(owner)
//Judicial marker: Created by the judicial visor. Immediately applies Belligerent and briefly knocks down, then after 3 seconds does large damage and briefly knocks down again //Judicial marker: Created by the judicial visor. Immediately applies Belligerent and briefly knocks down, then after 3 seconds does large damage and briefly knocks down again
/obj/effect/clockwork/judicial_marker /obj/effect/clockwork/judicial_marker
name = "judicial marker" name = "judicial marker"

View File

@@ -168,6 +168,8 @@
/datum/antagonist/clockcult/on_removal() /datum/antagonist/clockcult/on_removal()
SSticker.mode.servants_of_ratvar -= owner SSticker.mode.servants_of_ratvar -= owner
for(var/datum/action/item_action/clock/quickbind/existing_binds in owner.current.actions)
existing_binds.Remove(owner.current) //regenerate all our quickbound scriptures
if(!silent) if(!silent)
owner.current.visible_message("[span_deconversion_message("[owner.current] seems to have remembered [owner.current.p_their()] true allegiance!")]", null, null, null, owner.current) owner.current.visible_message("[span_deconversion_message("[owner.current] seems to have remembered [owner.current.p_their()] true allegiance!")]", null, null, null, owner.current)
to_chat(owner, span_userdanger("A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.")) to_chat(owner, span_userdanger("A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant."))
@@ -175,7 +177,7 @@
owner.special_role = null owner.special_role = null
if(iscyborg(owner.current)) if(iscyborg(owner.current))
to_chat(owner.current, span_warning("Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.")) to_chat(owner.current, span_warning("Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking."))
. = ..() return ..()
/datum/antagonist/clockcult/admin_add(datum/mind/new_owner,mob/admin) /datum/antagonist/clockcult/admin_add(datum/mind/new_owner,mob/admin)

View File

@@ -11,6 +11,8 @@
shapeshift_type = /mob/living/simple_animal/lesserdemon shapeshift_type = /mob/living/simple_animal/lesserdemon
spell_requirements = NONE
/mob/living/simple_animal/lesserdemon /mob/living/simple_animal/lesserdemon
name = "demon" name = "demon"
real_name = "demon" real_name = "demon"

View File

@@ -10,6 +10,7 @@
invocation_type = INVOCATION_SHOUT invocation_type = INVOCATION_SHOUT
wall_type = /obj/effect/gluttony/timed wall_type = /obj/effect/gluttony/timed
spell_requirements = NONE
/datum/action/cooldown/spell/shapeshift/demon/gluttony //emergency get out of jail card, but better. It also eats everything. /datum/action/cooldown/spell/shapeshift/demon/gluttony //emergency get out of jail card, but better. It also eats everything.
name = "Gluttony Demon Form" name = "Gluttony Demon Form"

View File

@@ -539,9 +539,8 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
var/mob/living/silicon/robot_devil = owner.current var/mob/living/silicon/robot_devil = owner.current
var/laws = list("You may not use violence to coerce someone into selling their soul.", "You may not directly and knowingly physically harm a devil, other than yourself.", GLOB.lawlorify[LAW][ban], GLOB.lawlorify[LAW][obligation], "Accomplish your objectives at all costs.") var/laws = list("You may not use violence to coerce someone into selling their soul.", "You may not directly and knowingly physically harm a devil, other than yourself.", GLOB.lawlorify[LAW][ban], GLOB.lawlorify[LAW][obligation], "Accomplish your objectives at all costs.")
robot_devil.set_law_sixsixsix(laws) robot_devil.set_law_sixsixsix(laws)
sleep(1 SECONDS)
handle_clown_mutation(owner.current, "Your infernal nature has allowed you to overcome your clownishness.") handle_clown_mutation(owner.current, "Your infernal nature has allowed you to overcome your clownishness.")
. = ..() return ..()
/datum/antagonist/devil/on_removal() /datum/antagonist/devil/on_removal()
to_chat(owner.current, span_userdanger("Your infernal link has been severed! You are no longer a devil!")) to_chat(owner.current, span_userdanger("Your infernal link has been severed! You are no longer a devil!"))

View File

@@ -169,11 +169,9 @@ new /datum/disease_ability/symptom/powerful/heal/youth
button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "cough" button_icon_state = "cough"
desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmissibility is low.<br>Cooldown: 10 seconds" desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmissibility is low.<br>Cooldown: 10 seconds"
cooldown_time = 100 cooldown_time = 10 SECONDS
/datum/action/cooldown/disease_cough/Trigger() /datum/action/cooldown/disease_cough/Activate()
if(!..())
return FALSE
var/mob/camera/disease/D = owner var/mob/camera/disease/D = owner
var/mob/living/L = D.following_host var/mob/living/L = D.following_host
if(!L) if(!L)
@@ -187,8 +185,6 @@ new /datum/disease_ability/symptom/powerful/heal/youth
var/datum/disease/advance/sentient_disease/SD = D.hosts[L] var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
SD.spread(2) SD.spread(2)
StartCooldown() StartCooldown()
return TRUE
/datum/disease_ability/action/sneeze /datum/disease_ability/action/sneeze
name = "Voluntary Sneezing" name = "Voluntary Sneezing"
@@ -203,11 +199,9 @@ new /datum/disease_ability/symptom/powerful/heal/youth
button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "sneeze" button_icon_state = "sneeze"
desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host even if your transmissibility is low.<br>Cooldown: 20 seconds" desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host even if your transmissibility is low.<br>Cooldown: 20 seconds"
cooldown_time = 200 cooldown_time = 20 SECONDS
/datum/action/cooldown/disease_sneeze/Trigger() /datum/action/cooldown/disease_sneeze/Activate()
if(!..())
return FALSE
var/mob/camera/disease/D = owner var/mob/camera/disease/D = owner
var/mob/living/L = D.following_host var/mob/living/L = D.following_host
if(!L) if(!L)
@@ -225,7 +219,6 @@ new /datum/disease_ability/symptom/powerful/heal/youth
M.AirborneContractDisease(SD, TRUE) M.AirborneContractDisease(SD, TRUE)
StartCooldown() StartCooldown()
return TRUE
/datum/disease_ability/action/infect /datum/disease_ability/action/infect
@@ -241,11 +234,9 @@ new /datum/disease_ability/symptom/powerful/heal/youth
button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "infect" button_icon_state = "infect"
desc = "Cause the host you are following to excrete an infective substance from their pores, causing all objects touching their skin to transmit your infection to anyone who touches them for the next 30 seconds.<br>Cooldown: 40 seconds" desc = "Cause the host you are following to excrete an infective substance from their pores, causing all objects touching their skin to transmit your infection to anyone who touches them for the next 30 seconds.<br>Cooldown: 40 seconds"
cooldown_time = 400 cooldown_time = 40 SECONDS
/datum/action/cooldown/disease_infect/Trigger() /datum/action/cooldown/disease_infect/Activate()
if(!..())
return FALSE
var/mob/camera/disease/D = owner var/mob/camera/disease/D = owner
var/mob/living/carbon/human/H = D.following_host var/mob/living/carbon/human/H = D.following_host
if(!H) if(!H)
@@ -266,7 +257,6 @@ new /datum/disease_ability/symptom/powerful/heal/youth
var/obj/O = V var/obj/O = V
O.AddComponent(/datum/component/infective, D.disease_template, 300) O.AddComponent(/datum/component/infective, D.disease_template, 300)
StartCooldown() StartCooldown()
return TRUE
/*******************BASE SYMPTOM TYPES*******************/ /*******************BASE SYMPTOM TYPES*******************/

View File

@@ -41,7 +41,11 @@
* This proc is called whenever a new eldritch knowledge is added to an antag datum * This proc is called whenever a new eldritch knowledge is added to an antag datum
*/ */
/datum/eldritch_knowledge/proc/on_gain(mob/user, datum/antagonist/heretic/our_heretic) /datum/eldritch_knowledge/proc/on_gain(mob/user, datum/antagonist/heretic/our_heretic)
return var/datum/antagonist/heretic/EC = user.mind?.has_antag_datum(/datum/antagonist/heretic)
for(var/X in unlocked_transmutations)
var/datum/eldritch_transmutation/ET = new X
EC.transmutations |= ET
/** /**
* What happens when you lose this * What happens when you lose this
* *
@@ -49,6 +53,7 @@
*/ */
/datum/eldritch_knowledge/proc/on_lose(mob/user, datum/antagonist/heretic/our_heretic) /datum/eldritch_knowledge/proc/on_lose(mob/user, datum/antagonist/heretic/our_heretic)
return return
/** /**
* What happens every tick * What happens every tick
* *
@@ -82,17 +87,6 @@
var/datum/action/cooldown/spell/created_spell = created_spell_ref?.resolve() var/datum/action/cooldown/spell/created_spell = created_spell_ref?.resolve()
created_spell?.Remove(user) created_spell?.Remove(user)
/**
* Mansus grasp act
*
* Gives addtional effects to mansus grasp spell
*/
/datum/eldritch_knowledge/proc/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
return FALSE
/** /**
* Sickly blade act * Sickly blade act
* *

View File

@@ -63,28 +63,27 @@
/datum/action/cooldown/spell/touch/mansus_grasp/can_cast_spell(feedback = TRUE) /datum/action/cooldown/spell/touch/mansus_grasp/can_cast_spell(feedback = TRUE)
return ..() && !!IS_HERETIC(owner) return ..() && !!IS_HERETIC(owner)
/datum/action/cooldown/spell/touch/mansus_grasp/on_antimagic_triggered(obj/item/melee/touch_attack/hand, atom/victim, mob/living/carbon/caster)
victim.visible_message(
span_danger("The spell bounces off of [victim]!"),
span_danger("The spell bounces off of you!"),
)
/datum/action/cooldown/spell/touch/mansus_grasp/cast_on_hand_hit(obj/item/melee/touch_attack/hand, atom/victim, mob/living/carbon/caster) /datum/action/cooldown/spell/touch/mansus_grasp/cast_on_hand_hit(obj/item/melee/touch_attack/hand, atom/victim, mob/living/carbon/caster)
if(!isliving(victim)) // if(!isliving(victim)) for now, makes heretic hand hit everything but it's for the best
return FALSE
var/mob/living/living_hit = victim
if(living_hit.can_block_magic(antimagic_flags))
victim.visible_message(
span_danger("The spell bounces off of [victim]!"),
span_danger("The spell bounces off of you!"),
)
return FALSE
// if(SEND_SIGNAL(caster, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, victim) & COMPONENT_BLOCK_HAND_USE)
// return FALSE // return FALSE
living_hit.apply_damage(10, BRUTE, wound_bonus = CANT_WOUND) if(SEND_SIGNAL(caster, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, victim) & COMPONENT_BLOCK_HAND_USE)
if(iscarbon(victim)) return FALSE
var/mob/living/carbon/carbon_hit = victim
carbon_hit.adjust_timed_status_effect(4 SECONDS, /datum/status_effect/speech/slurring/heretic) if(isliving(victim))
carbon_hit.AdjustKnockdown(5 SECONDS) var/mob/living/living_hit = victim
carbon_hit.adjustStaminaLoss(80) living_hit.apply_damage(10, BRUTE, wound_bonus = CANT_WOUND)
if(iscarbon(victim))
var/mob/living/carbon/carbon_hit = victim
carbon_hit.adjust_timed_status_effect(4 SECONDS, /datum/status_effect/speech/slurring/heretic)
carbon_hit.AdjustKnockdown(5 SECONDS)
carbon_hit.adjustStaminaLoss(80)
return TRUE return TRUE
@@ -98,7 +97,7 @@
/obj/item/melee/touch_attack/mansus_fist/ignition_effect(atom/A, mob/user) /obj/item/melee/touch_attack/mansus_fist/ignition_effect(atom/A, mob/user)
. = span_notice("[user] effortlessly snaps [user.p_their()] fingers near [A], igniting it with eldritch energies. Fucking badass!") . = span_notice("[user] effortlessly snaps [user.p_their()] fingers near [A], igniting it with eldritch energies. Fucking badass!")
qdel(src) remove_hand_with_no_refund(user)
/datum/action/cooldown/spell/aoe/rust_conversion /datum/action/cooldown/spell/aoe/rust_conversion
name = "Aggressive Spread" name = "Aggressive Spread"

View File

@@ -15,17 +15,20 @@
H.physiology.heat_mod *= 0.6 H.physiology.heat_mod *= 0.6
var/obj/realknife = new /obj/item/gun/magic/hook/sickly_blade/ash var/obj/realknife = new /obj/item/gun/magic/hook/sickly_blade/ash
user.put_in_hands(realknife) user.put_in_hands(realknife)
RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp))
/datum/eldritch_knowledge/base_ash/on_lose(mob/user)
UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK)
/datum/eldritch_knowledge/base_ash/proc/on_mansus_grasp(mob/living/source, mob/living/target)
// SIGNAL_HANDLER
/datum/eldritch_knowledge/base_ash/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(!iscarbon(target)) if(!iscarbon(target))
return return
var/mob/living/carbon/C = target var/mob/living/carbon/C = target
var/atom/throw_target = get_edge_target_turf(C, user.dir) var/atom/throw_target = get_edge_target_turf(C, source.dir)
if(!C.anchored) if(!C.anchored)
. = TRUE C.throw_at(throw_target, rand(4,8), 14, source)
C.throw_at(throw_target, rand(4,8), 14, user)
return
/datum/eldritch_knowledge/base_ash/on_eldritch_blade(atom/target, mob/user, proximity_flag, click_parameters) /datum/eldritch_knowledge/base_ash/on_eldritch_blade(atom/target, mob/user, proximity_flag, click_parameters)
. = ..() . = ..()
@@ -66,10 +69,17 @@
route = PATH_ASH route = PATH_ASH
tier = TIER_MARK tier = TIER_MARK
/datum/eldritch_knowledge/ash_mark/on_mansus_grasp(atom/target,mob/user,proximity_flag,click_parameters) /datum/eldritch_knowledge/ash_mark/on_gain(mob/user)
. = ..() . = ..()
RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp))
/datum/eldritch_knowledge/ash_mark/on_lose(mob/user, datum/antagonist/heretic/our_heretic)
UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK)
/datum/eldritch_knowledge/ash_mark/proc/on_mansus_grasp(mob/living/source, mob/living/target)
SIGNAL_HANDLER
if(isliving(target)) if(isliving(target))
. = TRUE
var/mob/living/living_target = target var/mob/living/living_target = target
living_target.apply_status_effect(/datum/status_effect/eldritch/ash, 5) living_target.apply_status_effect(/datum/status_effect/eldritch/ash, 5)

View File

@@ -14,10 +14,15 @@
. = ..() . = ..()
var/obj/realknife = new /obj/item/gun/magic/hook/sickly_blade/flesh var/obj/realknife = new /obj/item/gun/magic/hook/sickly_blade/flesh
user.put_in_hands(realknife) user.put_in_hands(realknife)
RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp))
/datum/eldritch_knowledge/base_flesh/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) /datum/eldritch_knowledge/base_flesh/on_lose(mob/user, datum/antagonist/heretic/our_heretic)
. = ..() UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK)
if(!ishuman(target) || target == user)
/datum/eldritch_knowledge/base_flesh/proc/on_mansus_grasp(mob/living/source, mob/living/target)
// SIGNAL_HANDLER godammit
if(!ishuman(target) || target == source)
return return
var/mob/living/carbon/human/human_target = target var/mob/living/carbon/human/human_target = target
@@ -27,25 +32,24 @@
human_target.grab_ghost() human_target.grab_ghost()
if(!human_target.mind || !human_target.client) if(!human_target.mind || !human_target.client)
to_chat(user, span_warning("There is no soul connected to this body...")) to_chat(source, span_warning("There is no soul connected to this body..."))
return return
if(HAS_TRAIT(human_target, TRAIT_HUSK)) if(HAS_TRAIT(human_target, TRAIT_HUSK))
to_chat(user, span_warning("The body is too damaged to be revived this way!")) to_chat(source, span_warning("The body is too damaged to be revived this way!"))
return return
if(HAS_TRAIT(human_target, TRAIT_MINDSHIELD)) if(HAS_TRAIT(human_target, TRAIT_MINDSHIELD))
to_chat(user, span_warning("Their will cannot be malformed to obey your own!")) to_chat(source, span_warning("Their will cannot be malformed to obey your own!"))
return return
if(LAZYLEN(spooky_scaries) >= ghoul_amt) if(LAZYLEN(spooky_scaries) >= ghoul_amt)
to_chat(user, span_warning("Your Oath cannot support more ghouls on this plane!")) to_chat(source, span_warning("Your Oath cannot support more ghouls on this plane!"))
return return
LAZYADD(spooky_scaries, human_target) LAZYADD(spooky_scaries, human_target)
log_game("[key_name_admin(human_target)] has become a ghoul, their master is [user.real_name]") log_game("[key_name_admin(human_target)] has become a ghoul, their master is [source.real_name]")
//we change it to true only after we know they passed all the checks //we change it to true only after we know they passed all the checks
. = TRUE
RegisterSignal(human_target,COMSIG_GLOB_MOB_DEATH, PROC_REF(remove_ghoul)) RegisterSignal(human_target,COMSIG_GLOB_MOB_DEATH, PROC_REF(remove_ghoul))
human_target.revive(full_heal = TRUE, admin_revive = TRUE) human_target.revive(full_heal = TRUE, admin_revive = TRUE)
human_target.setMaxHealth(25) human_target.setMaxHealth(25)
@@ -53,9 +57,8 @@
human_target.become_husk() human_target.become_husk()
human_target.faction |= "heretics" human_target.faction |= "heretics"
var/datum/antagonist/heretic_monster/heretic_monster = human_target.mind.add_antag_datum(/datum/antagonist/heretic_monster) var/datum/antagonist/heretic_monster/heretic_monster = human_target.mind.add_antag_datum(/datum/antagonist/heretic_monster)
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic) var/datum/antagonist/heretic/master = source.mind.has_antag_datum(/datum/antagonist/heretic)
heretic_monster.set_owner(master) heretic_monster.set_owner(master)
return
/datum/eldritch_knowledge/base_flesh/proc/remove_ghoul(datum/source) /datum/eldritch_knowledge/base_flesh/proc/remove_ghoul(datum/source)
var/mob/living/carbon/human/humie = source var/mob/living/carbon/human/humie = source
@@ -95,8 +98,16 @@
route = PATH_FLESH route = PATH_FLESH
tier = TIER_MARK tier = TIER_MARK
/datum/eldritch_knowledge/flesh_mark/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) /datum/eldritch_knowledge/flesh_mark/on_gain(mob/user)
. = ..() . = ..()
RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp))
/datum/eldritch_knowledge/flesh_mark/on_lose(mob/user)
UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK)
/datum/eldritch_knowledge/flesh_mark/proc/on_mansus_grasp(mob/living/source, mob/living/target)
SIGNAL_HANDLER
if(isliving(target)) if(isliving(target))
. = TRUE . = TRUE
var/mob/living/living_target = target var/mob/living/living_target = target

View File

@@ -12,11 +12,15 @@
. = ..() . = ..()
var/obj/realknife = new /obj/item/gun/magic/hook/sickly_blade/rust var/obj/realknife = new /obj/item/gun/magic/hook/sickly_blade/rust
user.put_in_hands(realknife) user.put_in_hands(realknife)
RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp))
/datum/eldritch_knowledge/base_rust/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) /datum/eldritch_knowledge/base_rust/on_lose(mob/user)
. = ..() UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK)
if(user.a_intent == INTENT_HARM)
. = TRUE /datum/eldritch_knowledge/base_rust/proc/on_mansus_grasp(mob/living/source, atom/target)
SIGNAL_HANDLER
if(source.a_intent == INTENT_HARM)
target.rust_heretic_act() target.rust_heretic_act()
/datum/eldritch_knowledge/base_rust/on_eldritch_blade(atom/target, mob/user, proximity_flag, click_parameters) /datum/eldritch_knowledge/base_rust/on_eldritch_blade(atom/target, mob/user, proximity_flag, click_parameters)
@@ -72,9 +76,17 @@
banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark) banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark)
route = PATH_RUST route = PATH_RUST
tier = TIER_MARK tier = TIER_MARK
/datum/eldritch_knowledge/rust_mark/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) /datum/eldritch_knowledge/rust_mark/on_gain(mob/user)
. = ..() . = ..()
RegisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK, PROC_REF(on_mansus_grasp))
/datum/eldritch_knowledge/rust_mark/on_lose(mob/user)
UnregisterSignal(user, COMSIG_HERETIC_MANSUS_GRASP_ATTACK)
/datum/eldritch_knowledge/rust_mark/proc/on_mansus_grasp(mob/living/source, mob/living/target)
SIGNAL_HANDLER
if(isliving(target)) if(isliving(target))
var/mob/living/living_target = target var/mob/living/living_target = target
living_target.apply_status_effect(/datum/status_effect/eldritch/rust) living_target.apply_status_effect(/datum/status_effect/eldritch/rust)

View File

@@ -117,7 +117,7 @@
return return
Infect(C) Infect(C)
return return
..() return ..()
/mob/living/simple_animal/horror/proc/has_chemicals(amt) /mob/living/simple_animal/horror/proc/has_chemicals(amt)
return chemicals >= amt return chemicals >= amt

View File

@@ -1038,7 +1038,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
var/mob/living/M = mob var/mob/living/M = mob
M.update_damage_hud() M.update_damage_hud()
if (prefs.read_preference(/datum/preference/toggle/auto_fit_viewport)) if (prefs.read_preference(/datum/preference/toggle/auto_fit_viewport))
addtimer(CALLBACK(src,.verb/fit_viewport,10)) //Delayed to avoid wingets from Login calls. addtimer(CALLBACK(src, VERB_REF(fit_viewport), 1 SECONDS)) //Delayed to avoid wingets from Login calls.
/client/proc/generate_clickcatcher() /client/proc/generate_clickcatcher()
if(!void) if(!void)

View File

@@ -8,7 +8,7 @@
/datum/round_event_control/tzimisce/bloodsucker /datum/round_event_control/tzimisce/bloodsucker
name = "Spawn Tzimisce - Bloodsucker" name = "Spawn Tzimisce - Bloodsucker"
max_occurrences = 1 max_occurrences = 1
weight = 2000 // weight = 2000
typepath = /datum/round_event/ghost_role/tzimisce/bloodsucker typepath = /datum/round_event/ghost_role/tzimisce/bloodsucker
min_players = 25 min_players = 25
earliest_start = 30 MINUTES earliest_start = 30 MINUTES
@@ -63,7 +63,8 @@
bloodsuckerdatum.antag_hud_name = "tzimisce" bloodsuckerdatum.antag_hud_name = "tzimisce"
bloodsuckerdatum.add_team_hud(tzimisce) bloodsuckerdatum.add_team_hud(tzimisce)
bloodsuckerdatum.bloodsucker_level_unspent += round(world.time / (15 MINUTES), 1) bloodsuckerdatum.bloodsucker_level_unspent += round(world.time / (15 MINUTES), 1)
bloodsuckerdatum.assign_clan_and_bane(tzimisce = TRUE) bloodsuckerdatum.my_clan = new /datum/bloodsucker_clan/tzimisce(bloodsuckerdatum)
bloodsuckerdatum.owner.announce_objectives()
spawned_mobs += tzimisce spawned_mobs += tzimisce
message_admins("[ADMIN_LOOKUPFLW(tzimisce)] has been made into a tzimisce bloodsucker an event.") message_admins("[ADMIN_LOOKUPFLW(tzimisce)] has been made into a tzimisce bloodsucker an event.")

View File

@@ -1,7 +1,7 @@
/datum/action/cooldown/spell/pointed/seismic /datum/action/cooldown/spell/pointed/seismic
spell_requirements = SPELL_REQUIRES_HUMAN spell_requirements = SPELL_REQUIRES_HUMAN
/datum/action/cooldown/spell/pointed/seismic/can_cast_spell() /datum/action/cooldown/spell/pointed/seismic/can_cast_spell(feedback = TRUE)
if(!isliving(owner)) if(!isliving(owner))
return FALSE return FALSE
var/mob/living/user = owner var/mob/living/user = owner
@@ -27,7 +27,7 @@
if(!.) if(!.)
return FALSE return FALSE
if(user.incapacitated()) if(user.incapacitated())
return return FALSE
var/turf/T = get_step(get_turf(user), user.dir) var/turf/T = get_step(get_turf(user), user.dir)
var/turf/Z = get_turf(user) var/turf/Z = get_turf(user)
var/obj/effect/temp_visual/decoy/fading/threesecond/F = new(Z, user) var/obj/effect/temp_visual/decoy/fading/threesecond/F = new(Z, user)
@@ -35,40 +35,42 @@
playsound(user,'sound/effects/gravhit.ogg', 20, 1) playsound(user,'sound/effects/gravhit.ogg', 20, 1)
for(var/i = 0 to jumpdistance) for(var/i = 0 to jumpdistance)
if(T.density) if(T.density)
return return FALSE
for(var/obj/D in T.contents) for(var/obj/D in T.contents)
if(D.density == TRUE) if(D.density)
return return FALSE
for(var/turf/open/chasm/C in T.contents) for(var/turf/open/chasm/C in T.contents)
return return FALSE
for(var/turf/closed/indestructible/I in T.contents) for(var/turf/closed/indestructible/I in T.contents)
return return FALSE
for(var/turf/open/lava/V in T.contents) for(var/turf/open/lava/V in T.contents)
return return FALSE
for(var/obj/machinery/door/window/E in Z.contents) for(var/obj/machinery/door/window/E in Z.contents)
if(E.density == TRUE) if(E.density)
return return FALSE
if(T) if(T)
sleep(0.1 SECONDS) addtimer(CALLBACK(src, PROC_REF(finish_lariat), user, T, F), 0.1 SECONDS)
user.forceMove(T)
walk_towards(F,user,0, 1.5)
animate(F, alpha = 0, color = "#00d9ff", time = 0.3 SECONDS)
for(var/mob/living/L in T.contents)
if(L != user)
user.forceMove(get_turf(L))
to_chat(L, span_userdanger("[user] catches you with [user.p_their()] arm and clotheslines you!"))
user.visible_message(span_warning("[user] hits [L] with a lariat!"))
L.SpinAnimation(0.5 SECONDS, 1)
if(isanimal(L))
L.adjustBruteLoss(50)
if(iscarbon(L))
L.adjustBruteLoss(10)
if(issilicon(L))
L.adjustBruteLoss(12)
playsound(L,'sound/effects/meteorimpact.ogg', 60, 1)
T = get_step(user,user.dir)
return TRUE return TRUE
/datum/action/cooldown/spell/pointed/seismic/lariat/proc/finish_lariat(mob/living/user, turf/target_turf, obj/effect/temp_visual/decoy/fading/threesecond/effect)
user.forceMove(target_turf)
walk_towards(effect,user,0, 1.5)
animate(effect, alpha = 0, color = "#00d9ff", time = 0.3 SECONDS)
for(var/mob/living/L in target_turf.contents)
if(L != user)
user.forceMove(get_turf(L))
to_chat(L, span_userdanger("[user] catches you with [user.p_their()] arm and clotheslines you!"))
user.visible_message(span_warning("[user] hits [L] with a lariat!"))
L.SpinAnimation(0.5 SECONDS, 1)
if(isanimal(L))
L.adjustBruteLoss(50)
if(iscarbon(L))
L.adjustBruteLoss(10)
if(issilicon(L))
L.adjustBruteLoss(12)
playsound(L,'sound/effects/meteorimpact.ogg', 60, 1)
target_turf = get_step(user,user.dir)
/datum/action/cooldown/spell/pointed/seismic/mop /datum/action/cooldown/spell/pointed/seismic/mop
name = "Mop the Floor" name = "Mop the Floor"
@@ -82,70 +84,71 @@
/datum/action/cooldown/spell/pointed/seismic/mop/InterceptClickOn(mob/living/user, params, atom/target) /datum/action/cooldown/spell/pointed/seismic/mop/InterceptClickOn(mob/living/user, params, atom/target)
. = ..() . = ..()
if(!.) if(!.)
return return FALSE
if(user.incapacitated()) if(user.incapacitated())
return return FALSE
var/turf/T = get_step(get_turf(user), user.dir) var/turf/T = get_step(get_turf(user), user.dir)
var/turf/Z = get_turf(user) var/turf/Z = get_turf(user)
var/obj/effect/temp_visual/decoy/fading/threesecond/F = new(Z, user) var/obj/effect/temp_visual/decoy/fading/threesecond/F = new(Z, user)
var/list/mopped = list()
user.visible_message(span_warning("[user] sprints forward with [user.p_their()] hand outstretched!")) user.visible_message(span_warning("[user] sprints forward with [user.p_their()] hand outstretched!"))
playsound(user,'sound/effects/gravhit.ogg', 20, 1) playsound(user,'sound/effects/gravhit.ogg', 20, 1)
for(var/i = 0 to jumpdistance) for(var/i = 0 to jumpdistance)
if(T.density) if(T.density)
return return FALSE
for(var/obj/D in T.contents) for(var/obj/D in T.contents)
if(D.density == TRUE) if(D.density)
return return FALSE
for (var/turf/open/chasm/C in T.contents) for(var/turf/open/chasm/C in T.contents)
return return FALSE
for (var/turf/closed/indestructible/I in T.contents) for(var/turf/closed/indestructible/I in T.contents)
return return FALSE
for(var/obj/machinery/door/window/E in Z.contents) for(var/obj/machinery/door/window/E in Z.contents)
if(E.density == TRUE) if(E.density)
return return FALSE
if(T) if(T)
sleep(0.1 SECONDS) addtimer(CALLBACK(src, PROC_REF(finish_mop), user, T, F), 0.1 SECONDS)
user.forceMove(T)
walk_towards(F,user,0, 1.5) return TRUE
animate(F, alpha = 0, color = "#00d9ff", time = 0.3 SECONDS)
for(var/mob/living/L in T.contents) /datum/action/cooldown/spell/pointed/seismic/mop/proc/finish_mop(mob/living/user, turf/target_turf, obj/effect/temp_visual/decoy/fading/threesecond/effect)
if(L != user) user.forceMove(target_turf)
mopped |= L walk_towards(effect,user,0, 1.5)
var/turf/Q = get_step(get_turf(user), user.dir) animate(effect, alpha = 0, color = "#00d9ff", time = 0.3 SECONDS)
var/mob/living/U = user var/list/mopped = list()
animate(L, transform = matrix(90, MATRIX_ROTATE), time = 0.1 SECONDS, loop = 0) for(var/mob/living/L in target_turf.contents)
if(ismineralturf(Q)) if(L != user)
var/turf/closed/mineral/M = Q mopped |= L
M.attempt_drill() var/turf/Q = get_step(get_turf(user), user.dir)
L.adjustBruteLoss(5) animate(L, transform = matrix(90, MATRIX_ROTATE), time = 0.1 SECONDS, loop = 0)
if(Q.density) if(ismineralturf(Q))
return var/turf/closed/mineral/M = Q
for(var/obj/D in Q.contents) M.attempt_drill()
if(D.density == TRUE) L.adjustBruteLoss(5)
return if(Q.density)
U.forceMove(get_turf(L)) return FALSE
to_chat(L, span_userdanger("[U] catches you with [U.p_their()] hand and drags you down!")) for(var/obj/D in Q.contents)
U.visible_message(span_warning("[U] hits [L] and drags them through the dirt!")) if(D.density)
L.forceMove(Q) return FALSE
if(isanimal(L)) user.forceMove(get_turf(L))
U.apply_status_effect(STATUS_EFFECT_BLOODDRUNK)//guaranteed extended contact with a fauna so i have to make it not a death sentence to_chat(L, span_userdanger("[user] catches you with [user.p_their()] hand and drags you down!"))
L.adjustBruteLoss(20) user.visible_message(span_warning("[user] hits [L] and drags them through the dirt!"))
if(L.stat == DEAD) L.forceMove(Q)
L.visible_message(span_warning("[L] is ground into paste!")) if(isanimal(L))
L.gib() user.apply_status_effect(STATUS_EFFECT_BLOODDRUNK)//guaranteed extended contact with a fauna so i have to make it not a death sentence
if(iscarbon(L)) L.adjustBruteLoss(20)
L.adjustBruteLoss(4) if(L.stat == DEAD)
if(issilicon(L)) L.visible_message(span_warning("[L] is ground into paste!"))
L.adjustBruteLoss(5) L.gib()
playsound(L,'sound/effects/meteorimpact.ogg', 60, 1) if(iscarbon(L))
T = get_step(user,user.dir) L.adjustBruteLoss(4)
if(issilicon(L))
L.adjustBruteLoss(5)
playsound(L,'sound/effects/meteorimpact.ogg', 60, 1)
target_turf = get_step(user, user.dir)
for(var/mob/living/C in mopped) for(var/mob/living/C in mopped)
if(C.stat == CONSCIOUS && C.resting == FALSE) if(C.stat == CONSCIOUS && C.resting == FALSE)
animate(C, transform = null, time = 0.5 SECONDS, loop = 0) animate(C, transform = null, time = 0.5 SECONDS, loop = 0)
return TRUE
/datum/action/cooldown/spell/pointed/seismic/suplex /datum/action/cooldown/spell/pointed/seismic/suplex
name = "Suplex" name = "Suplex"
desc = "Grab the target in front of you and slam them back onto the ground." desc = "Grab the target in front of you and slam them back onto the ground."
@@ -199,11 +202,15 @@
L.adjustBruteLoss(6) L.adjustBruteLoss(6)
if(issilicon(L)) if(issilicon(L))
L.adjustBruteLoss(8) L.adjustBruteLoss(8)
sleep(0.5 SECONDS) addtimer(CALLBACK(src, PROC_REF(fix_target_anim), L), 0.5 SECONDS)
if(L.stat == CONSCIOUS && L.resting == FALSE)
animate(L, transform = null, time = 0.1 SECONDS, loop = 0)
/datum/action/cooldown/spell/pointed/seismic/righthook return TRUE
/datum/action/cooldown/spell/pointed/seismic/suplex/proc/fix_target_anim(mob/living/target)
if(target.stat == CONSCIOUS && target.resting == FALSE)
animate(target, transform = null, time = 0.1 SECONDS, loop = 0)
/datum/action/cooldown/spell/touch/righthook
name = "Right Hook" name = "Right Hook"
desc = "Put the arm through its paces, cranking the outputs located at the front and back of the hand to full capacity for a powerful blow. This attack can only be readied for five seconds and connecting with it will temporarily overwhelm the entire arm for fifteen." desc = "Put the arm through its paces, cranking the outputs located at the front and back of the hand to full capacity for a powerful blow. This attack can only be readied for five seconds and connecting with it will temporarily overwhelm the entire arm for fifteen."
button_icon = 'icons/mob/actions/actions_arm.dmi' button_icon = 'icons/mob/actions/actions_arm.dmi'
@@ -211,17 +218,27 @@
cooldown_time = 3 SECONDS cooldown_time = 3 SECONDS
/datum/action/cooldown/spell/pointed/seismic/InterceptClickOn(mob/living/user, params, atom/target) sound = 'sound/effects/gravhit.ogg'
. = ..() draw_message = span_notice("Your arm begins crackling loudly!")
if(!.) drop_message = span_notice("You dissipate the power in your hand.")
spell_requirements = SPELL_REQUIRES_HUMAN
hand_path = /obj/item/melee/touch_attack/overcharged_emitter
/datum/action/cooldown/spell/touch/righthook/can_cast_spell(feedback = TRUE)
if(!isliving(owner))
return FALSE
var/mob/living/user = owner
var/obj/item/bodypart/r_arm/R = user.get_bodypart(BODY_ZONE_R_ARM)
if(R?.bodypart_disabled)
to_chat(user, span_warning("The arm isn't in a functional state right now!"))
return FALSE
if(user.IsParalyzed() || user.IsStun() || user.restrained())
return FALSE return FALSE
playsound(user,'sound/effects/beepskyspinsabre.ogg', 60, 1)
do_after(user, 2 SECONDS, user, TRUE, stayStill = FALSE)
user.put_in_r_hand(new /obj/item/overcharged_emitter)
user.visible_message(span_warning("[user]'s arm begins crackling loudly!"))
return TRUE return TRUE
/obj/item/overcharged_emitter /obj/item/melee/touch_attack/overcharged_emitter
name = "supercharged emitter" name = "supercharged emitter"
desc = "The result of all the prosthetic's power building up in its palm. It's fading fast." desc = "The result of all the prosthetic's power building up in its palm. It's fading fast."
icon = 'icons/obj/wizard.dmi' icon = 'icons/obj/wizard.dmi'
@@ -232,7 +249,7 @@
w_class = 5 w_class = 5
var/flightdist = 8 var/flightdist = 8
/obj/item/overcharged_emitter/afterattack(mob/living/L, mob/living/user, proximity) /obj/item/melee/touch_attack/overcharged_emitter/afterattack(mob/living/L, mob/living/user, proximity)
var/direction = user.dir var/direction = user.dir
var/obj/item/bodypart/r_arm/R = user.get_bodypart(BODY_ZONE_R_ARM) var/obj/item/bodypart/r_arm/R = user.get_bodypart(BODY_ZONE_R_ARM)
var/list/knockedback = list() var/list/knockedback = list()
@@ -246,7 +263,7 @@
qdel(src, force = TRUE) qdel(src, force = TRUE)
L.SpinAnimation(0.5 SECONDS, 2) L.SpinAnimation(0.5 SECONDS, 2)
playsound(L,'sound/effects/gravhit.ogg', 60, 1) playsound(L,'sound/effects/gravhit.ogg', 60, 1)
(R?.set_disabled(TRUE)) R?.set_disabled(TRUE)
to_chat(user, span_warning("The huge impact takes the arm out of commission!")) to_chat(user, span_warning("The huge impact takes the arm out of commission!"))
shake_camera(L, 4, 3) shake_camera(L, 4, 3)
shake_camera(user, 2, 3) shake_camera(user, 2, 3)
@@ -294,14 +311,19 @@
for(var/mob/living/S in knockedback) for(var/mob/living/S in knockedback)
S.forceMove(T) S.forceMove(T)
S.SpinAnimation(0.2 SECONDS, 1) S.SpinAnimation(0.2 SECONDS, 1)
sleep(0.001 SECONDS)
/obj/item/overcharged_emitter/Initialize() /obj/item/melee/touch_attack/overcharged_emitter/Initialize()
. = ..() . = ..()
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
animate(src, alpha = 50, time = 5 SECONDS) animate(src, alpha = 50, time = 5 SECONDS)
QDEL_IN(src, 5 SECONDS) QDEL_IN(src, 5 SECONDS)
/obj/item/melee/touch_attack/overcharged_emitter/Destroy()
var/datum/action/cooldown/spell/our_spell = spell_which_made_us?.resolve()
if(our_spell)
our_spell.build_all_button_icons()
return ..()
//Seismic Arm //Seismic Arm
/obj/item/bodypart/r_arm/robot/seismic /obj/item/bodypart/r_arm/robot/seismic
name = "seismic right arm" name = "seismic right arm"
@@ -309,15 +331,22 @@
icon = 'icons/mob/augmentation/augments_seismic.dmi' icon = 'icons/mob/augmentation/augments_seismic.dmi'
icon_state = "seismic_r_arm" icon_state = "seismic_r_arm"
max_damage = 60 max_damage = 60
var/list/seismic_arm_moves = list(
/datum/action/cooldown/spell/pointed/seismic/lariat,
/datum/action/cooldown/spell/pointed/seismic/mop,
/datum/action/cooldown/spell/pointed/seismic/suplex,
/datum/action/cooldown/spell/touch/righthook,
)
/obj/item/bodypart/r_arm/robot/seismic/attach_limb(mob/living/carbon/C, special) /obj/item/bodypart/r_arm/robot/seismic/attach_limb(mob/living/carbon/C, special)
. = ..() . = ..()
for(var/datum/action/cooldown/spell/pointed/seismic/spells as anything in subtypesof(/datum/action/cooldown/spell/pointed/seismic)) for(var/datum/action/cooldown/spell/moves as anything in seismic_arm_moves)
spells = new(C) moves = new moves(C)
spells.Grant(C) moves.Grant(C)
/obj/item/bodypart/r_arm/robot/seismic/drop_limb(special) /obj/item/bodypart/r_arm/robot/seismic/drop_limb(special)
var/mob/living/carbon/C = owner var/mob/living/carbon/C = owner
for(var/datum/action/cooldown/spell/pointed/seismic/spells in C.actions) for(var/datum/action/cooldown/spell/moves in C.actions)
spells.Remove(C) if(LAZYFIND(seismic_arm_moves, moves))
moves.Remove(C)
return ..() return ..()

View File

@@ -59,7 +59,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
var/deadchat_name var/deadchat_name
var/datum/orbit_menu/orbit_menu var/datum/orbit_menu/orbit_menu
var/datum/spawners_menu/spawners_menu var/datum/spawners_menu/spawners_menu
var/datum/action/unobserve/UO
// Current Viewrange // Current Viewrange
var/view = 0 var/view = 0
@@ -421,7 +420,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
for(var/area/A as anything in get_sorted_areas()) for(var/area/A as anything in get_sorted_areas())
if(!A.hidden) if(!A.hidden)
filtered += A filtered += A
var/area/thearea = input("Area to jump to", "BOOYEA") as null|anything in filtered var/area/thearea = tgui_input_list(usr, "Area to jump to", "BOOYEA", filtered)
if(!thearea) if(!thearea)
return return
@@ -483,7 +482,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
pixel_y = 0 pixel_y = 0
animate(src, pixel_y = 2, time = 1 SECONDS, loop = -1) animate(src, pixel_y = 2, time = 1 SECONDS, loop = -1)
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak /mob/dead/observer/verb/jump_to_mob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
set category = "Ghost" set category = "Ghost"
set name = "Jump to Mob" set name = "Jump to Mob"
set desc = "Teleport to a mob" set desc = "Teleport to a mob"
@@ -491,16 +490,15 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(isobserver(usr)) //Make sure they're an observer! if(isobserver(usr)) //Make sure they're an observer!
var/list/dest = list() //List of possible destinations (mobs) var/list/possible_destinations = getpois(mobs_only = TRUE) //List of possible destinations (mobs)
var/target = null //Chosen target. var/target = null //Chosen target.
dest += getpois(mobs_only = TRUE) //Fill list, prompt user with list target = tgui_input_list(usr, "Please, select a player!", "Jump to Mob", possible_destinations)
target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest
if (!target)//Make sure we actually have a target if (!target)//Make sure we actually have a target
return return
else else
var/mob/M = dest[target] //Destination mob var/mob/M = possible_destinations[target] //Destination mob
var/mob/A = src //Source mob var/mob/A = src //Source mob
var/turf/T = get_turf(M) //Turf of the destination mob var/turf/T = get_turf(M) //Turf of the destination mob
@@ -525,7 +523,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/list/views = list() var/list/views = list()
for(var/i in 7 to max_view) for(var/i in 7 to max_view)
views |= i views |= i
var/new_view = input("Choose your new view", "Modify view range", 0) as null|anything in views var/new_view = tgui_input_list(usr, "Choose your new view", "Modify view range", views)
if(new_view) if(new_view)
client.rescale_view(new_view, 0, ((max_view*2)+1) - 15) client.rescale_view(new_view, 0, ((max_view*2)+1) - 15)
else else
@@ -637,7 +635,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(!(L in GLOB.player_list) && !L.mind) if(!(L in GLOB.player_list) && !L.mind)
possessible += L possessible += L
var/mob/living/target = input("Your new life begins today!", "Possess Mob", null, null) as null|anything in possessible var/mob/living/target = tgui_input_list(usr, "Your new life begins today!", "Possess Mob", sortUsernames(possessible))
if(!target) if(!target)
return 0 return 0
@@ -840,7 +838,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
remove_verb(src, /mob/dead/observer/verb/possess) remove_verb(src, /mob/dead/observer/verb/possess)
/mob/dead/observer/reset_perspective(atom/A) /mob/dead/observer/reset_perspective(atom/A)
UO?.Remove(src)
if(client) if(client)
if(ismob(client.eye) && (client.eye != src)) if(ismob(client.eye) && (client.eye != src))
cleanup_observe() cleanup_observe()
@@ -860,7 +857,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
hide_other_mob_action_buttons(target) hide_other_mob_action_buttons(target)
LAZYREMOVE(target.observers, src) LAZYREMOVE(target.observers, src)
actions = originalactions actions = originalactions
actions -= UO
update_action_buttons() update_action_buttons()
/mob/dead/observer/verb/observe() /mob/dead/observer/verb/observe()
@@ -904,26 +900,24 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(is_secret_level(mob_eye.z) && !client?.holder) if(is_secret_level(mob_eye.z) && !client?.holder)
sight = null //we dont want ghosts to see through walls in secret areas sight = null //we dont want ghosts to see through walls in secret areas
RegisterSignal(mob_eye, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_observing_z_changed), TRUE) RegisterSignal(mob_eye, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_observing_z_changed), TRUE)
if(!UO)
UO = new(src) // Convinent way to unobserve
UO.Grant(src)
if(mob_eye.hud_used) if(mob_eye.hud_used)
client.screen = list() client.screen = list()
LAZYOR(mob_eye.observers, src) LAZYOR(mob_eye.observers, src)
mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src) mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src)
observetarget = mob_eye observetarget = mob_eye
/datum/action/unobserve /datum/action/innate/unobserve
name = "Stop Observing" name = "Stop Observing"
desc = "Stops observing the person." desc = "Stops observing the person."
button_icon = 'icons/mob/mob.dmi' button_icon = 'icons/mob/mob.dmi'
button_icon_state = "ghost_nodir" button_icon_state = "ghost_nodir"
show_to_observers = FALSE show_to_observers = FALSE
/datum/action/unobserve/Trigger() /datum/action/innate/unobserve/Activate()
owner.reset_perspective(null) var/mob/dead/observer/ghost = owner
ghost.reset_perspective(null)
/datum/action/unobserve/IsAvailable(feedback = FALSE) /datum/action/innate/unobserve/IsAvailable(feedback = FALSE)
return TRUE return TRUE
/mob/dead/observer/proc/on_observing_z_changed(datum/source, oldz, newz) /mob/dead/observer/proc/on_observing_z_changed(datum/source, oldz, newz)

View File

@@ -1251,7 +1251,7 @@
else else
mobility_flags |= MOBILITY_UI|MOBILITY_PULL mobility_flags |= MOBILITY_UI|MOBILITY_PULL
SEND_SIGNAL(src, COMSIG_LIVING_SET_BODY_POSITION, mobility_flags, .) //REMOVE THIS WHEN LAYING DOWN GETS PORTED
var/canitem = !paralyzed && !stun && conscious && !chokehold && !restrained && has_arms var/canitem = !paralyzed && !stun && conscious && !chokehold && !restrained && has_arms
if(canitem) if(canitem)

View File

@@ -144,7 +144,7 @@
if(disabled_modules & BORG_MODULE_ALL_DISABLED) if(disabled_modules & BORG_MODULE_ALL_DISABLED)
return FALSE return FALSE
inv1.icon_state = "[initial(inv1.icon_state)] +b" inv1?.icon_state = "[initial(inv1?.icon_state)] +b"
disabled_modules |= BORG_MODULE_ALL_DISABLED disabled_modules |= BORG_MODULE_ALL_DISABLED
if(!quiet) if(!quiet)
@@ -156,7 +156,7 @@
if(disabled_modules & BORG_MODULE_TWO_DISABLED) if(disabled_modules & BORG_MODULE_TWO_DISABLED)
return FALSE return FALSE
inv2.icon_state = "[initial(inv2.icon_state)] +b" inv2?.icon_state = "[initial(inv2?.icon_state)] +b"
disabled_modules |= BORG_MODULE_TWO_DISABLED disabled_modules |= BORG_MODULE_TWO_DISABLED
if(!quiet) if(!quiet)
@@ -168,7 +168,7 @@
if(disabled_modules & BORG_MODULE_THREE_DISABLED) if(disabled_modules & BORG_MODULE_THREE_DISABLED)
return FALSE return FALSE
inv3.icon_state = "[initial(inv3.icon_state)] +b" inv3?.icon_state = "[initial(inv3?.icon_state)] +b"
disabled_modules |= BORG_MODULE_THREE_DISABLED disabled_modules |= BORG_MODULE_THREE_DISABLED
if(!quiet) if(!quiet)

View File

@@ -109,12 +109,9 @@
// /datum/pet_command/point_targetting/attack/glockroach // /datum/pet_command/point_targetting/attack/glockroach
// ) // )
/datum/action/cooldown/riot/Trigger() /datum/action/cooldown/riot/Activate()
. = ..()
if(!.)
return
if(!isopenturf(owner.loc)) if(!isopenturf(owner.loc))
to_chat(owner,"<span class='warning'>You can't use raise soldiers while in an object!</span>") to_chat(owner, span_warning("You can't use raise soldiers while in an object!"))
return return
var/cap = CONFIG_GET(number/ratcap) var/cap = CONFIG_GET(number/ratcap)
var/something_from_nothing = FALSE var/something_from_nothing = FALSE
@@ -171,7 +168,7 @@
new /obj/effect/decal/cleanable/dirt(T) new /obj/effect/decal/cleanable/dirt(T)
StartCooldown() StartCooldown()
/datum/action/cooldown/domain/Activate(atom/target) /datum/action/cooldown/domain/Activate()
StartCooldown(10 SECONDS) StartCooldown(10 SECONDS)
domain() domain()
StartCooldown() StartCooldown()

View File

@@ -394,9 +394,12 @@
returning = TRUE returning = TRUE
var/obj/item/break_blade/secondblade = thrower.get_inactive_held_item() var/obj/item/break_blade/secondblade = thrower.get_inactive_held_item()
if(istype(secondblade)) if(istype(secondblade))
sleep(0.2 SECONDS) addtimer(CALLBACK(src, PROC_REF(finish_throw), secondblade, target, range, speed, thrower, spin, diagonals_first, callback, force, quickstart), 0.2 SECONDS)
thrower.dropItemToGround(secondblade, silent = TRUE)
secondblade.throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, quickstart) /obj/item/break_blade/proc/finish_throw(obj/item/break_blade/secondblade, atom/target, range, speed, mob/thrower, \
spin, diagonals_first, datum/callback/callback, force, quickstart)
thrower.dropItemToGround(secondblade, silent = TRUE)
secondblade.throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, quickstart)
/obj/item/break_blade/proc/return_to(mob/living/user) /obj/item/break_blade/proc/return_to(mob/living/user)
if(!istype(user)) if(!istype(user))

View File

@@ -397,22 +397,23 @@
/datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M) /datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
M.set_slurring_if_lower(1 SECONDS) M.set_slurring_if_lower(1 SECONDS)
switch(current_cycle) switch(current_cycle)
if(1 to 5) if(1 to 5)
M.adjust_dizzy(5 SECONDS) M.set_dizzy_if_lower(5 SECONDS)
M.set_drugginess(30) M.set_drugginess_if_lower(30 SECONDS)
if(prob(10)) if(prob(10))
M.emote(pick("twitch","giggle")) M.emote(pick("twitch","giggle"))
if(5 to 10) if(5 to 10)
M.adjust_jitter(10 SECONDS) M.set_jitter_if_lower(20 SECONDS)
M.adjust_dizzy(10 SECONDS) M.set_dizzy_if_lower(10 SECONDS)
M.set_drugginess(35) M.set_drugginess_if_lower(35 SECONDS)
if(prob(20)) if(prob(20))
M.emote(pick("twitch","giggle")) M.emote(pick("twitch","giggle"))
if (10 to INFINITY) if (10 to INFINITY)
M.adjust_jitter(20 SECONDS) M.set_jitter_if_lower(40 SECONDS)
M.adjust_dizzy(20 SECONDS) M.adjust_dizzy(20 SECONDS)
M.set_drugginess(40) M.set_drugginess_if_lower(40 SECONDS)
if(prob(30)) if(prob(30))
M.emote(pick("twitch","giggle")) M.emote(pick("twitch","giggle"))
..() ..()

View File

@@ -69,7 +69,6 @@
return TRUE return TRUE
/datum/action/cooldown/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/click_target) /datum/action/cooldown/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/click_target)
var/atom/aim_assist_target var/atom/aim_assist_target
if(aim_assist && isturf(click_target)) if(aim_assist && isturf(click_target))
// Find any human in the list. We aren't picky, it's aim assist after all // Find any human in the list. We aren't picky, it's aim assist after all
@@ -78,6 +77,8 @@
// If we didn't find a human, we settle for any living at all // If we didn't find a human, we settle for any living at all
aim_assist_target = locate(/mob/living) in click_target aim_assist_target = locate(/mob/living) in click_target
caller.face_atom(click_target)
return ..(caller, params, aim_assist_target || click_target) return ..(caller, params, aim_assist_target || click_target)
/datum/action/cooldown/spell/pointed/is_valid_target(atom/cast_on) /datum/action/cooldown/spell/pointed/is_valid_target(atom/cast_on)

View File

@@ -1,7 +1,7 @@
/datum/action/cooldown/spell/pointed/projectile/fireball /datum/action/cooldown/spell/pointed/projectile/fireball
name = "Fireball" name = "Fireball"
desc = "This spell fires an explosive fireball at a target." desc = "This spell fires an explosive fireball at a target."
button_icon_state = "fireball0" button_icon_state = "fireball"
sound = 'sound/magic/fireball.ogg' sound = 'sound/magic/fireball.ogg'
school = SCHOOL_EVOCATION school = SCHOOL_EVOCATION
@@ -13,6 +13,7 @@
spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC
base_icon_state = "fireball" base_icon_state = "fireball"
active_icon_state = "fireball_active"
active_msg = "You prepare to cast your fireball spell!" active_msg = "You prepare to cast your fireball spell!"
deactive_msg = "You extinguish your fireball... for now." deactive_msg = "You extinguish your fireball... for now."
cast_range = 8 cast_range = 8

View File

@@ -189,7 +189,7 @@
/obj/item/organ/cyberimp/leg/jumpboots/AddEffect() /obj/item/organ/cyberimp/leg/jumpboots/AddEffect()
ADD_TRAIT(owner, TRAIT_NOSLIPICE, "Jumpboot_implant") ADD_TRAIT(owner, TRAIT_NOSLIPICE, "Jumpboot_implant")
implant_ability = new implant_ability = new(src)
implant_ability.Grant(owner) implant_ability.Grant(owner)
/obj/item/organ/cyberimp/leg/jumpboots/RemoveEffect() /obj/item/organ/cyberimp/leg/jumpboots/RemoveEffect()
@@ -203,11 +203,10 @@
desc = "Dash forward." desc = "Dash forward."
button_icon = 'icons/mob/actions/actions_items.dmi' button_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "jetboot" button_icon_state = "jetboot"
check_flags = AB_CHECK_HANDS_BLOCKED| AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS
cooldown_time = 6 SECONDS cooldown_time = 6 SECONDS
var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles
var/jumpspeed = 3 var/jumpspeed = 3
var/mob/living/carbon/human/holder
/datum/action/cooldown/boost/link_to(target) /datum/action/cooldown/boost/link_to(target)
..() ..()
@@ -216,24 +215,18 @@
LAZYINITLIST(I.actions) LAZYINITLIST(I.actions)
I.actions += src I.actions += src
/datum/action/cooldown/boost/Grant(mob/user) /datum/action/cooldown/boost/Activate()
. = ..() var/mob/living/carbon/user = owner
holder = user var/atom/target = get_edge_target_turf(owner, owner.dir) //gets the user's direction
/datum/action/cooldown/boost/Trigger() if(!owner.throw_at(target, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE))
. = ..() to_chat(owner, span_warning("Something prevents you from dashing forward!"))
if(!.)
return return
var/atom/target = get_edge_target_turf(holder, holder.dir) //gets the user's direction user.Immobilize(0.1 SECONDS)
playsound(owner, 'sound/effects/stealthoff.ogg', 50, TRUE, 1)
if (holder.throw_at(target, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE)) owner.visible_message(span_warning("[owner] dashes forward into the air!"))
StartCooldown() StartCooldown()
holder.Immobilize(0.1 SECONDS)
playsound(holder, 'sound/effects/stealthoff.ogg', 50, 1, 1)
holder.visible_message(span_warning("[usr] dashes forward into the air!"))
else
to_chat(holder, span_warning("Something prevents you from dashing forward!"))
//------------wheelies implant //------------wheelies implant
/obj/item/organ/cyberimp/leg/wheelies /obj/item/organ/cyberimp/leg/wheelies

View File

Before

Width:  |  Height:  |  Size: 960 B

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -141,6 +141,7 @@
#include "code\__DEFINES\dcs\signals\signals_food.dm" #include "code\__DEFINES\dcs\signals\signals_food.dm"
#include "code\__DEFINES\dcs\signals\signals_gib.dm" #include "code\__DEFINES\dcs\signals\signals_gib.dm"
#include "code\__DEFINES\dcs\signals\signals_global.dm" #include "code\__DEFINES\dcs\signals\signals_global.dm"
#include "code\__DEFINES\dcs\signals\signals_heretic.dm"
#include "code\__DEFINES\dcs\signals\signals_global_object.dm" #include "code\__DEFINES\dcs\signals\signals_global_object.dm"
#include "code\__DEFINES\dcs\signals\signals_janitor.dm" #include "code\__DEFINES\dcs\signals\signals_janitor.dm"
#include "code\__DEFINES\dcs\signals\signals_mood.dm" #include "code\__DEFINES\dcs\signals\signals_mood.dm"

View File

@@ -1,11 +1,10 @@
/datum/antagonist/gang /datum/antagonist/gang
name = "Gangster" name = "Gangster"
roundend_category = "gangsters" roundend_category = "gangsters"
antag_hud_name = "hud_gangster" antag_hud_name = "gangster"
can_coexist_with_others = FALSE can_coexist_with_others = FALSE
job_rank = ROLE_GANG job_rank = ROLE_GANG
antagpanel_category = "Gang" antagpanel_category = "Gang"
var/hud_type = "gangster"
var/message_name = "Gangster" var/message_name = "Gangster"
var/datum/team/gang/gang var/datum/team/gang/gang
preview_outfit = /datum/outfit/gangster preview_outfit = /datum/outfit/gangster
@@ -17,7 +16,34 @@
return FALSE return FALSE
/datum/antagonist/gang/apply_innate_effects(mob/living/mob_override) /datum/antagonist/gang/apply_innate_effects(mob/living/mob_override)
add_team_hud(mob_override || owner.current, /datum/antagonist/gang) add_team_hud(mob_override || owner.current)
/datum/antagonist/gang/add_team_hud(mob/target)
QDEL_NULL(team_hud_ref)
team_hud_ref = WEAKREF(target.add_alt_appearance(
/datum/atom_hud/alternate_appearance/basic/has_antagonist,
"antag_team_hud_[REF(src)]",
hud_image_on(target),
))
var/datum/atom_hud/alternate_appearance/basic/has_antagonist/hud = team_hud_ref.resolve()
var/list/mob/living/mob_list = list()
for(var/datum/mind/collegues_minds as anything in gang.members)
mob_list += collegues_minds.current
for (var/datum/atom_hud/alternate_appearance/basic/has_antagonist/antag_hud as anything in GLOB.has_antagonist_huds)
if(!(antag_hud.target in mob_list))
continue
antag_hud.show_to(target)
hud.show_to(antag_hud.target)
/datum/antagonist/gang/hud_image_on(mob/hud_loc)
var/image/hud = image(hud_icon, hud_loc, antag_hud_name)
hud.color = gang.color
hud.plane = ABOVE_HUD_PLANE //not quite but needed
return hud
/datum/antagonist/gang/get_team() /datum/antagonist/gang/get_team()
return gang return gang
@@ -150,7 +176,7 @@
// Boss type. Those can use gang tools to buy items for their gang, in particular the Dominator, used to win the gamemode, along with more gang tools to promote fellow gangsters to boss status. // Boss type. Those can use gang tools to buy items for their gang, in particular the Dominator, used to win the gamemode, along with more gang tools to promote fellow gangsters to boss status.
/datum/antagonist/gang/boss /datum/antagonist/gang/boss
name = "Gang boss" name = "Gang boss"
hud_type = "gang_boss" antag_hud_name = "gang_boss"
message_name = "Leader" message_name = "Leader"
/datum/antagonist/gang/boss/on_gain() /datum/antagonist/gang/boss/on_gain()