Merge remote-tracking branch 'citadel/master' into combat_rework

This commit is contained in:
kevinz000
2020-05-27 18:11:15 -07:00
149 changed files with 3488 additions and 1036 deletions
+1 -6
View File
@@ -17,11 +17,6 @@
//eg: "Bloody screen" > "goggles colour" as the former is much more important
/mob
var/list/client_colours = list()
/*
Adds an instance of colour_type to the mob's client_colours list
colour_type - a typepath (subtyped from /datum/client_colour)
@@ -113,4 +108,4 @@
priority = INFINITY //we can't see colors anyway!
/datum/client_colour/monochrome/trance
priority = 1
priority = 1
+31 -1
View File
@@ -99,7 +99,37 @@
/// custom movement keys for this client
var/list/movement_keys = list()
///Autoclick list of two elements, first being the clicked thing, second being the parameters.
var/list/atom/selected_target[2]
///Autoclick variable referencing the associated item.
var/obj/item/active_mousedown_item = null
///Used in MouseDrag to preserve the original mouse click parameters
var/mouseParams = ""
///Used in MouseDrag to preserve the last mouse-entered location.
var/mouseLocation = null
///Used in MouseDrag to preserve the last mouse-entered object.
var/mouseObject = null
var/mouseControlObject = null
//Middle-mouse-button click dragtime control for aimbot exploit detection.
var/middragtime = 0
//Middle-mouse-button clicked object control for aimbot exploit detection.
var/atom/middragatom
/// Messages currently seen by this client
var/list/seen_messages
///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns
var/cryo_warned = -5 MINUTES
var/cryo_warned = -5 MINUTES
var/list/parallax_layers
var/list/parallax_layers_cached
var/atom/movable/movingmob
var/turf/previous_turf
///world.time of when we can state animate()ing parallax again
var/dont_animate_parallax
///world.time of last parallax update
var/last_parallax_shift
///ds between parallax updates
var/parallax_throttle = 0
var/parallax_movedir = 0
var/parallax_layers_max = 3
var/parallax_animate_timer
+3 -3
View File
@@ -789,9 +789,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
log_game("[key_name(src)] is using the middle click aimbot exploit")
message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] is using the middle click aimbot exploit</span>")
add_system_note("aimbot", "Is using the middle click aimbot exploit")
log_click(object, location, control, params, src, "lockout (spam - minute ab c [ab] s [middragtime])")
log_click(object, location, control, params, src, "lockout (spam - minute ab c [ab] s [middragtime])", TRUE)
else
log_click(object, location, control, params, src, "lockout (spam - minute)")
log_click(object, location, control, params, src, "lockout (spam - minute)", TRUE)
log_game("[key_name(src)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
to_chat(src, "<span class='danger'>[msg]</span>")
@@ -811,7 +811,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
return
if(ab) //Citadel edit, things with stuff.
log_click(object, location, control, params, src, "dropped (ab c [ab] s [middragtime])")
log_click(object, location, control, params, src, "dropped (ab c [ab] s [middragtime])", TRUE)
return
if(prefs.log_clicks)
@@ -24,7 +24,7 @@
. += "<span class='notice'>[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again."
/obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/living/user, was_forced = FALSE)
if(user.combat_flags & COMBAT_FLAG_COMBAT_TOGGLED && world.time >= nextadrenalinepop)
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_TOGGLED) && world.time >= nextadrenalinepop)
nextadrenalinepop = world.time + 5 MINUTES
user.reagents.add_reagent(/datum/reagent/syndicateadrenals, 5)
user.playsound_local(user, 'sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
+1
View File
@@ -198,6 +198,7 @@
desc = "A creepy wooden mask. Surprisingly expressive for a poorly carved bit of wood."
icon_state = "tiki_eyebrow"
item_state = "tiki_eyebrow"
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.25)
resistance_flags = FLAMMABLE
max_integrity = 100
actions_types = list(/datum/action/item_action/adjust)
@@ -45,6 +45,7 @@
desc = "A pair of rather plain wooden sandals."
name = "sandals"
icon_state = "wizard"
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 0.5)
strip_delay = 50
equip_delay_other = 50
permeability_coefficient = 0.9
@@ -444,7 +444,6 @@ Contains:
desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats. Alas, this one looks pretty worn out and rusted."
armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60)
slowdown = 0.8
obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints.
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old
charges = 12
@@ -470,7 +469,6 @@ Contains:
desc = "Voices echo from the hardsuit, driving the user insane. This one is pretty battle-worn, but still fearsome."
armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60)
slowdown = 0.8
obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints.
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old
charges = 6
+121 -18
View File
@@ -165,31 +165,134 @@
var/robe_charge = TRUE
actions_types = list(/datum/action/item_action/stickmen)
/obj/item/clothing/suit/wizrobe/paper/item_action_slot_check(slot, mob/user, datum/action/A)
if(A.type == /datum/action/item_action/stickmen && slot != SLOT_WEAR_SUIT)
return FALSE
return ..()
/obj/item/clothing/suit/wizrobe/paper/ui_action_click(mob/user, action)
stickmen()
//Stickmemes. VV-friendly.
/datum/action/item_action/stickmen
name = "Summon Stick Minions"
desc = "Allows you to summon faithful stickmen allies to aide you in battle."
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "art_summon"
var/ready = TRUE
var/list/summoned_stickmen = list()
var/summoned_mob_path = /mob/living/simple_animal/hostile/stickman //Must be an hostile animal path.
var/max_stickmen = 8
var/cooldown = 3 SECONDS
var/list/book_of_grudges = list()
/datum/action/item_action/stickmen/New(Target)
..()
if(isitem(Target))
RegisterSignal(Target, COMSIG_PARENT_EXAMINE, .proc/give_infos)
/datum/action/item_action/stickmen/Destroy()
for(var/A in summoned_stickmen)
var/mob/living/simple_animal/hostile/S = A
if(S.client)
to_chat(S, "<span class='danger'>A dizzying sensation strikes you as the comglomerate of pencil lines you call \
your body crumbles under the pressure of an invisible eraser, soon to join bilions discarded sketches. \
It seems whatever was keeping you in this realm has come to an end, like all things.</span>")
animate(S, alpha = 0, time = 5 SECONDS)
QDEL_IN(S, 5 SECONDS)
return ..()
/datum/action/item_action/stickmen/proc/give_infos(atom/source, mob/user, list/examine_list)
examine_list += "<span class='notice'>Making sure you are properly wearing or holding it, \
point at whatever you want to rally your minions to its position."
examine_list += "While on <b>harm</b> intent, pointed mobs (minus you and the minions) \
will also be marked as foes for your minions to attack for the next 2 minutes.</span>"
/datum/action/item_action/stickmen/Grant(mob/M)
. = ..()
if(owner)
RegisterSignal(M, COMSIG_MOB_POINTED, .proc/rally)
if(book_of_grudges[M]) //Stop attacking your new master.
book_of_grudges -= M
for(var/A in summoned_stickmen)
var/mob/living/simple_animal/hostile/S = A
if(!S.mind)
S.LoseTarget()
/obj/item/clothing/suit/wizrobe/paper/verb/stickmen()
set category = "Object"
set name = "Summon Stick Minions"
set src in usr
if(!isliving(usr))
/datum/action/item_action/stickmen/Remove(mob/M)
. = ..()
UnregisterSignal(M, COMSIG_MOB_POINTED)
/datum/action/item_action/stickmen/Trigger()
. = ..()
if(!.)
return
if(!robe_charge)
to_chat(usr, "<span class='warning'>\The robe's internal magic supply is still recharging!</span>")
if(!ready)
to_chat(owner, "<span class='warning'>[src]'s internal magic supply is still recharging!</span>")
return FALSE
var/summon = TRUE
if(length(summoned_stickmen) >= max_stickmen)
var/mob/living/simple_animal/hostile/S = popleft(summoned_stickmen)
if(!S.client)
qdel(S)
else
S.forceMove(owner.drop_location())
S.revive(TRUE)
summoned_stickmen[S] = TRUE
summon = FALSE
owner.say("Rise, my creation! Off your page into this realm!", forced = "stickman summoning")
playsound(owner, 'sound/magic/summon_magic.ogg', 50, 1, 1)
if(summon)
var/mob/living/simple_animal/hostile/S = new summoned_mob_path (get_turf(usr))
S.faction = owner.faction
S.foes = book_of_grudges
RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/remove_from_list)
ready = FALSE
addtimer(CALLBACK(src, .proc/ready_again), cooldown)
/datum/action/item_action/stickmen/proc/remove_from_list(datum/source, forced)
summoned_stickmen -= source
/datum/action/item_action/stickmen/proc/ready_again()
ready = TRUE
if(owner)
to_chat(owner, "<span class='notice'>[src] hums, its internal magic supply restored.</span>")
/**
* Rallies your army of stickmen to whichever target the user is pointing.
* Should the user be on harm intent and the target be a living mob that's not the user or a fellow stickman,
* said target will be added to a list of foes which the stickmen will gladly dispose regardless of faction.
* This is designed so stickmen will move toward whatever you point at even when you don't want to, that's the downside.
*/
/datum/action/item_action/stickmen/proc/rally(mob/source, atom/A)
var/turf/T = get_turf(A)
var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z))
if(!surrounding_turfs.len)
return
if(source.a_intent == INTENT_HARM && A != source && !summoned_stickmen[A])
var/mob/living/L
if(isliving(A)) //Gettem boys!
L = A
else if(ismecha(A))
var/obj/mecha/M = A
L = M.occupant
if(L && L.stat != DEAD && !HAS_TRAIT(L, TRAIT_DEATHCOMA)) //Taking revenge on the deads would be proposterous.
addtimer(CALLBACK(src, .proc/clear_grudge, L), 2 MINUTES, TIMER_OVERRIDE|TIMER_UNIQUE)
if(!book_of_grudges[L])
RegisterSignal(L, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH), .proc/grudge_settled)
book_of_grudges[L] = TRUE
for(var/k in summoned_stickmen) //Shamelessly copied from the blob rally power
var/mob/living/simple_animal/hostile/S = k
if(!S.mind && isturf(S.loc) && get_dist(S, T) <= 10)
S.LoseTarget()
S.Goto(pick(surrounding_turfs), S.move_to_delay)
usr.say("Rise, my creation! Off your page into this realm!", forced = "stickman summoning")
playsound(src.loc, 'sound/magic/summon_magic.ogg', 50, 1, 1)
var/mob/living/M = new /mob/living/simple_animal/hostile/stickman(get_turf(usr))
var/list/factions = usr.faction
M.faction = factions
src.robe_charge = FALSE
sleep(30)
src.robe_charge = TRUE
to_chat(usr, "<span class='notice'>\The robe hums, its internal magic supply restored.</span>")
/datum/action/item_action/stickmen/proc/clear_grudge(mob/living/L)
if(!QDELETED(L))
book_of_grudges -= L
/datum/action/item_action/stickmen/proc/grudge_settled(mob/living/L)
UnregisterSignal(L, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH))
book_of_grudges -= L
//Shielded Armour
+1 -5
View File
@@ -5,12 +5,8 @@
category = CATEGORY_COMBAT
description = "Toggles whether or not you're in combat mode."
/datum/keybinding/living/toggle_combat_mode/can_use(client/user)
return iscarbon(user.mob) // for now, only carbons should be using combat mode, although all livings have combat mode implemented.
/datum/keybinding/living/toggle_combat_mode/down(client/user)
var/mob/living/carbon/C = user.mob
C.user_toggle_intentional_combat_mode()
SEND_SIGNAL(user.mob, COMSIG_TOGGLE_COMBAT_MODE)
return TRUE
/datum/keybinding/living/active_block
@@ -12,7 +12,6 @@
/obj/effect/mapping_helpers/network_builder/Initialize(mapload)
. = ..()
to_chat(world, "DEBUG: Initializing [COORD(src)]")
var/conflict = check_duplicates()
if(conflict)
stack_trace("WARNING: [type] network building helper found check_duplicates() conflict [conflict] in its location.!")
@@ -27,7 +26,6 @@
/// How this works: On LateInitialize, detect all directions that this should be applicable to, and do what it needs to do, and then inform all network builders in said directions that it's been around since it won't be around afterwards.
/obj/effect/mapping_helpers/network_builder/LateInitialize()
to_chat(world, "DEBUG: LateInitializing [COORD(src)]")
scan_directions()
build_network()
if(!custom_spawned)
@@ -33,7 +33,7 @@
if(malfunctioning)
H.faction |= list("lazarus", "[REF(user)]")
H.robust_searching = 1
H.friends += user
H.friends[user]++
H.attack_same = 1
log_game("[key_name(user)] has revived hostile mob [key_name(target)] with a malfunctioning lazarus injector")
else
@@ -168,3 +168,17 @@
throwforce = 7
custom_materials = list(/datum/material/iron=50)
w_class = WEIGHT_CLASS_SMALL
/obj/item/shovel/serrated
name = "serrated bone shovel"
desc = "A wicked tool that cleaves through dirt just as easily as it does flesh. The design was styled after ancient lavaland tribal designs."
icon_state = "shovel_bone"
item_state = "shovel_bone"
lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
force = 15
throwforce = 12
w_class = WEIGHT_CLASS_NORMAL
toolspeed = 0.7
attack_verb = list("slashed", "impaled", "stabbed", "sliced")
sharpness = IS_SHARP
@@ -270,6 +270,7 @@
desc = "A sign of relief for weary miners, and a warning for would-be competitors to Nanotrasen's mining claims."
icon = 'icons/turf/walls/survival_pod_walls.dmi'
icon_state = "ntpod"
buildable_sign = FALSE
/obj/structure/sign/mining/survival
name = "shelter sign"
@@ -24,12 +24,12 @@
if(!eye_blind)
blind_eyes(1)
update_mobility()
else
if(stat == UNCONSCIOUS)
stat = CONSCIOUS
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT))
set_resting(FALSE, TRUE)
else if(stat == UNCONSCIOUS)
stat = CONSCIOUS
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT))
set_resting(FALSE, TRUE)
if(eye_blind <= 1)
adjust_blindness(-1)
update_mobility()
update_mobility()
update_damage_hud()
update_health_hud()
+7 -10
View File
@@ -442,14 +442,14 @@
//dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100
var/modifier = 0
var/modifier = 50
if(HAS_TRAIT(src, TRAIT_CLUMSY))
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
//CIT CHANGES START HERE
else if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
modifier += 50
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
modifier -= 50
if(modifier < 100)
dropItemToGround(I)
@@ -827,16 +827,17 @@
return
if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT)))
stat = UNCONSCIOUS
disable_intentional_combat_mode(FALSE, FALSE)
SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE)
if(!eye_blind)
blind_eyes(1)
else
if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
stat = SOFT_CRIT
disable_intentional_combat_mode(FALSE, FALSE)
SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE)
else
stat = CONSCIOUS
adjust_blindness(-1)
if(eye_blind <= 1)
adjust_blindness(-1)
update_mobility()
update_damage_hud()
update_health_hud()
@@ -1122,10 +1123,6 @@
if(mood.sanity < SANITY_UNSTABLE)
return TRUE
/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE)
disable_intentional_combat_mode(TRUE, FALSE)
return ..()
/mob/living/carbon/can_see_reagents()
. = ..()
if(.) //No need to run through all of this if it's already true.
@@ -1,6 +0,0 @@
/mob/living/carbon/enable_intentional_combat_mode()
. = ..()
if(.)
if(voremode)
toggle_vore_mode()
-6
View File
@@ -8,8 +8,6 @@
if(!gibbed)
emote("deathgasp")
disable_intentional_combat_mode(TRUE, FALSE)
. = ..()
for(var/T in get_traumas())
@@ -62,7 +60,3 @@
var/obj/item/bodypart/BP = X
BP.drop_limb()
BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
/mob/living/carbon/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE)
disable_intentional_combat_mode(TRUE, FALSE)
return ..()
+1 -1
View File
@@ -90,7 +90,7 @@
if(digitalcamo)
. += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly unsimian manner."
if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
. += "[t_He] [t_is] visibly tense[CHECK_MOBILITY(src, MOBILITY_STAND) ? "." : ", and [t_is] standing in combative stance."]"
var/trait_exam = common_trait_examine()
@@ -39,6 +39,7 @@
. = ..()
if(!CONFIG_GET(flag/disable_human_mood))
AddComponent(/datum/component/mood)
AddComponent(/datum/component/combat_mode)
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
@@ -16,8 +16,6 @@
if(!SSI)
SSI = CONFIG_GET_ENTRY(number/movedelay/sprint_speed_increase)
. -= SSI.config_entry_value
if(wrongdirmovedelay)
. += 1
if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP))
. -= 1.5
@@ -1473,11 +1473,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/punchedbrute = target.getBruteLoss()
//CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage
if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 1.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
damage *= 0.5
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 0.25
//END OF CITADEL CHANGES
@@ -1625,11 +1625,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
log_combat(user, target, "disarmed out of grab from")
return
var/randn = rand(1, 100)
if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) // CITADEL CHANGE
if(SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) // CITADEL CHANGE
randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed
if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE
randn += 100 //CITADEL CHANGE - No kosher disarming if you're resting
if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CITADEL CHANGE
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) //CITADEL CHANGE
randn += 25 //CITADEL CHANGE - Makes it harder to disarm outside of combat mode
if(user.pulling == target)
randn -= 20 //If you have the time to get someone in a grab, you should have a greater chance at snatching the thing in their hand. Will be made completely obsolete by the grab rework but i've got a poor track record for releasing big projects on time so w/e i guess
@@ -1830,7 +1830,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(IS_STAMCRIT(user))
to_chat(user, "<span class='warning'>You're too exhausted for that.</span>")
return
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
to_chat(user, "<span class='warning'>You need combat mode to be active to that!</span>")
return
if(user.IsKnockdown() || user.IsParalyzed() || user.IsStun())
@@ -6,8 +6,8 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
name = "Dwarf"
id = "dwarf" //Also called Homo sapiens pumilionis
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NO_UNDERWEAR,TRAIT_DWARF)
inherent_traits = list()
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB)
limbs_id = "human"
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
say_mod = "bellows" //high energy, EXTRA BIOLOGICAL FUEL
@@ -87,9 +87,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
var/heal_rate = 0.5 //The rate they heal damages over 400 alcohol stored. Default is 0.5 so we times 3 since 3 seconds.
var/alcohol_rate = 0.25 //The rate the alcohol ticks down per each iteration of dwarf_eth_ticker completing.
//These count in on_life ticks which should be 2 seconds per every increment of 1 in a perfect world.
var/dwarf_filth_ticker = 0 //Currently set =< 4, that means this will fire the proc around every 4-8 seconds.
var/dwarf_eth_ticker = 0 //Currently set =< 1, that means this will fire the proc around every 2 seconds
var/last_filth_spam
var/last_alcohol_spam
/obj/item/organ/dwarfgland/prepare_eat()
@@ -100,64 +98,10 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
/obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops..
. = ..()
if(owner && owner.stat != DEAD)
dwarf_cycle_ticker()
//Handles the delayed tick cycle by just adding on increments per each on_life() tick
/obj/item/organ/dwarfgland/proc/dwarf_cycle_ticker()
dwarf_eth_ticker++
dwarf_filth_ticker++
if(dwarf_filth_ticker >= 4) //Should be around 4-8 seconds since a tick is around 2 seconds.
dwarf_filth_cycle() //On_life will adjust regarding other factors, so we are along for the ride.
dwarf_filth_ticker = 0 //We set the ticker back to 0 to go again.
if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds.
dwarf_eth_cycle()
dwarf_eth_ticker = 0
//If this still friggin uses too much CPU, I'll make a for view subsystem If I have to.
/obj/item/organ/dwarfgland/proc/dwarf_filth_cycle()
if(!owner?.client || !owner?.mind)
return
//Filth Reactions - Since miasma now exists
var/filth_counter = 0 //Holder for the filth check cycle, basically contains how much filth dwarf sees numerically.
for(var/fuck in owner.fov_view(7)) //hello byond for view loop.
if(istype(fuck, /mob/living/carbon/human))
var/mob/living/carbon/human/H = fuck
if(H.stat == DEAD || (HAS_TRAIT(H, TRAIT_FAKEDEATH)))
filth_counter += 10
if(istype(fuck, /obj/effect/decal/cleanable/blood))
if(istype(fuck, /obj/effect/decal/cleanable/blood/gibs))
filth_counter += 1
else
filth_counter += 0.1
if(istype(fuck,/obj/effect/decal/cleanable/vomit)) //They are disgusted by their own vomit too.
filth_counter += 10 //Dwarves could technically chainstun each other in a vomit tantrum spiral.
switch(filth_counter)
if(11 to 25)
if(last_filth_spam + 40 SECONDS < world.time)
to_chat(owner, "<span class = 'warning'>Someone should really clean up in here!</span>")
last_filth_spam = world.time
if(26 to 50)
if(prob(6)) //And then the probability they vomit along with it.
to_chat(owner, "<span class = 'danger'>The stench makes you queasy.</span>")
owner.vomit(10) //I think vomit should stay over a disgust adjustment.
if(51 to 75)
if(prob(9))
to_chat(owner, "<span class = 'danger'>By Armok! You won't be able to keep alcohol down at all!</span>")
owner.vomit(20) //Its more funny
if(76 to 100)
if(prob(11))
to_chat(owner, "<span class = 'userdanger'>You can't live in such FILTH!</span>")
owner.adjustToxLoss(10) //Now they start dying.
owner.vomit(20)
if(101 to INFINITY) //Now they will really start dying
if(last_filth_spam + 12 SECONDS < world.time)
to_chat(owner, "<span class = 'userdanger'> THERES TOO MUCH FILTH, OH GODS THE FILTH!</span>")
last_filth_spam = world.time
if(prob(40))
owner.adjustToxLoss(15)
owner.vomit(30)
CHECK_TICK //Check_tick right here, its motherfuckin magic. (To me at least)
dwarf_eth_ticker++
if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds.
dwarf_eth_cycle()
dwarf_eth_ticker = 0
//Handles the dwarf alcohol cycle tied to on_life, it ticks in dwarf_cycle_ticker.
/obj/item/organ/dwarfgland/proc/dwarf_eth_cycle()
+1 -1
View File
@@ -523,7 +523,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc..
/mob/living/carbon/handle_status_effects()
..()
if(getStaminaLoss() && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active
if(getStaminaLoss() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active
adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? -7.5 : -6) : -3)//CIT CHANGE - decreases adjuststaminaloss to stop stamina damage from being such a joke
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1)
+1 -1
View File
@@ -322,7 +322,7 @@
set_pull_offsets(M, state)
/mob/living/proc/set_pull_offsets(mob/living/M, grab_state = GRAB_PASSIVE)
if(M.buckled || M.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)
if(M.buckled || SEND_SIGNAL(M, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
return //don't make them change direction or offset them if they're buckled into something or in combat mode.
var/offset = 0
switch(grab_state)
+1 -1
View File
@@ -122,7 +122,7 @@
//// CITADEL STATION COMBAT ////
/// See __DEFINES/combat.dm
var/combat_flags = COMBAT_FLAGS_STAMSYSTEM_EXEMPT
var/combat_flags = COMBAT_FLAGS_SPRINT_EXEMPT
/// Next world.time when we will show a visible message on entering combat mode voluntarily again.
var/combatmessagecooldown = 0
@@ -15,8 +15,6 @@
speech_span = SPAN_ROBOT
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
vore_flags = NO_VORE
/// Enable sprint system but not stamina
combat_flags = COMBAT_FLAGS_STAMEXEMPT_YESSPRINT
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
var/last_lawchange_announce = 0
@@ -27,7 +27,7 @@
glide_size = 2
footstep_type = FOOTSTEP_MOB_CLAW
/mob/living/simple_animal/pet/fox/ComponentInitialize()
/mob/living/simple_animal/pet/sloth/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "sloth") //finally oranges can be held
@@ -23,29 +23,21 @@
for(var/ab in boss_abilities)
boss_abilities -= ab
var/datum/action/boss/AB = new ab()
AB.boss = src
AB.Grant(src)
boss_abilities += AB
atb.assign_abilities(boss_abilities)
/mob/living/simple_animal/hostile/boss/Destroy()
qdel(atb)
atb = null
for(var/ab in boss_abilities)
var/datum/action/boss/AB = ab
AB.boss = null
AB.Remove(src)
qdel(AB)
boss_abilities.Cut()
QDEL_NULL(atb)
QDEL_LIST(boss_abilities)
return ..()
//Action datum for bosses
//Override Trigger() as shown below to do things
/datum/action/boss
check_flags = AB_CHECK_CONSCIOUS //Incase the boss is given a player
required_mobility_flags = NONE
var/boss_cost = 100 //Cost of usage for the boss' AI 1-100
var/usage_probability = 100
var/mob/living/simple_animal/hostile/boss/boss
@@ -53,23 +45,34 @@
var/needs_target = TRUE //Does the boss need to have a target? (Only matters for the AI)
var/say_when_triggered = "" //What does the boss Say() when the ability triggers?
/datum/action/boss/Destroy()
boss = null
return ..()
/datum/action/boss/Grant(mob/M)
. = ..()
boss = owner
/datum/action/boss/Remove(mob/M)
. = ..()
boss = null
/datum/action/boss/Trigger()
. = ..()
if(.)
if(!istype(boss, boss_type))
return 0
if(!boss.atb)
return 0
if(boss.atb.points < boss_cost)
return 0
if(!boss.client)
if(needs_target && !boss.target)
return 0
if(boss)
if(say_when_triggered)
boss.say(say_when_triggered, forced = "boss action")
if(!boss.atb.spend(boss_cost))
return 0
if(!.)
return
if(!istype(boss, boss_type))
return FALSE
if(!boss.atb)
return FALSE
if(boss.atb.points < boss_cost)
return FALSE
if(!boss.client && needs_target && !boss.target)
return FALSE
if(!boss.atb.spend(boss_cost))
return FALSE
if(say_when_triggered)
boss.say(say_when_triggered, forced = "boss action")
//Example:
/*
@@ -83,7 +86,8 @@
/datum/boss_active_timed_battle
var/list/abilities //a list of /datum/action/boss owned by a boss mob
var/point_regen_delay = 5
var/points = 50 //1-100, start with 50 so we can use some abilities but not insta-buttfug somebody
var/max_points = 100
var/points = 50 //start with 50 so we can use some abilities but not insta-buttfug somebody
var/next_point_time = 0
var/chance_to_hold_onto_points = 50
var/highest_cost = 0
@@ -108,22 +112,22 @@
/datum/boss_active_timed_battle/proc/spend(cost)
if(cost <= points)
points = max(0,points-cost)
return 1
return 0
return TRUE
return FALSE
/datum/boss_active_timed_battle/proc/refund(cost)
points = min(points+cost, 100)
points = min(points+cost, max_points)
/datum/boss_active_timed_battle/process()
if(world.time >= next_point_time)
if(world.time >= next_point_time && points < max_points)
next_point_time = world.time + point_regen_delay
points = min(100, ++points) //has to be out of 100
points = min(max_points, ++points) //has to be out of 100
if(abilities)
chance_to_hold_onto_points = highest_cost*0.5
if(points != 100 && prob(chance_to_hold_onto_points))
if(points != max_points && prob(chance_to_hold_onto_points))
return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
if(!boss.client)
abilities = shuffle(abilities)
@@ -135,5 +139,5 @@
/datum/boss_active_timed_battle/Destroy()
abilities = null
SSobj.processing.Remove(src)
STOP_PROCESSING(SSobj, src)
return ..()
@@ -32,25 +32,47 @@
name = "Summon Minions"
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
button_icon_state = "art_summon"
usage_probability = 40
usage_probability = 20
boss_cost = 30
boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard
needs_target = FALSE
say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!"
var/static/summoned_minions = 0
var/list/summoned_minions = list()
var/maximum_stickmen = 6
var/stickmen_to_summon = 3
/datum/action/boss/wizard_summon_minions/Trigger()
if(summoned_minions <= 6 && ..())
var/list/minions = list(
/mob/living/simple_animal/hostile/stickman,
/mob/living/simple_animal/hostile/stickman/ranged,
/mob/living/simple_animal/hostile/stickman/dog)
var/list/directions = GLOB.cardinals.Copy()
for(var/i in 1 to 3)
var/minions_chosen = pick_n_take(minions)
new minions_chosen (get_step(boss,pick_n_take(directions)), 1)
summoned_minions += 3;
. =..()
if(!.)
return
var/to_summon = stickmen_to_summon
var/current_len = length(summoned_minions)
if(current_len > maximum_stickmen - stickmen_to_summon)
for(var/a in (maximum_stickmen - stickmen_to_summon) to current_len)
var/mob/living/simple_animal/hostile/stickman/S = popleft(summoned_minions)
if(!S.client)
qdel(S)
else
S.forceMove(boss.drop_location())
S.revive(TRUE)
summoned_minions += S
to_summon--
var/static/list/minions = list(
/mob/living/simple_animal/hostile/stickman,
/mob/living/simple_animal/hostile/stickman/ranged,
/mob/living/simple_animal/hostile/stickman/dog)
var/list/directions = GLOB.cardinals.Copy()
for(var/i in 1 to to_summon)
var/minions_chosen = pick(minions)
var/mob/living/simple_animal/hostile/stickman/S = new minions_chosen (get_step(boss,pick_n_take(directions)), 1)
S.faction = boss.faction
RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/remove_from_list)
summoned_minions += S
/datum/action/boss/wizard_summon_minions/proc/remove_from_list(datum/source, forced)
summoned_minions -= source
//Mimic Ability
//Summons mimics of himself with magical papercraft
@@ -66,28 +88,32 @@
say_when_triggered = ""
/datum/action/boss/wizard_mimic/Trigger()
if(..())
var/mob/living/target
if(!boss.client) //AI's target
target = boss.target
else //random mob
var/list/threats = boss.PossibleThreats()
if(threats.len)
target = pick(threats)
if(target)
var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss
var/directions = GLOB.cardinals.Copy()
for(var/i in 1 to 3)
var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions)))
wiz.copies += C
C.original = wiz
C.say("My craft defines me, you could even say it IS me!")
wiz.say("My craft defines me, you could even say it IS me!")
wiz.forceMove(get_step(target,pick_n_take(directions)))
wiz.minimum_distance = 1 //so he doesn't run away and ruin everything
wiz.retreat_distance = 0
. = ..()
if(!.)
return
var/mob/living/target
if(!boss.client) //AI's target
target = boss.target
else //random mob
var/list/threats = boss.PossibleThreats()
if(threats.len)
target = pick(threats)
else
boss.atb.refund(boss_cost)
to_chat(owner, "<span class='warning'>There is no potential foe of different faction around to attack</span>")
if(target)
var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss
var/directions = GLOB.cardinals.Copy()
for(var/i in 1 to 3)
var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions)))
wiz.copies += C
C.original = wiz
C.say("My craft defines me, you could even say it IS me!")
wiz.say("My craft defines me, you could even say it IS me!")
wiz.forceMove(get_step(target,pick_n_take(directions)))
wiz.minimum_distance = 1 //so he doesn't run away and ruin everything
wiz.retreat_distance = 0
else
boss.atb.refund(boss_cost)
/mob/living/simple_animal/hostile/boss/paper_wizard/copy
desc = "'Tis a ruse!"
@@ -20,6 +20,7 @@
var/casingtype //set ONLY it and NULLIFY projectiletype, if we have projectile IN CASING
var/move_to_delay = 3 //delay for the automated movement.
var/list/friends = list()
var/list/foes = list()
var/list/emote_taunt = list()
var/taunt_chance = 0
@@ -62,6 +63,8 @@
/mob/living/simple_animal/hostile/Destroy()
targets_from = null
friends = null
foes = null
return ..()
/mob/living/simple_animal/hostile/Life()
@@ -193,7 +196,7 @@
// Please do not add one-off mob AIs here, but override this function for your mob
/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
if(!the_target || the_target.type == /atom/movable/lighting_object || isturf(the_target)) // bail out on invalids
return FALSE
if(ismob(the_target)) //Target is in godmode, ignore it.
@@ -208,13 +211,13 @@
if(search_objects < 2)
if(isliving(the_target))
var/mob/living/L = the_target
var/faction_check = faction_check_mob(L)
var/faction_check = !foes[L] && faction_check_mob(L)
if(robust_searching)
if(faction_check && !attack_same)
return FALSE
if(L.stat > stat_attack)
if(L.stat > stat_attack || (L.stat == UNCONSCIOUS && stat_attack == UNCONSCIOUS && HAS_TRAIT(L, TRAIT_DEATHCOMA)))
return FALSE
if(L in friends)
if(friends[L] > 0 && foes[L] < 1)
return FALSE
else
if((faction_check && !attack_same) || L.stat)
@@ -298,5 +298,5 @@
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc)
A.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
A.GiveTarget(target)
A.friends = user
A.friends[user]++
A.faction = user.faction.Copy()
@@ -13,7 +13,7 @@
speed = 0
blood_volume = 0
stat_attack = UNCONSCIOUS
robust_searching = 1
robust_searching = TRUE //This is also required for the paper robe rallying to work.
environment_smash = ENVIRONMENT_SMASH_NONE
maxHealth = 100
health = 100
@@ -30,8 +30,6 @@
faction = list("hostile","stickman")
check_friendly_fire = 1
status_flags = CANPUSH
var/datum/action/boss/wizard_summon_minions/changesummons = /datum/action/boss/wizard_summon_minions
var/summoned_by_wizard = 0
/mob/living/simple_animal/hostile/stickman/ranged
ranged = 1
@@ -43,7 +41,6 @@
projectilesound = 'sound/misc/bang.ogg'
loot = list(/obj/item/gun/ballistic/automatic/pistol/stickman)
/mob/living/simple_animal/hostile/stickman/dog
name = "Angry Stick Dog"
desc = "Stickman's best friend, if he could see him at least."
@@ -52,12 +49,6 @@
icon_dead = "stickdog_dead"
mob_biotypes = MOB_BEAST
/mob/living/simple_animal/hostile/stickman/Initialize(mapload, var/wizard_summoned)
/mob/living/simple_animal/hostile/stickman/Initialize(mapload)
. = ..()
new /obj/effect/temp_visual/paper_scatter(src)
summoned_by_wizard = wizard_summoned
/mob/living/simple_animal/hostile/stickman/death()
..()
if(summoned_by_wizard == 1)
changesummons.summoned_minions --
+3 -2
View File
@@ -571,12 +571,13 @@
/mob/living/proc/cure_blind(source)
REMOVE_TRAIT(src, TRAIT_BLIND, source)
if(!HAS_TRAIT(src, TRAIT_BLIND))
update_blindness()
if(eye_blind <= 1) //little hack now that we don't actively check for trait and unconsciousness on update_blindness.
adjust_blindness(-1)
/mob/living/proc/become_blind(source)
if(!HAS_TRAIT(src, TRAIT_BLIND)) // not blind already, add trait then overlay
ADD_TRAIT(src, TRAIT_BLIND, source)
update_blindness()
blind_eyes(1)
else
ADD_TRAIT(src, TRAIT_BLIND, source)
+4 -8
View File
@@ -128,15 +128,13 @@
* * target (optional) is the other mob involved with the visible message. For example, the attacker in many combat messages.
* * target_message (optional) is what the target mob will see e.g. "[src] does something to you!"
*/
/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, mob/target, target_message)
/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, ignored_mobs, mob/target, target_message)
var/turf/T = get_turf(src)
if(!T)
return
var/list/hearers = get_hearers_in_view(vision_distance, src) //caches the hearers and then removes ignored mobs.
if(!length(hearers))
return
if(!islist(ignored_mobs))
ignored_mobs = list(ignored_mobs)
hearers -= ignored_mobs
if(target_message && target && istype(target) && target.client)
@@ -150,7 +148,7 @@
msg = blind_message
if(msg)
target.show_message(msg, MSG_VISUAL,blind_message, MSG_AUDIBLE)
else if(self_message)
if(self_message)
hearers -= src
for(var/mob/M in hearers)
if(!M.client)
@@ -185,15 +183,13 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
* * hearing_distance (optional) is the range, how many tiles away the message can be heard.
* * ignored_mobs (optional) doesn't show any message to any given mob in the list.
*/
/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs)
/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, ignored_mobs)
var/turf/T = get_turf(src)
if(!T)
return
var/list/hearers = get_hearers_in_view(hearing_distance, src)
if(!length(hearers))
return
if(!islist(ignored_mobs))
ignored_mobs = list(ignored_mobs)
hearers -= ignored_mobs
if(self_message)
hearers -= src
@@ -377,7 +373,7 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
return FALSE
new /obj/effect/temp_visual/point(A,invisibility)
SEND_SIGNAL(src, COMSIG_MOB_POINTED, A)
return TRUE
/mob/proc/can_resist()
+7
View File
@@ -127,6 +127,13 @@
var/registered_z
var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly
var/list/screens = list()
var/list/client_colours = list()
var/hud_type = /datum/hud
var/datum/hSB/sandbox = null
var/mob/audiovisual_redirect //Mob to redirect messages, speech, and sounds to
var/siliconaccessareas = list()
+2 -2
View File
@@ -101,10 +101,10 @@
mob.throwing.finalize(FALSE)
var/atom/movable/AM = L.pulling
if(AM && AM.density && !(L.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && !ismob(AM))
if(AM && AM.density && !SEND_SIGNAL(L, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && !ismob(AM))
L.setDir(turn(L.dir, 180))
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc)
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay)
/// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement.
/client/proc/Process_Grab()
+8 -8
View File
@@ -23,9 +23,9 @@
* Sets a mob's blindness to an amount if it was not above it already, similar to how status effects work
*/
/mob/proc/blind_eyes(amount)
var/old_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND)
eye_blind = max(eye_blind, amount)
var/new_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND)
var/old_blind = eye_blind
eye_blind = max((!eye_blind && stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : eye_blind , amount)
var/new_blind = eye_blind
if(old_blind != new_blind)
update_blindness()
@@ -36,21 +36,21 @@
*/
/mob/proc/adjust_blindness(amount)
var/old_eye_blind = eye_blind
eye_blind = max(0, eye_blind + amount)
if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND))
eye_blind = max((stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0, eye_blind + amount)
if(!old_eye_blind || !eye_blind)
update_blindness()
/**
* Force set the blindness of a mob to some level
*/
/mob/proc/set_blindness(amount)
var/old_eye_blind = eye_blind
eye_blind = max(amount, 0)
if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND))
eye_blind = max(amount, (stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0)
if(!old_eye_blind || !eye_blind)
update_blindness()
/// proc that adds and removes blindness overlays when necessary
/mob/proc/update_blindness()
if(stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND) || eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
if(stat == CONSCIOUS || stat == SOFT_CRIT)
throw_alert("blind", /obj/screen/alert/blind)
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
+3
View File
@@ -384,3 +384,6 @@
/obj/item/paper/crumpled/bloody
icon_state = "scrap_bloodied"
/obj/item/paper/crumpled/muddy
icon_state = "scrap_mud"
+2 -1
View File
@@ -4,7 +4,7 @@
name = "picture frame"
desc = "The perfect showcase for your favorite deathtrap memories."
icon = 'icons/obj/decals.dmi'
custom_materials = null
custom_materials = list(/datum/material/wood = 2000)
flags_1 = 0
icon_state = "frame-empty"
result_path = /obj/structure/sign/picture_frame
@@ -64,6 +64,7 @@
desc = "Every time you look it makes you laugh."
icon = 'icons/obj/decals.dmi'
icon_state = "frame-empty"
custom_materials = list(/datum/material/wood = 2000)
var/obj/item/photo/framed
var/persistence_id
var/can_decon = TRUE
+8 -10
View File
@@ -80,6 +80,8 @@
/// Just 'slightly' snowflakey way to modify projectile damage for projectiles fired from this gun.
var/projectile_damage_multiplier = 1
var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds
/obj/item/gun/Initialize()
. = ..()
if(no_pin_required)
@@ -213,7 +215,8 @@
var/bonus_spread = 0
var/loop_counter = 0
bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming
if(user)
bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming
if(ishuman(user) && user.a_intent == INTENT_HARM && weapon_weight <= WEAPON_LIGHT)
var/mob/living/carbon/human/H = user
for(var/obj/item/gun/G in H.held_items)
@@ -563,12 +566,7 @@
chambered = null
update_icon()
/obj/item/gun/proc/getinaccuracy(mob/living/user)
if(!isliving(user))
return FALSE
else
var/mob/living/holdingdude = user
if(istype(holdingdude) && (holdingdude.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
return 0
else
return ((weapon_weight * 25) * inaccuracy_modifier)
/obj/item/gun/proc/getinaccuracy(mob/user)
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
return ((weapon_weight * 25) * inaccuracy_modifier)
return 0
@@ -77,7 +77,6 @@
var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty")
var/datum/action/item_action/zoom_lock_action/zoom_lock_action
var/mob/listeningTo
/obj/item/gun/energy/beam_rifle/debug
delay = 0
@@ -178,7 +177,6 @@
STOP_PROCESSING(SSfastprocess, src)
set_user(null)
QDEL_LIST(current_tracers)
listeningTo = null
return ..()
/obj/item/gun/energy/beam_rifle/proc/aiming_beam(force_update = FALSE)
@@ -260,17 +258,12 @@
if(user == current_user)
return
stop_aiming(current_user)
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
listeningTo = null
if(istype(current_user))
LAZYREMOVE(current_user.mousemove_intercept_objects, src)
if(current_user)
UnregisterSignal(current_user, COMSIG_MOVABLE_MOVED)
current_user = null
if(istype(user))
current_user = user
LAZYOR(current_user.mousemove_intercept_objects, src)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
listeningTo = user
/obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
if(aiming)
@@ -351,7 +351,7 @@
name = "wooden bucket"
desc = "It's a bucket made of wood."
icon_state = "bucket_wooden"
custom_materials = null
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 2)
slot_flags = NONE
item_flags = NO_MAT_REDEMPTION
@@ -0,0 +1,247 @@
//******Decoration objects
//***Bone statues and giant skeleton parts.
/obj/structure/statue/bone
anchored = TRUE
max_integrity = 120
material_drop_type = /obj/item/stack/sheet/bone
impressiveness = 18 // Carved from the bones of a massive creature, it's going to be a specticle to say the least
layer = ABOVE_ALL_MOB_LAYER
/obj/structure/statue/bone/rib
name = "collosal rib"
desc = "It's staggering to think that something this big could have lived, let alone died."
oreAmount = 4
icon = 'icons/obj/statuelarge.dmi'
icon_state = "rib"
/obj/structure/statue/bone/skull
name = "collosal skull"
desc = "The gaping maw of a dead, titanic monster."
oreAmount = 12
icon = 'icons/obj/statuelarge.dmi'
icon_state = "skull"
/obj/structure/statue/bone/skull/half
desc = "The gaping maw of a dead, titanic monster. This one is cracked in half."
oreAmount = 6
icon = 'icons/obj/statuelarge.dmi'
icon_state = "skull-half"
//***Wasteland floor and rock turfs here.
/turf/open/floor/plating/asteroid/basalt/wasteland //Like a more fun version of living in Arizona.
name = "cracked earth"
icon = 'icons/turf/floors.dmi'
icon_state = "wasteland"
environment_type = "wasteland"
baseturfs = /turf/open/floor/plating/asteroid/basalt/wasteland
digResult = /obj/item/stack/ore/glass/basalt
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
slowdown = 0.5
floor_variance = 30
/turf/open/floor/plating/asteroid/basalt/wasteland/Initialize()
.=..()
if(prob(floor_variance))
icon_state = "[environment_type][rand(0,6)]"
/turf/closed/mineral/strong/wasteland
name = "ancient dry rock"
color = "#B5651D"
environment_type = "wasteland"
turf_type = /turf/open/floor/plating/asteroid/basalt/wasteland
baseturfs = /turf/open/floor/plating/asteroid/basalt/wasteland
smooth_icon = 'icons/turf/walls/rock_wall.dmi'
/turf/closed/mineral/strong/wasteland/drop_ores()
if(prob(10))
new /obj/item/stack/ore/iron(src, 1)
new /obj/item/stack/ore/glass(src, 1)
new /obj/effect/decal/remains/human/grave(src, 1)
else
new /obj/item/stack/sheet/bone(src, 1)
//***Oil well puddles.
/obj/structure/sink/oil_well //You're not going to enjoy bathing in this...
name = "oil well"
desc = "A bubbling pool of oil.This would probably be valuable, had bluespace technology not destroyed the need for fossil fuels 200 years ago."
icon = 'icons/obj/watercloset.dmi'
icon_state = "puddle-oil"
dispensedreagent = /datum/reagent/oil
/obj/structure/sink/oil_well/Initialize()
.=..()
create_reagents(20)
reagents.add_reagent(dispensedreagent, 20)
/obj/structure/sink/oil_well/attack_hand(mob/M)
flick("puddle-oil-splash",src)
reagents.reaction(M, TOUCH, 20) //Covers target in 20u of oil.
to_chat(M, "<span class='notice'>You touch the pool of oil, only to get oil all over yourself. It would be wise to wash this off with water.</span>")
/obj/structure/sink/oil_well/attackby(obj/item/O, mob/user, params)
flick("puddle-oil-splash",src)
if(O.tool_behaviour == TOOL_SHOVEL && !(flags_1&NODECONSTRUCT_1)) //attempt to deconstruct the puddle with a shovel
to_chat(user, "You fill in the oil well with soil.")
O.play_tool_sound(src)
deconstruct()
return 1
if(istype(O, /obj/item/reagent_containers)) //Refilling bottles with oil
var/obj/item/reagent_containers/RG = O
if(RG.is_refillable())
if(!RG.reagents.holder_full())
RG.reagents.add_reagent(dispensedreagent, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
to_chat(user, "<span class='notice'>You fill [RG] from [src].</span>")
return TRUE
to_chat(user, "<span class='notice'>\The [RG] is full.</span>")
return FALSE
if(user.a_intent != INTENT_HARM)
to_chat(user, "<span class='notice'>You won't have any luck getting \the [O] out if you drop it in the oil.</span>")
return 1
else
return ..()
/obj/structure/sink/oil_well/drop_materials()
new /obj/effect/decal/cleanable/oil(loc)
//***Grave mounds.
/obj/structure/closet/crate/grave
name = "burial mound"
desc = "An marked patch of soil, showing signs of a burial long ago. You wouldn't disturb a grave... right?"
icon = 'icons/obj/crates.dmi'
icon_state = "grave"
dense_when_open = TRUE
material_drop = /obj/item/stack/ore/glass/basalt
material_drop_amount = 5
anchorable = FALSE
anchored = TRUE
locked = TRUE
breakout_time = 900
cutting_tool = /obj/item/shovel
var/lead_tomb = FALSE
var/first_open = FALSE
/obj/structure/closet/crate/grave/PopulateContents() //GRAVEROBBING IS NOW A FEATURE
..()
new /obj/effect/decal/remains/human/grave(src)
switch(rand(1,8))
if(1)
new /obj/item/coin/gold(src)
new /obj/item/storage/wallet(src)
if(2)
new /obj/item/clothing/glasses/meson(src)
if(3)
new /obj/item/coin/silver(src)
new /obj/item/shovel/spade(src)
if(4)
new /obj/item/storage/book/bible/booze(src)
if(5)
new /obj/item/clothing/neck/stethoscope(src)
new /obj/item/scalpel(src)
new /obj/item/hemostat(src)
if(6)
new /obj/item/reagent_containers/glass/beaker(src)
new /obj/item/clothing/glasses/science(src)
if(7)
new /obj/item/clothing/glasses/sunglasses(src)
new /obj/item/clothing/mask/cigarette/rollie(src)
/obj/structure/closet/crate/grave/open(mob/living/user, obj/item/S)
if(!opened)
to_chat(user, "<span class='notice'>The ground here is too hard to dig up with your bare hands. You'll need a shovel.</span>")
else
to_chat(user, "<span class='notice'>The grave has already been dug up.</span>")
/obj/structure/closet/crate/grave/tool_interact(obj/item/S, mob/living/carbon/user)
if(user.a_intent == INTENT_HELP) //checks to attempt to dig the grave, must be done on help intent only.
if(!opened)
if(istype(S,cutting_tool) && S.tool_behaviour == TOOL_SHOVEL)
to_chat(user, "<span class='notice'>You start start to dig open \the [src] with \the [S]...</span>")
if (do_after(user,20, target = src))
opened = TRUE
locked = TRUE
dump_contents()
update_icon()
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "graverobbing", /datum/mood_event/graverobbing)
if(lead_tomb == TRUE && first_open == TRUE)
user.gain_trauma(/datum/brain_trauma/magic/stalker)
to_chat(user, "<span class='boldwarning'>Oh no, no no no, THEY'RE EVERYWHERE! EVERY ONE OF THEM IS EVERYWHERE!</span>")
first_open = FALSE
return 1
return 1
else
to_chat(user, "<span class='notice'>You can't dig up a grave with \the [S.name].</span>")
return 1
else
to_chat(user, "<span class='notice'>The grave has already been dug up.</span>")
return 1
else if((user.a_intent != INTENT_HELP) && opened) //checks to attempt to remove the grave entirely.
if(istype(S,cutting_tool) && S.tool_behaviour == TOOL_SHOVEL)
to_chat(user, "<span class='notice'>You start to remove \the [src] with \the [S].</span>")
if (do_after(user,15, target = src))
to_chat(user, "<span class='notice'>You remove \the [src] completely.</span>")
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "graverobbing", /datum/mood_event/graverobbing)
deconstruct(TRUE)
return 1
return
/obj/structure/closet/crate/grave/bust_open()
..()
opened = TRUE
update_icon()
dump_contents()
return
/obj/structure/closet/crate/grave/lead_researcher
name = "ominous burial mound"
desc = "Even in a place filled to the brim with graves, this one shows a level of preperation and planning that fills you with dread."
icon = 'icons/obj/crates.dmi'
icon_state = "grave_lead"
lead_tomb = TRUE
first_open = TRUE
/obj/structure/closet/crate/grave/lead_researcher/PopulateContents() //ADVANCED GRAVEROBBING
..()
new /obj/effect/decal/cleanable/blood/gibs/old(src)
new /obj/item/book/granter/crafting_recipe/boneyard_notes(src)
/obj/effect/decal/remains/human/grave
turf_loc_check = FALSE
/obj/item/book/granter/crafting_recipe/boneyard_notes
name = "The Complete Works of Lavaland Bone Architecture"
desc = "Pried from the lead Archaeologist's cold, dead hands, this seems to explain how ancient bone architecture was erected long ago."
crafting_recipe_types = list(/datum/crafting_recipe/rib, /datum/crafting_recipe/boneshovel, /datum/crafting_recipe/halfskull, /datum/crafting_recipe/skull)
icon = 'icons/obj/library.dmi'
icon_state = "boneworking_learing"
oneuse = FALSE
remarks = list("Who knew you could bend bones that far back?", "I guess that was much easier before the planet heated up...", "So that's how they made those ruins survive the ashstorms. Neat!", "The page is just filled with insane ramblings about some 'legion' thing.", "But why would they need vinegar to polish the bones? And rags too?", "You spend a few moments cleaning dirt and blood off of the page, yeesh.")
//***Fluff items for lore/intrigue
/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard
name = "posted warning"
desc = "It seems to be smudged with mud and... oil?"
info = "<B>TO WHOM IT MAY CONCERN</B><BR><BR>This area is property of the Nanotrasen Mining Division.<BR><BR>Trespassing in this area is illegal, highly dangerous, and subject to several NDAs.<br><br>Please turn back now, under intergalactic law section 48-R."
/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/rnd_notes
name = "Research Findings: Day 26"
desc = "Huh, this one page looks like it was torn out of a full book. How odd."
icon_state = "docs_part"
info = "<b>Researcher name:</b> B--*--* J--*s.<BR><BR>Detailed findings:<i>Today the camp site's cond-tion has wor--ene*. The ashst--ms keep blocking us off from le-ving the sit* for m-re supplies, and it's lo-king like we're out of pl*sma to p-wer the ge-erat*r. Can't rea-*y study c-*bon *ating with no li--ts, ya know? Da-*y's been going -*f again and ag-*n a-*ut h*w the company's left us to *ie here, but I j-s* keep tell-ng him to stop che*-in* out these damn graves. We m-y b* archaeologists, but -e sho*ld have t-e dec-**cy to know these grav-s are *-l NEW.</i><BR><BR><b>The rest of the page is just semantics about carbon dating methods.</b>"
/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/mutiny
name = "hastily scribbled note"
desc = "Seems like someone was in a hurry."
info = "Alright, we all know that stuck up son a bitch is just doing this to keep us satisifed. Who the hell does he think he is, taking extra rations? We're OUT OF FOOD, CARL. Tomorrow at noon, we're going to try and take the ship by force. He HAS to be lying about the engine cooling down. He HAS TO BE. I'm tellin ya, with this implant I lifted off that last supply ship, I got the smarts to get us offa this shithole. Keep your knife handy carl."
/obj/item/paper/fluff/ruins/elephant_graveyard/hypothesis
name = "research document"
desc = "Standard Nanotrasen typeface for important research documents."
info = "<b>Day 9: Tenative Conclusions</b><BR><BR>While the area appears to be of significant cultural importance to the lizard race, outside of some sparce contact with native wildlife, we're yet to find any exact reasoning for the nature of this phenomenon. It seems that organic life is communally drawn to this planet as though it functions as a final resting place for intelligent life. As per company guidelines, this site shall be given the following classification: 'LZ-0271 - Elephant Graveyard' <BR><BR><u>Compiled list of Artifact findings (Currently Sent Offsite)</u><BR>Cultist Blade Fragments: x8<BR>Brass Multiplicative Ore Sample: x105<BR>Syndicate Revolutionary Leader Implant (Broken) x1<BR>Extinct Cortical Borer Tissue Sample x1<BR>Space Carp Fossil x3"
/obj/item/paper/fluff/ruins/elephant_graveyard/final_message
name = "important looking Note"
desc = "This note is well written, and seems to have been put here so you'd find it."
info = "If you find this... you don't need to know who I am.<BR><BR>You need to leave this place. I dunno what shit they did to me out here, but I don't think I'm going to be making it out of here.<BR><BR>This place... it wears down your psyche. The other researchers out here laughed it off but... They were the first to go.<BR><BR>One by one they started turning on each other. The more they found out, the more they started fighting and arguing...<BR>As I speak now, I had to... I wound up having to put most of my men down. I know what I had to do, and I know there's no way left for me to live with myself.<BR> If anyone ever finds this, just don't touch the graves.<BR><BR>DO NOT. TOUCH. THE GRAVES. Don't be a dumbass, like we all were."
+24
View File
@@ -0,0 +1,24 @@
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+13
View File
@@ -0,0 +1,13 @@
# DMAPI Internals
This folder should be placed on it's own inside a codebase that wishes to use the TGS DMAPI. Warranty void if modified.
- [includes.dm](./includes.dm) is the file that should be included by DM code, it handles including the rest.
- The [core](./core) folder includes all code not directly part of any API version.
- The other versioned folders contain code for the different DMAPI versions.
- [v3210](./v3210) contains the final TGS3 API.
- [v4](./v4) is the legacy DMAPI 4 (Used in TGS 4.0.X versions).
- [v5](./v5) is the current DMAPI version used by TGS4 >=4.1.
- [LICENSE](./LICENSE) is the MIT license for the DMAPI.
APIs communicate with TGS in two ways. All versions implement TGS -> DM communication using /world/Topic. DM -> TGS communication, called the bridge method, is different for each version.
+8
View File
@@ -0,0 +1,8 @@
# Core DMAPI functions
This folder contains all DMAPI code not directly involved in an API.
- [_definitions.dm](./definitions.dm) contains defines needed across DMAPI internals.
- [core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code.
- [datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement.
- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition
-27
View File
@@ -154,30 +154,3 @@
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
if(api)
api.SecurityLevel()
/*
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-27
View File
@@ -55,30 +55,3 @@ TGS_PROTECT_DATUM(/datum/tgs_api)
/datum/tgs_api/proc/SecurityLevel()
return TGS_UNIMPLEMENTED
/*
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-27
View File
@@ -15,30 +15,3 @@
#include "v5\api.dm"
#include "v5\commands.dm"
#include "v5\undef.dm"
/*
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+6
View File
@@ -0,0 +1,6 @@
# DMAPI V3
This DMAPI implements bridge using file output which TGS monitors for.
- [api.dm](./api.dm) contains the bulk of the API code.
- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s.
-27
View File
@@ -226,30 +226,3 @@
#undef SERVICE_REQUEST_API_VERSION
#undef SERVICE_RETURN_SUCCESS
/*
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+1 -33
View File
@@ -19,7 +19,7 @@
TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!")
warned_command_names[command_name] = TRUE
continue
if(command_name_types[command_name])
if(warnings_only)
TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!")
@@ -44,35 +44,3 @@
user.friendly_name = sender
user.mention = sender
return stc.Run(user, params) || TRUE
/*
#undef SERVICE_JSON_PARAM_HELPTEXT
#undef SERVICE_JSON_PARAM_ADMINONLY
#undef SERVICE_JSON_PARAM_REQUIREDPARAMETERS
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+6
View File
@@ -0,0 +1,6 @@
# DMAPI V4
This DMAPI implements bridge requests using file output which TGS monitors for. It has a safe mode restriction.
- [api.dm](./api.dm) contains the bulk of the API code.
- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s.
+4 -27
View File
@@ -50,6 +50,10 @@
return new /datum/tgs_version("4.0.0.0")
/datum/tgs_api/v4/OnWorldNew(minimum_required_security_level)
if(minimum_required_security_level == TGS_SECURITY_ULTRASAFE)
TGS_WARNING_LOG("V4 DMAPI requires safe security!")
minimum_required_security_level = TGS_SECURITY_SAFE
json_path = world.params[TGS4_PARAM_INFO_JSON]
if(!json_path)
TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!")
@@ -310,30 +314,3 @@
/datum/tgs_api/v4/SecurityLevel()
return security_level
/*
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-28
View File
@@ -39,31 +39,3 @@
result = ""
return result
return "Unknown command: [command]!"
/*
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+2 -28
View File
@@ -12,13 +12,14 @@
#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5
#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier"
#define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands"
#define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage"
#define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType"
#define DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT "currentPort"
#define DMAPI5_BRIDGE_PARAMETER_VERSION "version"
#define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage"
#define DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS "customCommands"
#define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel"
#define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort"
@@ -95,30 +96,3 @@
#define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name"
#define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText"
#define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly"
/*
The MIT License
Copyright (c) 2020 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+19 -36
View File
@@ -16,7 +16,7 @@
var/list/chat_channels
/datum/tgs_api/v5/ApiVersion()
return new /datum/tgs_version("5.1.1")
return new /datum/tgs_version("5.2.1")
/datum/tgs_api/v5/OnWorldNew(minimum_required_security_level)
server_port = world.params[DMAPI5_PARAM_SERVER_PORT]
@@ -24,7 +24,7 @@
var/datum/tgs_version/api_version = ApiVersion()
version = null
var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands()))
var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands()))
if(!istype(bridge_response))
TGS_ERROR_LOG("Failed initial bridge request!")
return FALSE
@@ -201,17 +201,27 @@
if(DMAPI5_TOPIC_COMMAND_HEARTBEAT)
return TopicResponse()
if(DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH)
var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT]
var/error_message = null
if (new_port != null)
if (!isnum(new_port) || !(new_port > 0))
error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]"
else
server_port = new_port
var/new_version_string = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]
if (!istext(new_version_string))
return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]")
if(error_message != null)
error_message += ", "
error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]"
else
var/datum/tgs_version/new_version = new(new_version_string)
if (event_handler)
event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version)
var/datum/tgs_version/new_version = new(new_version_string)
if (event_handler)
event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version)
version = new_version
version = new_version
return TopicResponse()
return json_encode(list(DMAPI5_RESPONSE_ERROR_MESSAGE = error_message, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands()))
return TopicResponse("Unknown command: [command]")
@@ -343,30 +353,3 @@
/datum/tgs_api/v5/SecurityLevel()
RequireInitialBridgeResponse()
return security_level
/*
The MIT License
Copyright (c) 2020 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-28
View File
@@ -38,31 +38,3 @@
topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = text_response
return json_encode(topic_response)
return TopicResponse("Unknown custom chat command: [command]!")
/*
The MIT License
Copyright (c) 2020 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+2 -28
View File
@@ -12,13 +12,14 @@
#undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND
#undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER
#undef DMAPI5_PARAMETER_CUSTOM_COMMANDS
#undef DMAPI5_RESPONSE_ERROR_MESSAGE
#undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE
#undef DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT
#undef DMAPI5_BRIDGE_PARAMETER_VERSION
#undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE
#undef DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS
#undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL
#undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT
@@ -95,30 +96,3 @@
#undef DMAPI5_CUSTOM_CHAT_COMMAND_NAME
#undef DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT
#undef DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY
/*
The MIT License
Copyright (c) 2020 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/