more work
2
.vscode/settings.json
vendored
@@ -10,7 +10,7 @@
|
||||
"**/.pnp.*": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"workbench.editorAssociations": {
|
||||
"*.dmi": "dmiEditor.dmiEditor"
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
if(!weight_gain_rate_modifier)
|
||||
return FALSE
|
||||
|
||||
if(!iscarbon(wearer) || slot != SLOT_NECK || !wearer?.client?.prefs?.weight_gain_items)
|
||||
if(!iscarbon(wearer) || slot !=ITEM_SLOT_NECK || !wearer?.client?.prefs?.weight_gain_items)
|
||||
return FALSE
|
||||
|
||||
wearer.weight_gain_rate = wearer.weight_gain_rate * weight_gain_rate_modifier
|
||||
|
||||
wearer.weight_gain_rate = wearer.weight_gain_rate * weight_gain_rate_modifier
|
||||
|
||||
/obj/item/clothing/neck/dropped(mob/user)
|
||||
. = ..()
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
if(!iscarbon(wearer) || !(wearer.get_item_by_slot(SLOT_NECK) == src) || !wearer?.client?.prefs?.weight_gain_items)
|
||||
return FALSE
|
||||
|
||||
|
||||
wearer.weight_gain_rate = (wearer.weight_gain_rate / weight_gain_rate_modifier)
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
/obj/item/clothing/mask/gas/fattening/equipped(mob/M, slot)
|
||||
. = ..()
|
||||
if (slot == SLOT_WEAR_MASK)
|
||||
if (slot ==ITEM_SLOT_WEAR_MASK)
|
||||
if(iscarbon(M))
|
||||
C = M
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 0, "bio" = 0, "rad" = 25, "fire" = 25, "acid" = 25)
|
||||
item_color = "white"
|
||||
slowdown = 0
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
actions_types = list()
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/engine/haydee
|
||||
@@ -23,7 +23,7 @@
|
||||
actions_types = list(/datum/action/item_action/toggle_helmet)
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/haydee
|
||||
slowdown = 0
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
var/icon_location = 'GainStation13/icons/obj/clothing/haydee_modular.dmi'
|
||||
var/mob/living/carbon/U
|
||||
|
||||
|
||||
@@ -4,25 +4,22 @@
|
||||
name = "GATO Hardsuit Helmet"
|
||||
desc = "Exclusive version of a hardsuit helmet, usually reserved for GATO CC personnel."
|
||||
icon = 'GainStation13/icons/mob/head.dmi'
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/head.dmi'
|
||||
icon_state = "hardsuit0-gato"
|
||||
item_state = "hardsuit0-gato"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/head/HoS/beret/gato
|
||||
name = "GT-CC Beret"
|
||||
desc = "A robust beret for the CC personnel, for looking stylish while not sacrificing protection."
|
||||
icon = 'GainStation13/icons/mob/head.dmi'
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/head.dmi'
|
||||
icon_state = "gato_beret"
|
||||
item_state = "gato_beret"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/head/HoS/gato
|
||||
name = "GT-CC Cap"
|
||||
desc = "The robust standard-issue cap of the CC personnel."
|
||||
icon = 'GainStation13/icons/mob/head.dmi'
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/head.dmi'
|
||||
icon_state = "gato_cap"
|
||||
item_state = "gato_cap"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/suits.dmi'
|
||||
icon_state = "letterman_gato"
|
||||
item_state = "letterman_gato"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/capcarapace/cc
|
||||
name = "Elegant Carapace"
|
||||
@@ -17,7 +17,7 @@
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/suits.dmi'
|
||||
icon_state = "cc_carapace"
|
||||
item_state = "cc_carapace"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/capcarapace/gato
|
||||
name = "CC-GT Carapace"
|
||||
@@ -26,7 +26,7 @@
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/suits.dmi'
|
||||
icon_state = "gato_carapace"
|
||||
item_state = "gato_carapace"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/capcarapace/moka
|
||||
name = "Hellcat Overcoat"
|
||||
@@ -35,7 +35,7 @@
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/suits.dmi'
|
||||
icon_state = "hellcat_overcoat"
|
||||
item_state = "hellcat_overcoat"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/capcarapace/paradeblack
|
||||
name = "CC Parade Jacket"
|
||||
@@ -44,7 +44,7 @@
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/suits.dmi'
|
||||
icon_state = "paradejacket_black"
|
||||
item_state = "paradejacket_black"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/capcarapace/paradepurple
|
||||
name = "CC Parade Jacket"
|
||||
@@ -53,7 +53,7 @@
|
||||
alternate_worn_icon = 'GainStation13/icons/mob/suits.dmi'
|
||||
icon_state = "paradejacket_purple"
|
||||
item_state = "paradejacket_purple"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/alert/gato
|
||||
name = "GATO Hardsuit"
|
||||
@@ -63,4 +63,4 @@
|
||||
icon_state = "gato_hardsuit"
|
||||
item_state = "gato_hardsuit"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert/gato
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
prereq_ids = list("adv_engi", "adv_bluespace")
|
||||
design_ids = list("arcd_design")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7000)
|
||||
export_price = 7000
|
||||
|
||||
/obj/item/borg/upgrade/arcd
|
||||
name = "cyborg ARCD"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
value = 0 //ERP quirk
|
||||
gain_text = "<span class='notice'>Your body feels like it could grow at any moment.</span>"
|
||||
lose_text = "<span class='notice'>The feeling of impending growth is gone...</span>"
|
||||
category = CATEGORY_SEXUAL
|
||||
mob_trait = TRAIT_FATROUSAL
|
||||
|
||||
/datum/quirk/fatrousal/add()
|
||||
@@ -23,7 +22,7 @@
|
||||
return C.getArousalLoss()*35
|
||||
return FALSE
|
||||
|
||||
///mob/living/adjustArousalLoss(amount, updating_arousal=1)
|
||||
///mob/living/adjust_arousal(amount, updating_arousal=1)
|
||||
// if(HAS_TRAIT(src, TRAIT_FATROUSAL))
|
||||
// amount = amount * 0.2
|
||||
// ..()
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
return ..()
|
||||
|
||||
/datum/species/can_equip(obj/item/I, slot, disable_warning, mob/living/carbon/human/H, bypass_equip_delay_self)
|
||||
if(HAS_TRAIT(H, TRAIT_NO_BACKPACK) && slot == SLOT_BACK)
|
||||
if(HAS_TRAIT(H, TRAIT_NO_BACKPACK) && slot ==ITEM_SLOT_BACK)
|
||||
to_chat(H, "<span class='warning'>You are too fat to wear anything on your back.</span>")
|
||||
return FALSE
|
||||
|
||||
if(!istype(I, /obj/item/clothing/under/color/grey/modular) && HAS_TRAIT(H, TRAIT_NO_JUMPSUIT) && slot == SLOT_W_UNIFORM)
|
||||
if(!istype(I, /obj/item/clothing/under/color/grey/modular) && HAS_TRAIT(H, TRAIT_NO_JUMPSUIT) && slot ==ITEM_SLOT_W_UNIFORM)
|
||||
to_chat(H, "<span class='warning'>You are too fat to wear [I].</span>")
|
||||
return FALSE
|
||||
|
||||
if(HAS_TRAIT(H, TRAIT_NO_MISC) && (slot == SLOT_SHOES || slot == SLOT_GLOVES || slot == SLOT_WEAR_SUIT))
|
||||
if(HAS_TRAIT(H, TRAIT_NO_MISC) && (slot ==ITEM_SLOT_SHOES || slot ==ITEM_SLOT_GLOVES || slot ==ITEM_SLOT_WEAR_SUIT))
|
||||
to_chat(H, "<span class='warning'>You are too fat to wear [I].</span>")
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -7,32 +7,32 @@
|
||||
min_players = 6
|
||||
|
||||
/datum/round_event/dessert_infestation
|
||||
announceWhen = 100
|
||||
var/static/list/dessert_station_areas_blacklist = typecacheof(/area/space,
|
||||
announce_when = 100
|
||||
var/static/list/dessert_station_areas_blacklist = typecacheof(/area/space,
|
||||
/area/shuttle,
|
||||
/area/mine,
|
||||
/area/holodeck,
|
||||
/area/ruin,
|
||||
/area/hallway,
|
||||
/area/hallway/primary,
|
||||
/area/hallway/secondary,
|
||||
/area/mine,
|
||||
/area/holodeck,
|
||||
/area/ruin,
|
||||
/area/hallway,
|
||||
/area/hallway/primary,
|
||||
/area/hallway/secondary,
|
||||
/area/hallway/secondary/entry,
|
||||
/area/engine/supermatter,
|
||||
/area/engine/atmospherics_engine,
|
||||
/area/engine/engineering/reactor_core,
|
||||
/area/engine/engineering/reactor_control,
|
||||
/area/engine/supermatter,
|
||||
/area/engine/atmospherics_engine,
|
||||
/area/engine/engineering/reactor_core,
|
||||
/area/engine/engineering/reactor_control,
|
||||
/area/ai_monitored/turret_protected,
|
||||
/area/layenia/cloudlayer,
|
||||
/area/asteroid/nearstation,
|
||||
/area/science/server,
|
||||
/area/science/explab,
|
||||
/area/layenia/cloudlayer,
|
||||
/area/asteroid/nearstation,
|
||||
/area/science/server,
|
||||
/area/science/explab,
|
||||
/area/science/xenobiology,
|
||||
/area/security/processing)
|
||||
var/spawncount = 1
|
||||
fakeable = FALSE
|
||||
|
||||
/datum/round_event/dessert_infestation/setup()
|
||||
announceWhen = rand(announceWhen, announceWhen + 50)
|
||||
announce_when = rand(announce_when, announce_when + 50)
|
||||
spawncount = rand(4, 7)
|
||||
|
||||
/datum/round_event/dessert_infestation/announce(fake)
|
||||
@@ -67,11 +67,6 @@
|
||||
pickedArea = pick_n_take(eligible_areas)
|
||||
var/list/turf/t = get_area_turfs(pickedArea, SSmapping.station_start)
|
||||
for(var/turf/thisTurf in t) // now we check if it's a closed turf, cold turf or occupied turf and yeet it
|
||||
if(isopenturf(thisTurf))
|
||||
var/turf/open/tempGet = thisTurf
|
||||
if(tempGet.air.temperature <= T0C)
|
||||
t -= thisTurf
|
||||
continue
|
||||
if(isclosedturf(thisTurf))
|
||||
t -= thisTurf
|
||||
else
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
value = 0 //ERP quirk
|
||||
gain_text = "<span class='notice'>You feel like you could eat steel.</span>"
|
||||
lose_text = "<span class='notice'>Your teeth hurt too much...</span>"
|
||||
category = CATEGORY_FOOD
|
||||
mob_trait = TRAIT_METAL_CRUNCHER
|
||||
|
||||
/obj/item/stack
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
value = 0 //ERP quirk
|
||||
gain_text = "<span class='notice'>You feel absorbant.</span>"
|
||||
lose_text = "<span class='notice'>You don't feel absorbant anymore.</span>"
|
||||
category = CATEGORY_FOOD
|
||||
mob_trait = TRAIT_WATER_SPONGE
|
||||
|
||||
/datum/reagent/water/on_mob_add(mob/living/L, amount)
|
||||
@@ -28,7 +27,7 @@
|
||||
M.reagents.add_reagent(/datum/reagent/water, reac_volume/2)
|
||||
if(method == VAPOR)
|
||||
M.reagents.add_reagent(/datum/reagent/water, reac_volume/3)
|
||||
|
||||
|
||||
|
||||
/datum/reagent/water/proc/fat_hide(mob/living/carbon/user)
|
||||
return volume * 3.5
|
||||
@@ -67,7 +66,7 @@
|
||||
add_fingerprint(usr)
|
||||
attached = target
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/obj/structure/sink/process()
|
||||
if(!(get_dist(src, attached) <= 1 && isturf(attached.loc)))
|
||||
to_chat(attached, "<span class='userdanger'>[attached] is ripped from the sink!</span>") // GS13
|
||||
@@ -78,7 +77,7 @@
|
||||
attached.reagents.add_reagent(/datum/reagent/water, 5)
|
||||
else
|
||||
return PROCESS_KILL
|
||||
|
||||
|
||||
/obj/structure/sink/attack_hand(mob/living/user)
|
||||
if(attached)
|
||||
visible_message("[attached] is detached from [src]")
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
value = 0 //ERP quirk
|
||||
gain_text = "<span class='notice'>You find yourself able to weave webs.</span>"
|
||||
lose_text = "<span class='notice'>You are no longer able to weave webs.</span>"
|
||||
category = CATEGORY_SEXUAL
|
||||
mob_trait = TRAIT_WEB_WEAVER
|
||||
///What action is linked with this quirk?
|
||||
var/datum/action/innate/wrap_target/linked_action1
|
||||
@@ -20,7 +19,7 @@
|
||||
linked_action1.Remove(quirk_holder)
|
||||
linked_action2.Remove(quirk_holder)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/action/innate/wrap_target
|
||||
name = "wrap"
|
||||
desc = "encases a humanoid in a web cocoon."
|
||||
@@ -32,14 +31,14 @@
|
||||
var/mob/living/carbon/user = owner
|
||||
if(!user || !ishuman(user))
|
||||
return FALSE
|
||||
|
||||
|
||||
var/mob/living/carbon/human/target = user.pulling
|
||||
if(!target || !ishuman(target) || user.grab_state < GRAB_AGGRESSIVE) //Add a check for a bondage pref whenever that gets added in.
|
||||
to_chat(user, "<span class='warning'>You need to aggressively grab a humanoid to use this.</span>")
|
||||
return FALSE
|
||||
|
||||
if(target.wear_suit)
|
||||
var/obj/item/clothing/suit = target.wear_suit
|
||||
var/obj/item/clothing/suit = target.wear_suit
|
||||
if(istype(suit, /obj/item/clothing/suit/straight_jacket/web))
|
||||
user.visible_message("<span class='warning'>[user] begins to fully encase [target] in a cocoon!</span>", "<span class='warning'>You begin to fully encase [target] in a cocoon.</span>")
|
||||
if(!do_after_mob(user, target, 30 SECONDS))
|
||||
@@ -58,7 +57,7 @@
|
||||
new_matrix.Translate(0,16 * (cocoon_size-1))
|
||||
spawned_cocoon.transform = new_matrix
|
||||
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
user.visible_message("<span class='warning'>[user] attempts to remove [target]'s [target.wear_suit]!</span>", "<span class='warning'>You attempt to remove [target]'s [target.wear_suit].</span>")
|
||||
if(!do_after_mob(user, target, 10 SECONDS) || !target.dropItemToGround(suit))
|
||||
@@ -69,7 +68,7 @@
|
||||
return FALSE
|
||||
|
||||
user.visible_message("<span class='warning'>[user] attempts to wrap [target] inside of [wrapping]!</span>", "<span class='warning'>You attempt to wrap [target] inside of [wrapping].</span>")
|
||||
if(!do_after_mob(user, target, 20 SECONDS) || !target.equip_to_slot_if_possible(wrapping, SLOT_WEAR_SUIT, TRUE, TRUE))
|
||||
if(!do_after_mob(user, target, 20 SECONDS) || !target.equip_to_slot_if_possible(wrapping,ITEM_SLOT_WEAR_SUIT, TRUE, TRUE))
|
||||
user.visible_message("<span class='warning'>[user] fails to wrap [target] inside of [wrapping]!</span>", "<span class='warning'>You fail to wrap [target] inside of [wrapping].</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -86,10 +85,10 @@
|
||||
breakouttime = 600 //1 minute is reasonable.
|
||||
equip_delay_other = 0
|
||||
equip_delay_self = 0
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
mutantrace_variation = NONE
|
||||
|
||||
/obj/item/clothing/suit/straight_jacket/web/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
. = ..()
|
||||
if((user.get_item_by_slot(SLOT_WEAR_SUIT)) != src && !QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
|
||||
2
GainStation13/code/mobs/emote.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
/datum/emote/proc/get_sound(mob/living/user)
|
||||
return sound //by default just return this var.
|
||||
@@ -6,13 +6,13 @@
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/flatulose = 4, /datum/reagent/consumable/sodiumchloride = 0.5)
|
||||
filling_color = "#74291b"
|
||||
tastes = list("refried beans","grease" = 1)
|
||||
foodtype = MEAT
|
||||
foodtype = MEAT
|
||||
price = 3
|
||||
|
||||
//these have been ported from CHOMPstation / Virgo
|
||||
/obj/item/reagent_containers/food/snacks/doner_kebab
|
||||
name = "doner kebab"
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
desc = "A delicious sandwich-like food from ancient Earth. The meat is typically cooked on a vertical rotisserie."
|
||||
icon_state = "doner_kebab"
|
||||
trash = null
|
||||
@@ -24,7 +24,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/lasagna
|
||||
name = "lasagna"
|
||||
desc = "Meaty, tomato-y, and ready to eat-y. Favorite of cats."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "lasagna"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 10)
|
||||
filling_color = "#872020"
|
||||
@@ -34,7 +34,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/corndog
|
||||
name = "corn dog"
|
||||
desc = "A cornbread covered sausage deepfried in oil."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "corndog"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5)
|
||||
filling_color = "#df9745"
|
||||
@@ -44,7 +44,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/turkey
|
||||
name = "turkey"
|
||||
desc = "Tastes like chicken. It can be sliced!"
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "turkey"
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/turkey_leg
|
||||
slices_num = 4
|
||||
@@ -56,61 +56,61 @@
|
||||
/obj/item/reagent_containers/food/snacks/turkey_leg
|
||||
name = "turkey leg"
|
||||
desc = "Tastes like chicken."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "turkey_slice"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5)
|
||||
filling_color = "#ae6941"
|
||||
tastes = list("turkey" = 1)
|
||||
foodtype = MEAT
|
||||
foodtype = MEAT
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/brownies
|
||||
name = "brownies"
|
||||
desc = "Halfway to fudge, or halfway to cake? Who cares!"
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "brownies"
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/brownies_slice
|
||||
slices_num = 6
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 30)
|
||||
filling_color = "#392f27"
|
||||
tastes = list("chocolate" = 1)
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/brownies_slice
|
||||
name = "brownie"
|
||||
desc = "a dense, decadent chocolate brownie."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "browniesslice"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5)
|
||||
filling_color = "#392f27"
|
||||
tastes = list("chocolate" = 1)
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/brownies_cosmic
|
||||
name = "cosmic brownies"
|
||||
desc = "The power of cosmos likes within your hand."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "cosmicbrownies"
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/brownies_slice_cosmic
|
||||
slices_num = 6
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 25, /datum/reagent/medicine/omnizine = 5)
|
||||
filling_color = "#392f27"
|
||||
tastes = list("chocolate" = 1)
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/brownies_slice_cosmic
|
||||
name = "cosmic brownie"
|
||||
desc = "a dense, decadent and fun-looking chocolate brownie."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "cosmicbrownieslice"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/medicine/omnizine = 1)
|
||||
filling_color = "#392f27"
|
||||
tastes = list("chocolate" = 1)
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
foodtype = GRAIN | SUGAR | DAIRY
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/bacon_and_eggs
|
||||
name = "bacon and eggs"
|
||||
desc = "A staple of every breakfast."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "bacon_and_eggs"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 8)
|
||||
filling_color = "#e9e6e3"
|
||||
@@ -120,7 +120,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/eggmuffin
|
||||
name = "egg muffin"
|
||||
desc = "A staple of every breakfast."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "eggmuffin"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 8)
|
||||
filling_color = "#e9e6e3"
|
||||
@@ -130,7 +130,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/cinammonbun
|
||||
name = "cinammon bun"
|
||||
desc = "Careful not to have it stolen."
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
icon_state = "cinammonbun"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5)
|
||||
filling_color = "#e9e6e3"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/pizza/framewrecker
|
||||
name = "Framewrecker Pizza"
|
||||
desc = "You feel your arteries clogging just by merely looking at this monster. Is this even real, or a mere hallucination?"
|
||||
icon = 'icons/obj/food/food64x64.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/food64x64.dmi'
|
||||
icon_state = "theonepizza"
|
||||
pixel_x = -16
|
||||
pixel_y = -16
|
||||
@@ -32,7 +32,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/pizzaslice/framewrecker
|
||||
name = "Framewrecker Pizza Slice"
|
||||
desc = "This mere slice is the size of pizza on its own!"
|
||||
icon = 'icons/obj/food/ported_meals.dmi'
|
||||
icon = 'GainStation13/icons/obj/food/ported_meals.dmi'
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 60)
|
||||
icon_state = "big_mushroom_slice"
|
||||
filling_color = "#FFA500"
|
||||
|
||||
@@ -87,11 +87,11 @@
|
||||
|
||||
/datum/reagent/consumable/caloriteblessing/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_GOTTAGOFAST, type)
|
||||
L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants)
|
||||
|
||||
|
||||
/datum/reagent/consumable/caloriteblessing/on_mob_end_metabolize(mob/living/L)
|
||||
REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, type)
|
||||
L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants)
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
glass_name = "belly bloats"
|
||||
glass_desc = "The perfect mix to be big and merry with."
|
||||
shot_glass_icon_state = "shotglassbrown"
|
||||
hydration = 3
|
||||
|
||||
/datum/reagent/consumable/ethanol/belly_bloats/on_mob_life(mob/living/carbon/M)
|
||||
if(M && M?.client?.prefs.weight_gain_food) // GS13
|
||||
@@ -31,7 +30,6 @@
|
||||
glass_name = "blobby mary"
|
||||
glass_desc = "For the morbidly obese ladies and gentlemen."
|
||||
shot_glass_icon_state = "shotglassred"
|
||||
hydration = 4
|
||||
|
||||
/datum/reagent/consumable/ethanol/blobby_mary/on_mob_life(mob/living/carbon/M)
|
||||
if(M && M?.client?.prefs.weight_gain_food) // GS13
|
||||
@@ -51,7 +49,6 @@
|
||||
glass_name = "beltbuster mead"
|
||||
glass_desc = "The ambrosia of the blubbery gods."
|
||||
shot_glass_icon_state = "shotglassgold"
|
||||
hydration = 4
|
||||
|
||||
/datum/reagent/consumable/ethanol/beltbuster_mead/on_mob_life(mob/living/carbon/M)
|
||||
if(M && M?.client?.prefs.weight_gain_food) // GS13
|
||||
@@ -70,7 +67,6 @@
|
||||
glass_name = "heavy cafe"
|
||||
glass_desc = "To enjoy slow mornings with."
|
||||
shot_glass_icon_state = "shotglassbrown"
|
||||
hydration = 3
|
||||
|
||||
/datum/reagent/consumable/heavy_cafe/on_mob_life(mob/living/carbon/M)
|
||||
M.dizziness = max(0,M.dizziness-5)
|
||||
@@ -96,7 +92,6 @@
|
||||
glass_name = "fruits tea"
|
||||
glass_desc = "Goes down really easy and stays there for a long time."
|
||||
shot_glass_icon_state = "shotglassgold"
|
||||
hydration = 4
|
||||
|
||||
/datum/reagent/consumable/fruits_tea/on_mob_life(mob/living/carbon/M)
|
||||
M.dizziness = max(0,M.dizziness-2)
|
||||
@@ -123,7 +118,6 @@
|
||||
glass_name = "snakebite"
|
||||
glass_desc = "Won't hurt like a real bite, but you'll still regert drinking this."
|
||||
shot_glass_icon_state = "shotglassgreen"
|
||||
hydration = 4
|
||||
|
||||
/datum/reagent/consumable/snakebite/on_mob_life(mob/living/carbon/M)
|
||||
if(M && M?.client?.prefs.weight_gain_food) // GS13
|
||||
@@ -143,7 +137,6 @@
|
||||
glass_name = "vanilla milkshake"
|
||||
glass_desc = "Guess they fixed the milkshake machine after all, huh?"
|
||||
shot_glass_icon_state = "shotglasscream"
|
||||
hydration = 3
|
||||
|
||||
/datum/reagent/consumable/milkshake_chocolate
|
||||
name = "Chocolate Milkshake"
|
||||
@@ -156,4 +149,3 @@
|
||||
glass_name = "chocolate milkshake"
|
||||
glass_desc = "Nothing better than cream AND cocoa!"
|
||||
shot_glass_icon_state = "shotglassbrown"
|
||||
hydration = 3
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
/obj/item/reagent_containers/barrel_tank/equipped(mob/user, slot)
|
||||
..()
|
||||
if(slot != SLOT_BACK && U != null)
|
||||
if(slot !=ITEM_SLOT_BACK && U != null)
|
||||
to_chat(user, "<span class='warning'>The barrel's tube slips out of your mouth!</span>")
|
||||
U = null
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
design_ids = list("calorite_collar", "ci-nutrimentturbo", "bluespace_belt", "adipoelectric_transformer", "cookie_synthesizer", "borg_upgrade_cookiesynthesizer", "borg_upgrade_feedingtube", "ci-fatmobility")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
boost_item_paths = list(/obj/item/gun/energy/fatoray, /obj/item/gun/energy/fatoray/cannon, /obj/item/trash/fatoray_scrap1, /obj/item/trash/fatoray_scrap2)
|
||||
export_price = 5000
|
||||
hidden = TRUE
|
||||
|
||||
/datum/techweb_node/nutritech_weapons
|
||||
@@ -19,5 +18,4 @@
|
||||
design_ids = list("fatoray_weak", "fatoray_cannon_weak", "alter_ray_metabolism", "alter_ray_reverser", "borg_upgrade_fatoray", "bwomf_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||
boost_item_paths = list(/obj/item/gun/energy/fatoray, /obj/item/gun/energy/fatoray/cannon, /obj/item/trash/fatoray_scrap1, /obj/item/trash/fatoray_scrap2)
|
||||
export_price = 10000
|
||||
hidden = TRUE
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
desc = "This implant was meant to prevent people from going hungry, but due to a flaw in its designs, it permanently produces a small amount of nutriment overtime."
|
||||
icon_state = "chest_implant"
|
||||
implant_color = "#006607"
|
||||
nutrition_amount = 20 //somewhere around 5 pounds
|
||||
hunger_threshold = NUTRITION_LEVEL_FULL
|
||||
poison_amount = 10
|
||||
message = "" //no message cuz spam is annoying
|
||||
|
||||
/obj/item/organ/cyberimp/chest/mobility
|
||||
name = "Mobility Nanite Core"
|
||||
@@ -16,10 +14,11 @@
|
||||
icon_state = "chest_implant"
|
||||
implant_color = "#9034db"
|
||||
|
||||
/obj/item/organ/cyberimp/chest/mobility/Insert(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/cyberimp/chest/mobility/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
..()
|
||||
ADD_TRAIT(M, TRAIT_NO_FAT_SLOWDOWN, src)
|
||||
|
||||
/obj/item/organ/cyberimp/chest/mobility/Remove(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/cyberimp/chest/mobility/Remove(special = FALSE)
|
||||
var/mob/living/carbon/human/M = owner
|
||||
REMOVE_TRAIT(M, TRAIT_NO_FAT_SLOWDOWN, src)
|
||||
..()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/machinery/vending/gato
|
||||
name = "GATO Vending Machine"
|
||||
desc = "A GATO branded cola machine, a cute little cat is plastered onto it."
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon = 'GainStation13/icons/obj/vending.dmi'
|
||||
icon_state = "cola_black"
|
||||
product_slogans = "Meow~, time for some cola!"
|
||||
vend_reply = "Meow~ Meow~"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/machinery/vending/mealdor
|
||||
name = "Meal Vendor"
|
||||
desc = "The vending machine used by starving people. Looks like they've changed the shell, it looks cuter."
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon = 'GainStation13/icons/obj/vending.dmi'
|
||||
icon_state = "mealdor"
|
||||
product_slogans = "Are you hungry? Eat some of my food!;Be sure to eat one of our tasty treats!;Was that your stomach? Go ahead, get some food!"
|
||||
vend_reply = "Enjoy your meal."
|
||||
@@ -40,8 +40,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/cookie = 10,
|
||||
/obj/item/reagent_containers/food/snacks/salad/fruit = 15,
|
||||
/obj/item/reagent_containers/food/snacks/salad = 20,
|
||||
/obj/item/reagent_containers/food/snacks/salad/hellcobb = 10,
|
||||
/obj/item/clothing/under/cowkini = 5,
|
||||
/obj/item/reagent_containers/food/snacks/blueberry_gum = 5
|
||||
)
|
||||
premium = list(
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
icon_state = "bluespace_belt"
|
||||
item_state = "bluespace_belt"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
equip_sound = 'sound/items/equip/toolbelt_equip.ogg'
|
||||
drop_sound = 'sound/items/handling/toolbelt_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/toolbelt_pickup.ogg'
|
||||
equip_sound = 'GainStation13/sound/items/equip/toolbelt_equip.ogg'
|
||||
drop_sound = 'GainStation13/sound/items/handling/toolbelt_drop.ogg'
|
||||
pickup_sound = 'GainStation13/sound/items/handling/toolbelt_pickup.ogg'
|
||||
|
||||
/obj/item/bluespace_belt/equipped(mob/user, slot)
|
||||
..()
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
var/mob/living/carbon/U = user
|
||||
if(slot == SLOT_BELT)
|
||||
if(slot ==ITEM_SLOT_BELT)
|
||||
to_chat(U, "<span class='notice'>You put the belt around your waist and your mass begins to shrink...</span>")
|
||||
U.hider_add(src)
|
||||
else
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/obj/item/clothing/accessory/pride_pin
|
||||
name = "pride pin"
|
||||
desc = "A pride pin."
|
||||
icon_state = "pride"
|
||||
item_color = "pride"
|
||||
|
||||
/obj/item/clothing/accessory/pride_pin/bi
|
||||
name = "bisexual pride pin"
|
||||
desc = "A bisexual pride pin."
|
||||
icon_state = "pride_bi"
|
||||
item_color = "pride_bi"
|
||||
|
||||
/obj/item/clothing/accessory/pride_pin/trans
|
||||
name = "transgender pride pin"
|
||||
desc = "A transgender pride pin."
|
||||
icon_state = "pride_trans"
|
||||
item_color = "pride_trans"
|
||||
|
||||
/obj/item/clothing/accessory/pride_pin/ace
|
||||
name = "asexual pride pin"
|
||||
desc = "A asexual pride pin."
|
||||
icon_state = "pride_ace"
|
||||
item_color = "pride_ace"
|
||||
|
||||
/obj/item/clothing/accessory/pride_pin/enby
|
||||
name = "non-binary pride pin"
|
||||
desc = "A non-binary pride pin."
|
||||
icon_state = "pride_enby"
|
||||
item_color = "pride_enby"
|
||||
|
||||
/obj/item/clothing/accessory/pride_pin/pan
|
||||
name = "pansexual pride pin"
|
||||
desc = "A pansexual pride pin."
|
||||
icon_state = "pride_pan"
|
||||
item_color = "pride_pan"
|
||||
|
||||
/obj/item/clothing/accessory/pride_pin/lesbian
|
||||
name = "lesbian pride pin"
|
||||
desc = "A lesbian pride pin."
|
||||
icon_state = "pride_lesbian"
|
||||
item_color = "pride_lesbian"
|
||||
|
||||
/obj/item/clothing/accessory/pride_pin/intersex
|
||||
name = "intersex pride pin"
|
||||
desc = "A intersex pride pin."
|
||||
icon_state = "pride_intersex"
|
||||
item_color = "pride_intersex"
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/gun/fatbeam // GS13
|
||||
name = "Fatbeam Gun"
|
||||
desc = "Apparently used to treat malnourished patients from a safe distance... But we all know what it will truly be used for."
|
||||
icon = 'icons/obj/fatbeam.dmi'
|
||||
icon = 'GainStation13/icons/obj/weapons/fatbeam.dmi'
|
||||
icon_state = "fatbeam"
|
||||
item_state = "fatbeam"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
@@ -41,7 +41,7 @@
|
||||
on_beam_release(current_target)
|
||||
current_target = null
|
||||
|
||||
/obj/item/gun/fatbeam/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/fatbeam/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stan_cost = 0)
|
||||
if(isliving(user))
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
BIN
GainStation13/icons/obj/food/burgerbread.dmi
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
GainStation13/icons/obj/food/containers.dmi
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
GainStation13/icons/obj/food/donut.dmi
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
GainStation13/icons/obj/food/food.dmi
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
GainStation13/icons/obj/food/food64x64.dmi
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
GainStation13/icons/obj/food/food_ingredients.dmi
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
GainStation13/icons/obj/food/piecake.dmi
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
GainStation13/icons/obj/food/pizzaspaghetti.dmi
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
GainStation13/icons/obj/food/ported_meals.dmi
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
GainStation13/icons/obj/food/slimecookies.dmi
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
GainStation13/icons/obj/food/snowcones.dmi
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
GainStation13/icons/obj/food/soupsalad.dmi
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
GainStation13/icons/obj/vending.dmi
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
GainStation13/icons/obj/weapons/fatbeam.dmi
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
GainStation13/sound/items/equip/jumpsuit_equip.ogg
Normal file
BIN
GainStation13/sound/items/equip/toolbelt_equip.ogg
Normal file
BIN
GainStation13/sound/items/handling/toolbelt_drop.ogg
Normal file
BIN
GainStation13/sound/items/handling/toolbelt_pickup.ogg
Normal file
BIN
GainStation13/sound/items/handling/toolbox_drop.ogg
Normal file
BIN
GainStation13/sound/items/handling/toolbox_pickup.ogg
Normal file
@@ -54,6 +54,9 @@
|
||||
#define CRYOKINESIS /datum/mutation/human/cryokinesis
|
||||
#define SPIDER_WEB /datum/mutation/human/webbing
|
||||
#define CLUWNEMUT /datum/mutation/human/cluwne
|
||||
// GS13 DEFINES
|
||||
#define FATFANG /datum/mutation/human/fatfang
|
||||
#define RADFAT /datum/mutation/human/radfat
|
||||
|
||||
#define UI_CHANGED "ui changed"
|
||||
#define UE_CHANGED "ue changed"
|
||||
|
||||
@@ -261,6 +261,14 @@
|
||||
#define TRAIT_NO_FAT_SLOWDOWN "no_fat_slowdown"
|
||||
#define HELPLESSNESS_TRAIT "helplessness"
|
||||
|
||||
#define TRAIT_RADRESONANCE "radresonance" //FIX THIS LATER
|
||||
#define COMSIG_MICRO_PICKUP_FEET "micro_force_grabbed" //From /datum/element/mob_holder/micro
|
||||
#define COMSIG_MOBSIZE_CHANGED "mobsize_changed" //Adding this in so items and whatnot can check when someone changes size. -Cap'n
|
||||
|
||||
#define TRAIT_MACROPHILE "macrophile" //likes the big
|
||||
#define TRAIT_MICROPHILE "microphile" //likes the small
|
||||
#define TRAIT_APATHETIC "apathetic" //doesn't care
|
||||
|
||||
#define TRAIT_FATTER "fatter"
|
||||
#define TRAIT_VERYFAT "veryfat"
|
||||
#define TRAIT_OBESE "obese"
|
||||
|
||||
76
code/modules/hud/alert.dm
Normal file
@@ -0,0 +1,76 @@
|
||||
/obj/screen/alert/blob
|
||||
name = "Fatty Blob"
|
||||
desc = "Every last piece of your corpulent body is now plush and bloated with vast rolls of blubber. Your corpulence is such that you are akin to a gigantic, towering wad of dough."
|
||||
icon_state = "blob"
|
||||
|
||||
/obj/screen/alert/immobile
|
||||
name = "Immobile"
|
||||
desc = "Fat has taken over your body, now colossal in size and loaded with cumbersome flab. You are having a lot difficulty with moving the bulk that has set upon your body."
|
||||
icon_state = "immobile"
|
||||
|
||||
/obj/screen/alert/barelymobile
|
||||
name = "Barely Mobile"
|
||||
desc = "Your fat legs barely allow you to waddle, continuing to slow your pace with each pound that you gain. If you continue gaining weight, you might find yourself unable to move at all."
|
||||
icon_state = "barelymobile"
|
||||
|
||||
/obj/screen/alert/extremelyobese
|
||||
name = "Extremely Obese"
|
||||
desc = "In your journey through crossing further borders of obesity, your movement continues to get more and more restricted, body overcome with overwhelming amounts of adipose."
|
||||
icon_state = "extremelyobese"
|
||||
|
||||
/obj/screen/alert/morbidlyobese
|
||||
name = "Morbidly Obese"
|
||||
desc = "Every inch of you is beginning to pack away lard, making your movements awkward and clunky. If your weight gain continues, walking might become a real issue."
|
||||
icon_state = "morbobese"
|
||||
|
||||
/obj/screen/alert/obese
|
||||
name = "Obese"
|
||||
desc = "Your body is swollen with lard, and your movement is starting to be slightly hindered by your weight."
|
||||
icon_state = "obese"
|
||||
|
||||
/obj/screen/alert/veryfat
|
||||
name = "Very fat"
|
||||
desc = "You're beginning to inch closer and closer to proper obesity. Your body is starting to slightly jiggle when you move around."
|
||||
icon_state = "veryfat"
|
||||
|
||||
/obj/screen/alert/fatter
|
||||
name = "Fat"
|
||||
desc = "Clothes begin to cling onto your frame tighter and tighter, as your body begins to display first signs of fatness."
|
||||
icon_state = "fatter"
|
||||
|
||||
/obj/screen/alert/fat
|
||||
name = "Rounded"
|
||||
desc = "Your body's beginning to display the first signs of softened curves, though they're barely noticeable."
|
||||
icon_state = "fat"
|
||||
|
||||
|
||||
//GS13 - fullness alerts
|
||||
/obj/screen/alert/bloated
|
||||
name = "Bloated"
|
||||
desc = "Your stomach is starting to feel packed."
|
||||
icon_state = "Stuffed"
|
||||
|
||||
/obj/screen/alert/stuffed
|
||||
name = "Stuffed"
|
||||
desc = "Whatever you ate, you ate too much. Your stomach has stretched to accomodate its contents, forming a very obvious stuffed belly."
|
||||
icon_state = "Bloated"
|
||||
|
||||
/obj/screen/alert/beegbelly
|
||||
name = "Overfilled"
|
||||
desc = "You've somehow managed to fit even more in your stomach, barely allowing for any more room inside."
|
||||
icon_state = "beegbelly"
|
||||
|
||||
/obj/screen/alert/sated
|
||||
name = "Sated"
|
||||
desc = "You're perfectly rather sated right now."
|
||||
icon_state = "sated"
|
||||
|
||||
/obj/screen/alert/full
|
||||
name = "Full"
|
||||
desc = "You're rather full right now. Eating more food would result in weight gain."
|
||||
icon_state = "full"
|
||||
|
||||
/obj/screen/alert/hungry
|
||||
name = "Hungry"
|
||||
desc = "Some food would be good right about now."
|
||||
icon_state = "hungry"
|
||||
@@ -1225,7 +1225,7 @@
|
||||
- tweak: Air alarm All clear color changed from green to blue
|
||||
- balance: APCs are harder to destroy.
|
||||
- rscadd: Added Digitigrade versions of everything appliciable in suit.dmi
|
||||
- imageadd: Snowflake Icons weren't modified, and were given NO_MUTANTRACE_VARIATION
|
||||
- imageadd: Snowflake Icons weren't modified, and were given NONE
|
||||
- imageadd: naga and quad Taurs literally don't freeze their ass off in space anymore.
|
||||
- bugfix: Digitigrade legs will toggle on/off properly on character menue
|
||||
- bugfix: The misleading "normal" has been removed from species options
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
Putnam3145:
|
||||
- rscadd: Configurable weekly high-chaos days
|
||||
SandPoot:
|
||||
- refactor: Kills off SLOT_ in favor of ITEM_SLOT_
|
||||
- refactor: Kills offITEM_SLOT_ in favor of ITEM_SLOT_
|
||||
SandPoot and Crowbar764:
|
||||
- rscadd: TGUI for the player playtimes menu.
|
||||
bunny232:
|
||||
|
||||
6
hyperstation/code/__DEFINES/economy.dm
Normal file
@@ -0,0 +1,6 @@
|
||||
#define STARTING_PAYCHECK 50
|
||||
|
||||
//ID bank account support defines.
|
||||
#define ID_NO_BANK_ACCOUNT 0
|
||||
#define ID_FREE_BANK_ACCOUNT 1
|
||||
#define ID_LOCKED_BANK_ACCOUNT 2
|
||||
1
hyperstation/code/__DEFINES/wendigo.dm
Normal file
@@ -0,0 +1 @@
|
||||
GLOBAL_LIST_EMPTY(wendigo_soul_storages)
|
||||
10
hyperstation/code/controllers/subsystem/economy.dm
Normal file
@@ -0,0 +1,10 @@
|
||||
SUBSYSTEM_DEF(economy)
|
||||
name = "Economy"
|
||||
wait = 5 MINUTES
|
||||
init_order = INIT_ORDER_ECONOMY
|
||||
runlevels = RUNLEVEL_GAME
|
||||
flags = SS_NO_FIRE //Let's not forget this. This subsystem does not use fire and was needlessly using CPU.
|
||||
var/roundstart_paychecks = 5
|
||||
var/budget_pool = 35000
|
||||
var/list/generated_accounts = list()
|
||||
var/list/bank_accounts = list() //List of normal accounts (not department accounts)
|
||||
67
hyperstation/code/datums/actions.dm
Normal file
@@ -0,0 +1,67 @@
|
||||
//Small Sprite for borgs --Cyanosis
|
||||
//Basically the same as /small_sprite, but i'm screaming for modularization
|
||||
/datum/action/cyborg_small_sprite
|
||||
name = "Toggle Giant Sprite"
|
||||
desc = "Others will continue to see you giant."
|
||||
icon_icon = 'icons/obj/plushes.dmi'
|
||||
button_icon_state = "securityk9"
|
||||
background_icon_state = "bg_default_on" //looks techy enough
|
||||
var/designated_module as text
|
||||
var/small = FALSE
|
||||
var/small_icon = null
|
||||
var/small_icon_state = null
|
||||
var/image/icon_image
|
||||
var/i_am_wide = FALSE //transform stuff so we appear in the middle of a tile instead of between two WHEN PLUSHIE
|
||||
|
||||
/datum/action/cyborg_small_sprite/k9 //turns you into a marketable plushie
|
||||
designated_module = "Security K-9 Unit"
|
||||
small_icon = 'icons/obj/plushes.dmi'
|
||||
small_icon_state = "securityk9"
|
||||
i_am_wide = TRUE
|
||||
|
||||
/datum/action/cyborg_small_sprite/medihound
|
||||
designated_module = "MediHound"
|
||||
small_icon = 'icons/obj/plushes.dmi'
|
||||
small_icon_state = "medihound"
|
||||
i_am_wide = TRUE
|
||||
|
||||
/datum/action/cyborg_small_sprite/scrubpup
|
||||
designated_module = "Scrub Pup"
|
||||
small_icon = 'icons/obj/plushes.dmi'
|
||||
small_icon_state = "scrubpuppy"
|
||||
i_am_wide = TRUE
|
||||
|
||||
/datum/action/cyborg_small_sprite/Grant(mob/M)
|
||||
..()
|
||||
if(!owner)
|
||||
return
|
||||
update_image()
|
||||
RegisterSignal(owner, COMSIG_CYBORG_MODULE_CHANGE,PROC_REF(update_image))
|
||||
|
||||
/datum/action/cyborg_small_sprite/Remove(mob/M)
|
||||
UnregisterSignal(owner, COMSIG_CYBORG_MODULE_CHANGE)
|
||||
..()
|
||||
|
||||
/datum/action/cyborg_small_sprite/Trigger()
|
||||
if(!icon_image)
|
||||
update_image()
|
||||
if(!small)
|
||||
owner.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic, "cyborg_smallsprite", icon_image)
|
||||
else
|
||||
owner.remove_alt_appearance("cyborg_smallsprite")
|
||||
small = !small
|
||||
return TRUE
|
||||
|
||||
/datum/action/cyborg_small_sprite/proc/update_image()
|
||||
var/image/I
|
||||
if(small_icon && small_icon_state)
|
||||
I = image(icon=small_icon,icon_state=small_icon_state,loc=owner,layer=owner.layer,pixel_x=owner.pixel_x,pixel_y=owner.pixel_y)
|
||||
else
|
||||
I = image(icon=owner.icon,icon_state=owner.icon_state,loc=owner,layer=owner.layer,pixel_x=owner.pixel_x,pixel_y=owner.pixel_y)
|
||||
I.overlays = owner.overlays
|
||||
var/matrix/M = matrix() //I don't understand why, I don't want to know why, but this matrix is needed
|
||||
M.Scale(0.5) //If you ever change the borg's size, be sure to change this too
|
||||
M.Translate(8*i_am_wide, -8) //x position is for WIDE borgs. If they're not wide, this doesn't matter
|
||||
I.transform = M //also why do images have transforms
|
||||
I.override = TRUE
|
||||
icon_image = I
|
||||
105
hyperstation/code/datums/components/crafting/bounties.dm
Normal file
@@ -0,0 +1,105 @@
|
||||
|
||||
//Jay Sparrow
|
||||
//The base for this datum is found in reagent.dm
|
||||
/datum/bounty/lewd
|
||||
var/required_volume = 10
|
||||
var/shipped_volume = 0
|
||||
var/datum/reagent/wanted_reagent
|
||||
|
||||
|
||||
/datum/bounty/lewd/completion_string()
|
||||
return {"[round(shipped_volume)]/[required_volume] Units"}
|
||||
|
||||
/datum/bounty/lewd/can_claim()
|
||||
return ..() && shipped_volume >= required_volume
|
||||
|
||||
/datum/bounty/lewd/applies_to(obj/O)
|
||||
if(!istype(O, /obj/item/reagent_containers))
|
||||
return FALSE
|
||||
if(!O.reagents || !O.reagents.has_reagent(wanted_reagent.type))
|
||||
return FALSE
|
||||
if(O.flags_1 & HOLOGRAM_1)
|
||||
return FALSE
|
||||
return shipped_volume < required_volume
|
||||
|
||||
/datum/bounty/lewd/ship(obj/O)
|
||||
if(!applies_to(O))
|
||||
return
|
||||
shipped_volume += O.reagents.get_reagent_amount(wanted_reagent.type)
|
||||
if(shipped_volume > required_volume)
|
||||
shipped_volume = required_volume
|
||||
|
||||
/datum/bounty/lewd/compatible_with(other_bounty)
|
||||
return TRUE //Not a lot of different reagents right now, so no sense in closing these off.
|
||||
|
||||
/datum/bounty/lewd/fluid
|
||||
name = "Discretionary Bounty"
|
||||
reward = 1500
|
||||
|
||||
datum/bounty/lewd/fluid/New() //GS13 made some edits here that changes stuff into fatty-related junk
|
||||
var/reagent_type
|
||||
switch(rand(1, 20)) //So we can set probabilities for each kind
|
||||
if(1,2,3,4,5)//Nutriment bounty
|
||||
required_volume = 200
|
||||
reagent_type = /datum/reagent/consumable/nutriment
|
||||
wanted_reagent = new reagent_type
|
||||
name = wanted_reagent.name
|
||||
description = "CentCom's food lab requires more nutriment to experiment with."
|
||||
reward += rand(2, 7) * 500
|
||||
if(6,7) //Big nutriment bounty
|
||||
required_volume = 1000
|
||||
reagent_type = /datum/reagent/consumable/nutriment
|
||||
wanted_reagent = new reagent_type
|
||||
name = wanted_reagent.name
|
||||
description = "CentCom's food lab have requested vast amounts of nutriment for undisclosed purposes."
|
||||
reward += rand(10, 17) * 500
|
||||
if(8,9,10,11,12) //Milk
|
||||
required_volume = 200
|
||||
reagent_type = /datum/reagent/consumable/milk
|
||||
wanted_reagent = new reagent_type
|
||||
name = wanted_reagent.name
|
||||
description = "CentCom's kitchen is low on dairy, and this station always seems to have plenty for some reason. Mind sending us some?"
|
||||
reward += rand(2, 7) * 500
|
||||
if(13,14) //Mega Milk
|
||||
required_volume = 1000
|
||||
reagent_type = /datum/reagent/consumable/milk
|
||||
wanted_reagent = new reagent_type
|
||||
name = wanted_reagent.name
|
||||
description = "The GATO annual bake sale is soon, and all of our milk has expired. Help us out."
|
||||
reward += rand(10, 17) * 500 //Milk is generally easier to get. Make the reward a little lower.
|
||||
if(15,16) //A little romance
|
||||
var/static/list/possible_reagents = list(\
|
||||
/datum/reagent/drug/aphrodisiac,\
|
||||
/datum/reagent/consumable/ethanol/between_the_sheets,\
|
||||
/datum/reagent/drug/aphrodisiacplus,\
|
||||
/datum/reagent/lube)
|
||||
required_volume = 30
|
||||
reagent_type = pick(possible_reagents)
|
||||
wanted_reagent = new reagent_type
|
||||
name = wanted_reagent.name
|
||||
description = "A CentCom official wants something to spice up the bedroom. We told them this was a misuse of their power. It went through anyways."
|
||||
reward += rand(0, 5) * 500
|
||||
if(17,18,19,20) //Not as popular of a fluid, so we will leave it the lowest chance.
|
||||
required_volume = 50
|
||||
reagent_type = /datum/reagent/consumable/lipoifier
|
||||
wanted_reagent = new reagent_type
|
||||
name = wanted_reagent.name
|
||||
description = "The quality of GATO's meat-related products have diminished. Send us some lipoifier to help with meat production."
|
||||
reward += rand(2, 7) * 500
|
||||
|
||||
/* //Just not getting this to work.
|
||||
//Freeform sales
|
||||
/datum/export/lewd/reagent_container
|
||||
cost = 0 //Base cost of canister. We only care about what's inside.
|
||||
unit_name = "Fluid Container"
|
||||
export_types = list(/obj/item/reagent_containers/)
|
||||
/datum/export/lewd/reagent_containers/get_cost(obj/O)
|
||||
var/obj/item/reagent_containers/C = O
|
||||
var/worth = 0
|
||||
var/fluids = C.reagents.reagent_list
|
||||
|
||||
worth += fluids[/datum/reagent/consumable/semen]*2
|
||||
worth += fluids[/datum/reagent/consumable/milk]*2
|
||||
worth += fluids[/datum/reagent/consumable/femcum]*5
|
||||
return worth
|
||||
*/
|
||||
46
hyperstation/code/datums/components/crafting/recipes.dm
Normal file
@@ -0,0 +1,46 @@
|
||||
/datum/crafting_recipe/milking_machine
|
||||
name = "Milking Machine"
|
||||
reqs = list(/obj/item/stack/cable_coil = 5, /obj/item/stack/rods = 2, /obj/item/stack/sheet/cardboard = 1, /obj/item/reagent_containers/glass/beaker = 2, /obj/item/stock_parts/manipulator = 1)
|
||||
result = /obj/item/milking_machine
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/milking_machine/penis
|
||||
name = "Penis Milking Machine"
|
||||
reqs = list(/obj/item/stack/cable_coil = 5, /obj/item/stack/rods = 1, /obj/item/stack/sheet/cardboard = 1, /obj/item/reagent_containers/glass/beaker/large = 1, /obj/item/stock_parts/manipulator = 1)
|
||||
result = /obj/item/milking_machine/penis
|
||||
|
||||
//to do: put carpentry in it's own crafting tab
|
||||
/datum/crafting_recipe/weak_metal
|
||||
name = "Heated Metal"
|
||||
reqs = list(/obj/item/stack/sheet/metal = 5)
|
||||
tools = list(TOOL_WELDER)
|
||||
category = CAT_CARPENTRY
|
||||
result = /obj/item/processed/metal
|
||||
|
||||
/datum/crafting_recipe/processed_wood
|
||||
name = "Processable Wood"
|
||||
reqs = list(/obj/item/stack/sheet/mineral/wood = 5)
|
||||
tools = list(TOOL_WIRECUTTER, TOOL_WELDER)
|
||||
category = CAT_CARPENTRY
|
||||
result = /obj/item/processed/wood/plank
|
||||
|
||||
/datum/crafting_recipe/stool_base
|
||||
name = "Stool Base"
|
||||
reqs = list(/obj/item/processed/wood/seat = 1, /obj/item/processed/wood/gluepeg = 4)
|
||||
category = CAT_CARPENTRY
|
||||
result = /obj/item/processed/wood/stool1
|
||||
|
||||
/datum/crafting_recipe/clothcushion
|
||||
name = "Cloth Cushion"
|
||||
reqs = list(/obj/item/stack/sheet/cloth = 2, /obj/item/stack/sheet/cotton = 5)
|
||||
tools = list(TOOL_WIRECUTTER)
|
||||
category = CAT_CARPENTRY
|
||||
result = /obj/item/cushion
|
||||
|
||||
/datum/crafting_recipe/silkcushion
|
||||
name = "Silk Cushion"
|
||||
reqs = list(/obj/item/stack/sheet/silk = 2, /obj/item/stack/sheet/cotton = 5)
|
||||
tools = list(TOOL_WIRECUTTER)
|
||||
category = CAT_CARPENTRY
|
||||
result = /obj/item/cushion/silk
|
||||
191
hyperstation/code/datums/elements/holder_micro.dm
Normal file
@@ -0,0 +1,191 @@
|
||||
/datum/element/mob_holder/micro
|
||||
|
||||
/datum/element/mob_holder/micro/Attach(datum/target, _worn_state, _alt_worn, _right_hand, _left_hand, _inv_slots = NONE, _proctype)
|
||||
. = ..()
|
||||
|
||||
if(!isliving(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
worn_state = _worn_state
|
||||
alt_worn = _alt_worn
|
||||
right_hand = _right_hand
|
||||
left_hand = _left_hand
|
||||
inv_slots = _inv_slots
|
||||
proctype = _proctype
|
||||
|
||||
RegisterSignal(target, COMSIG_CLICK_ALT,PROC_REF(mob_try_pickup_micro), override = TRUE)
|
||||
RegisterSignal(target, COMSIG_PARENT_EXAMINE,PROC_REF(on_examine), override = TRUE)
|
||||
RegisterSignal(target, COMSIG_MICRO_PICKUP_FEET,PROC_REF(mob_pickup_micro_feet))
|
||||
|
||||
/datum/element/mob_holder/micro/Detach(datum/source, force)
|
||||
. = ..()
|
||||
UnregisterSignal(source, COMSIG_CLICK_ALT)
|
||||
UnregisterSignal(source, COMSIG_PARENT_EXAMINE)
|
||||
UnregisterSignal(source, COMSIG_MICRO_PICKUP_FEET)
|
||||
|
||||
/datum/element/mob_holder/micro/proc/mob_pickup_micro(mob/living/source, mob/user)
|
||||
var/obj/item/clothing/head/mob_holder/micro/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
|
||||
if(!holder)
|
||||
return
|
||||
user.put_in_hands(holder)
|
||||
return
|
||||
|
||||
//shoehorned (get it?) and lazy way to do instant foot pickups cause haha funny.
|
||||
/datum/element/mob_holder/micro/proc/mob_pickup_micro_feet(mob/living/source, mob/user)
|
||||
var/obj/item/clothing/head/mob_holder/micro/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
|
||||
if(!holder)
|
||||
return
|
||||
user.equip_to_slot(holder,ITEM_SLOT_SHOES)
|
||||
return
|
||||
|
||||
/datum/element/mob_holder/micro/proc/mob_try_pickup_micro(mob/living/source, mob/user)
|
||||
if(!ishuman(user) || !user.Adjacent(source) || user.incapacitated())
|
||||
return FALSE
|
||||
if(abs(user.get_effective_size()/source.get_effective_size()) < 2.0 )
|
||||
to_chat(user, "<span class='warning'>They're too big to pick up!</span>")
|
||||
return FALSE
|
||||
if(user.get_active_held_item())
|
||||
to_chat(user, "<span class='warning'>Your hands are full!</span>")
|
||||
return FALSE
|
||||
if(source.buckled)
|
||||
to_chat(user, "<span class='warning'>[source] is buckled to something!</span>")
|
||||
return FALSE
|
||||
if(source == user)
|
||||
to_chat(user, "<span class='warning'>You can't pick yourself up.</span>")
|
||||
return FALSE
|
||||
source.visible_message("<span class='warning'>[user] starts picking up [source].</span>", \
|
||||
"<span class='userdanger'>[user] starts picking you up!</span>")
|
||||
var/p = abs(source.get_effective_size()/user.get_effective_size() * 40) //Scale how fast the pickup will be depending on size difference
|
||||
if(!do_after(user, p, target = source))
|
||||
return FALSE
|
||||
|
||||
if(user.get_active_held_item()||source.buckled)
|
||||
return FALSE
|
||||
|
||||
source.visible_message("<span class='warning'>[user] picks up [source]!</span>", \
|
||||
"<span class='userdanger'>[user] picks you up!</span>")
|
||||
to_chat(user, "<span class='notice'>You pick [source] up.</span>")
|
||||
source.drop_all_held_items()
|
||||
mob_pickup_micro(source, user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro
|
||||
name = "micro"
|
||||
desc = "Another person, small enough to fit in your hand."
|
||||
icon = null
|
||||
icon_state = ""
|
||||
slot_flags = ITEM_SLOT_FEET | ITEM_SLOT_HEAD | ITEM_SLOT_ID | ITEM_SLOT_BACK | ITEM_SLOT_NECK
|
||||
w_class = null //handled by their size
|
||||
can_head = TRUE
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
|
||||
. = ..()
|
||||
|
||||
if(M)
|
||||
M.setDir(SOUTH)
|
||||
held_mob = M
|
||||
M.forceMove(src)
|
||||
appearance = M.appearance
|
||||
name = M.name
|
||||
desc = M.desc
|
||||
assimilate(M)
|
||||
|
||||
if(_can_head_override)
|
||||
can_head = _can_head_override
|
||||
if(alt_worn)
|
||||
alternate_worn_icon = alt_worn
|
||||
if(_worn_state)
|
||||
item_state = _worn_state
|
||||
icon_state = _worn_state
|
||||
if(lh_icon)
|
||||
lefthand_file = lh_icon
|
||||
if(rh_icon)
|
||||
righthand_file = rh_icon
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/Destroy()
|
||||
if(held_mob)
|
||||
release()
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/dropped()
|
||||
..()
|
||||
if(isturf(loc))//don't release on soft-drops
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/relaymove(mob/user)
|
||||
return
|
||||
|
||||
//TODO: add a timer to escape someone's grip dependant on size diff
|
||||
/obj/item/clothing/head/mob_holder/micro/container_resist(mob/living/user)
|
||||
if(user.incapacitated())
|
||||
to_chat(user, "<span class='warning'>You can't escape while you're restrained like this!</span>")
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
var/mob/living/L = loc
|
||||
visible_message("<span class='warning'>[src] begins to squirm in [L]'s grasp!</span>")
|
||||
if(!do_after(user, 100, target = src))
|
||||
to_chat(loc, "<span class='warning'>[src] stops resisting.</span>")
|
||||
return
|
||||
visible_message("<span class='warning'>[src] escapes [L]!")
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/assume_air(datum/gas_mixture/env)
|
||||
var/atom/location = loc
|
||||
if(!loc)
|
||||
return //null
|
||||
var/turf/T = get_turf(loc)
|
||||
while(location != T)
|
||||
location = location.loc
|
||||
if(ismob(location))
|
||||
return location.loc.assume_air(env)
|
||||
return location.assume_air(env)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/remove_air(amount)
|
||||
var/atom/location = loc
|
||||
if(!loc)
|
||||
return //null
|
||||
var/turf/T = get_turf(loc)
|
||||
while(location != T)
|
||||
location = location.loc
|
||||
if(ismob(location))
|
||||
return location.loc.remove_air(amount)
|
||||
return location.remove_air(amount)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/examine(var/mob/user)
|
||||
for(var/mob/living/M in contents)
|
||||
M.examine(user)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/MouseDrop(mob/M as mob)
|
||||
..()
|
||||
if(M != usr) return
|
||||
if(usr == src) return
|
||||
if(!Adjacent(usr)) return
|
||||
if(istype(M,/mob/living/silicon/ai)) return
|
||||
for(var/mob/living/carbon/human/O in contents)
|
||||
O.show_inv(usr)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/attack_self(var/mob/living/user)
|
||||
if(cooldown < world.time)
|
||||
for(var/mob/living/carbon/human/M in contents)
|
||||
cooldown = world.time + 15
|
||||
if(user.a_intent == "harm") //TO:DO, rework all of these interactions to be a lot more in depth
|
||||
visible_message("<span class='danger'> [user] slams their fist down on [M]!</span>")
|
||||
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
|
||||
M.adjustBruteLoss(5)
|
||||
return
|
||||
if(user.a_intent == "disarm")
|
||||
visible_message("<span class='danger'> [user] pins [M] down with a finger!</span>")
|
||||
playsound(loc, 'sound/effects/bodyfall1.ogg', 50, 1)
|
||||
M.adjustStaminaLoss(10)
|
||||
return
|
||||
if(user.a_intent == "grab")
|
||||
visible_message("<span class='danger'> [user] squeezes their fist around [M]!</span>")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1)
|
||||
M.adjustOxyLoss(5)
|
||||
return
|
||||
M.help_shake_act(user)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/micro/attacked_by(obj/item/I, mob/living/user)
|
||||
for(var/mob/living/carbon/human/M in contents)
|
||||
M.attacked_by(I, user)
|
||||
96
hyperstation/code/datums/ert_hazard_cleanup.dm
Normal file
@@ -0,0 +1,96 @@
|
||||
//This file contains everything to spawn ERT for cleaning up a nuclear reactor meltdown, if those things could actually explode
|
||||
|
||||
//ERT
|
||||
/datum/ert/cleanup
|
||||
rename_team = "Emergency Cleanup Crew"
|
||||
code = "Blue" //CC probably wouldn't know if it was sabotage or not, but nuclear waste is a hazard to personnel
|
||||
mission = "Remove all nuclear residue from X station"
|
||||
enforce_human = FALSE
|
||||
opendoors = FALSE
|
||||
polldesc = "a Sanitation Expert in nuclear waste"
|
||||
teamsize = 3 //2 is not enough for such a big area, 4 is too much
|
||||
leader_role = /datum/antagonist/ert/cleanup
|
||||
roles = list(/datum/antagonist/ert/cleanup)
|
||||
|
||||
/datum/ert/cleanup/New()
|
||||
mission = "Remove all nuclear waste on [station_name()]."
|
||||
|
||||
//Antag mind & team (for objectives on what to do)
|
||||
/datum/antagonist/ert/cleanup
|
||||
name = "Nuclear Waste Expert"
|
||||
role = "Nuclear Waste Expert"
|
||||
ert_team = /datum/team/ert/cleanup
|
||||
outfit = /datum/outfit/ert/cleanup
|
||||
|
||||
/datum/antagonist/ert/cleanup/greet()
|
||||
//\an [name] because modularization is nice
|
||||
to_chat(owner, "You are \an [name].\n\
|
||||
Your job is to remove all nuclear waste and residue contaminants from [station_name()], \
|
||||
under orders of GATO's Crew Health and Safety Division, as formerly as possible.\n\
|
||||
You are not required to repair any construction damages, as you are not equipped for such.")
|
||||
|
||||
/datum/team/ert/cleanup
|
||||
mission = "Remove all nuclear waste aboard the station."
|
||||
objectives = list("Remove all nuclear waste aboard the station.")
|
||||
|
||||
//Outfit
|
||||
/datum/outfit/ert/cleanup
|
||||
name = "Emergency Cleanup Technician"
|
||||
id = /obj/item/card/id/ert/Engineer/cleanup
|
||||
uniform = /obj/item/clothing/under/rank/chief_engineer
|
||||
suit = /obj/item/clothing/suit/space/hardsuit/rd/hev/no_sound/nuclear_sanitation
|
||||
glasses = /obj/item/clothing/glasses/meson/engine
|
||||
back = /obj/item/storage/backpack/industrial
|
||||
gloves = /obj/item/clothing/gloves/color/yellow/nuclear_sanitation
|
||||
shoes = /obj/item/clothing/shoes/jackboots/nuclear_sanitation
|
||||
suit_store = /obj/item/tank/internals/emergency_oxygen/engi
|
||||
belt = /obj/item/gun/energy/e_gun/advtaser
|
||||
backpack_contents = list(/obj/item/storage/firstaid/radbgone=2,
|
||||
/obj/item/storage/firstaid/toxin=1,
|
||||
/obj/item/jawsoflife=1,
|
||||
/obj/item/shovel=1,
|
||||
/obj/item/geiger_counter=1)
|
||||
|
||||
/datum/outfit/ert/cleanup/New()
|
||||
if(prob(30))
|
||||
l_hand = /obj/item/inducer/sci/combat //A whole engine gets destroyed, so add a nice inducer to help charge areas back up
|
||||
. = ..()
|
||||
|
||||
//Clothes
|
||||
/obj/item/radio/headset/headset_cent/cleanup
|
||||
icon_state = "rob_headset" //cause it looks fancy
|
||||
keyslot = new /obj/item/encryptionkey/headset_eng
|
||||
|
||||
/obj/item/card/id/ert/Engineer/cleanup
|
||||
registered_name = "Waste Expert"
|
||||
assignment = "Emergency Cleanup Technician"
|
||||
|
||||
/obj/item/card/id/ert/Engineer/cleanup/Initialize(mapload)
|
||||
access = get_ert_access("eng")+get_region_accesses(1)+get_region_accesses(5)+get_region_accesses(7) //CC eng, general, engineering, and command
|
||||
|
||||
/obj/item/clothing/gloves/color/yellow/nuclear_sanitation
|
||||
name = "thick gloves"
|
||||
desc = "A pair of yellow gloves. They help protect from radiation."
|
||||
siemens_coefficient = 0.85
|
||||
permeability_coefficient = 0.7
|
||||
cold_protection = HANDS
|
||||
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
|
||||
heat_protection = HANDS
|
||||
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 20, "rad" = 100, "fire" = 0, "acid" = 50)
|
||||
item_color = "chief"
|
||||
|
||||
/obj/item/clothing/shoes/jackboots/nuclear_sanitation
|
||||
desc = "A pair of jackboots, sewn with special material to help protect from radiation."
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 5, "bomb" = 5, "bio" = 0, "rad" = 100, "fire" = 10, "acid" = 70)
|
||||
item_color = "chief"
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/rd/hev/no_sound/nuclear_sanitation
|
||||
name = "improved radiation suit"
|
||||
desc = "A radiation suit that's been manufactured for being a hardsuit. It provides complete protection from radiation and bio contaminants."
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/rd/hev/no_scanner/nuclear_sanitation
|
||||
slowdown = 0.7 //removes 30% of the slowness. This is actually a considerable amount
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/rd/hev/no_scanner/nuclear_sanitation
|
||||
name = "improved radiation hood"
|
||||
desc = "It protects from radiation and bio contaminants."
|
||||
29
hyperstation/code/datums/mood_events/events.dm
Normal file
@@ -0,0 +1,29 @@
|
||||
/datum/mood_event/heatneed
|
||||
description = "<span class='warning'>I need someone to satisfy me, my heat is driving me crazy.</span>\n"
|
||||
mood_change = -3
|
||||
timeout = 2 MINUTES
|
||||
|
||||
/datum/mood_event/heat
|
||||
description = "<span class='userlove'>I have satisfied my heat, and I'm filled with happiness!</span>\n"
|
||||
mood_change = 3
|
||||
timeout = 5 MINUTES
|
||||
|
||||
/datum/mood_event/kiss
|
||||
description = "<span class='nicegreen'>Someone kissed me, I feel happy!</span>\n"
|
||||
mood_change = 2
|
||||
timeout = 3 MINUTES
|
||||
|
||||
/datum/mood_event/deathsaw
|
||||
description = "<span class='boldwarning'>I saw someone die!</span>\n"
|
||||
mood_change = -5
|
||||
timeout = 20 MINUTES //May be fine tuned in the future.
|
||||
|
||||
/datum/mood_event/healsbadman
|
||||
description = "<span class='warning'>I feel like I'm held together by flimsy string, and could fall apart at any moment!</span>\n"
|
||||
mood_change = -4
|
||||
timeout = 2 MINUTES
|
||||
|
||||
/datum/mood_event/copium
|
||||
description = "<span class='nicegreen'>Things are going to be okay, right?</span>\n"
|
||||
mood_change = 3
|
||||
timeout = 3 MINUTES
|
||||
8
hyperstation/code/datums/ruins/lavaland.dm
Normal file
@@ -0,0 +1,8 @@
|
||||
/datum/map_template/ruin/lavaland/duohermit
|
||||
name = "Makeshift Big Shelter"
|
||||
id = "duohermitcave"
|
||||
description = "A place of shelter for a couple of stranded hermits, scraping by to live another day."
|
||||
suffix = "lavaland_surface_duohermit.dmm"
|
||||
allow_duplicates = FALSE
|
||||
never_spawn_with = list(/datum/map_template/ruin/lavaland/hermit)
|
||||
cost = 5
|
||||
63
hyperstation/code/datums/traits/good.dm
Normal file
@@ -0,0 +1,63 @@
|
||||
/datum/quirk/narsianspeaker
|
||||
name = "Nar-Sian speaker"
|
||||
desc = "Obsessed with forbidden knowledge regarding the blood cult, you've learned how to speak their ancient language."
|
||||
value = 1
|
||||
category = CATEGORY_LANGUAGES
|
||||
gain_text = "<span class='notice'>Your mind feels sensitive to the slurred, ancient language of Nar'Sian cultists.</span>"
|
||||
lose_text = "<span class='notice'>You forget how to speak Nar'Sian!</span>"
|
||||
|
||||
/datum/quirk/narsianspeaker/add()
|
||||
var/mob/living/M = quirk_holder
|
||||
M.grant_language(/datum/language/narsie)
|
||||
|
||||
/datum/quirk/narsianspeaker/remove()
|
||||
if(quirk_holder)
|
||||
quirk_holder.remove_language(/datum/language/ratvar)
|
||||
|
||||
/datum/quirk/ratvarianspeaker
|
||||
name = "Ratvarian speaker"
|
||||
desc = "Obsessed with the inner workings of the clock cult, you've learned how to speak their language."
|
||||
value = 1
|
||||
category = CATEGORY_LANGUAGES
|
||||
gain_text = "<span class='notice'>Your mind feels sensitive to the ancient language of Ratvarian cultists.</span>"
|
||||
lose_text = "<span class='notice'>You forget how to speak Ratvarian!</span>"
|
||||
|
||||
/datum/quirk/ratvarianspeaker/add()
|
||||
var/mob/living/M = quirk_holder
|
||||
M.grant_language(/datum/language/ratvar)
|
||||
|
||||
/datum/quirk/ratvarianspeaker/remove()
|
||||
if(quirk_holder)
|
||||
quirk_holder.remove_language(/datum/language/ratvar)
|
||||
|
||||
/datum/quirk/encodedspeaker
|
||||
name = "Encoded Audio speaker"
|
||||
desc = "You've been augmented with language encoders, allowing you to understand encoded audio."
|
||||
value = 1
|
||||
category = CATEGORY_LANGUAGES
|
||||
gain_text = "<span class='notice'>Your mouth feels a little weird for a moment as your language encoder kicks in.</span>"
|
||||
lose_text = "<span class='notice'>You feel your encoded audio chip malfunction. You can no longer speak or understand the language of fax machines.</span>"
|
||||
|
||||
/datum/quirk/encodedspeaker/add()
|
||||
var/mob/living/M = quirk_holder
|
||||
M.grant_language(/datum/language/machine)
|
||||
|
||||
/datum/quirk/encodedspeaker/remove()
|
||||
if(quirk_holder)
|
||||
quirk_holder.remove_language(/datum/language/ratvar)
|
||||
|
||||
/datum/quirk/xenospeaker
|
||||
name = "Xenocommon speaker"
|
||||
desc = "Through time observing and interacting with xenos and xeno hybrids, you've learned the intricate hissing patterns of their language."
|
||||
value = 1
|
||||
category = CATEGORY_LANGUAGES
|
||||
gain_text = "<span class='notice'>You feel that you are now able to hiss in the same way xenomorphs do.</span>"
|
||||
lose_text = "<span class='notice'>You seem to no longer know how to speak xenocommon.</span>"
|
||||
|
||||
/datum/quirk/xenospeaker/add()
|
||||
var/mob/living/M = quirk_holder
|
||||
M.grant_language(/datum/language/xenocommon)
|
||||
|
||||
/datum/quirk/xenospeaker/remove()
|
||||
if(quirk_holder)
|
||||
quirk_holder.remove_language(/datum/language/ratvar)
|
||||
47
hyperstation/code/datums/traits/neutral.dm
Normal file
@@ -0,0 +1,47 @@
|
||||
//Skyrat port start
|
||||
/datum/quirk/alcohol_lightweight
|
||||
name = "Alcoholic Lightweight"
|
||||
desc = "Alcohol really goes straight to your head, gotta be careful with what you drink."
|
||||
value = 0
|
||||
category = CATEGORY_ALCOHOL
|
||||
mob_trait = TRAIT_ALCOHOL_LIGHTWEIGHT
|
||||
gain_text = "<span class='notice'>You feel woozy thinking of alcohol.</span>"
|
||||
lose_text = "<span class='notice'>You regain your stomach for drinks.</span>"
|
||||
//Skyrat port stop
|
||||
|
||||
/datum/quirk/cursed_blood
|
||||
name = "Cursed Blood"
|
||||
desc = "Your lineage is cursed with the paleblood curse. Best to stay away from holy water... Hell water, on the other hand..."
|
||||
value = 0
|
||||
category = CATEGORY_GAMEPLAY
|
||||
mob_trait = TRAIT_CURSED_BLOOD
|
||||
gain_text = "<span class='notice'>A curse from a land where men return as beasts runs deep in your blood. Best to stay away from holy water... Hell water, on the other hand...</span>"
|
||||
lose_text = "<span class='notice'>You feel the weight of the curse in your blood finally gone.</span>"
|
||||
medical_record_text = "Patient suffers from an unknown type of aversion to holy reagents. Keep them away from a chaplain."
|
||||
|
||||
/datum/quirk/inheat
|
||||
name = "In Heat"
|
||||
desc = "Your system burns with the desire to be bred, your body will betray you and alert others' to your desire when examining you. Satisfying your lust will make you happy, but ignoring it may cause you to become sad and needy."
|
||||
value = 0
|
||||
category = CATEGORY_SEXUAL
|
||||
mob_trait = TRAIT_HEAT
|
||||
gain_text = "<span class='notice'>You body burns with the desire to be bred.</span>"
|
||||
lose_text = "<span class='notice'>You feel more in control of your body and thoughts.</span>"
|
||||
|
||||
/datum/quirk/macrophile
|
||||
name = "Macrophile"
|
||||
desc = "You are attracted to larger people, and being stepped on by them."
|
||||
value = 0
|
||||
category = CATEGORY_SEXUAL
|
||||
mob_trait = TRAIT_MACROPHILE
|
||||
gain_text = "<span class='notice'>You feel attracted to people larger than you."
|
||||
lose_text = "<span class='notice'>You feel less attracted to people larger than you."
|
||||
|
||||
/datum/quirk/microphile
|
||||
name = "Microphile"
|
||||
desc = "You are attracted to smaller people, and stepping on them."
|
||||
value = 0
|
||||
category = CATEGORY_SEXUAL
|
||||
mob_trait = TRAIT_MICROPHILE
|
||||
gain_text = "<span class='notice'>You feel attracted to people smaller than you."
|
||||
lose_text = "<span class='notice'>You feel less attracted to people smaller than you."
|
||||
93
hyperstation/code/datums/weather/oxygen_rain.dm
Normal file
@@ -0,0 +1,93 @@
|
||||
//GS13 Edit
|
||||
/*
|
||||
/datum/weather/oxygen_rain
|
||||
name = "oxygen rain"
|
||||
desc = "The weather of Layenia can be quite unpredictable. Given the natural low temperature of Layenia, the formation of natural croxygenic liquid gases is possible."
|
||||
|
||||
telegraph_duration = 300
|
||||
telegraph_message = "<span class='boldwarning'>Oxygen clouds condense above and around the station...</span>"
|
||||
telegraph_overlay = "rain_med"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Liquid oxygen pours down around you! It's freezing!</i></span>"
|
||||
weather_overlay = "rain_high"
|
||||
weather_duration_lower = 1200
|
||||
weather_duration_upper = 4000
|
||||
|
||||
end_duration = 300
|
||||
end_message = "<span class='boldannounce'>The downpour gradually slows to a light shower before fading away...</span>"
|
||||
end_overlay = "rain_low"
|
||||
|
||||
area_type = /area/layenia
|
||||
target_trait = ZTRAIT_STATION
|
||||
|
||||
immunity_type = "storm" // temp
|
||||
probability = 2 //The chances of this happening are very low after all. We'll rarely see it, but it's worth it.
|
||||
barometer_predictable = TRUE
|
||||
|
||||
var/datum/looping_sound/weak_outside_oxygenrain/sound_wo = new(list(), FALSE, TRUE)
|
||||
var/datum/looping_sound/weak_inside_oxygenrain/sound_wi = new(list(), FALSE, TRUE)
|
||||
|
||||
/datum/weather/oxygen_rain/telegraph()
|
||||
. = ..()
|
||||
priority_announce("[station_name()]: A large quantity of condensed low temperature oxygen clouds has been detected around and above the station. A liquid oxygen downpour is expected.",
|
||||
sound = 'sound/misc/notice2.ogg',
|
||||
sender_override = "GATO Meteorology Division")
|
||||
for(var/V in GLOB.player_list)
|
||||
var/mob/M = V
|
||||
if((M.client?.prefs?.toggles & SOUND_MIDI) && is_station_level(M.z))
|
||||
M.playsound_local(M, 'hyperstation/sound/ambience/embrace.ogg', 40, FALSE, pressure_affected = FALSE)
|
||||
/*
|
||||
"Sappheiros - Embrace" is under a Creative Commons license (CC BY 3.0)
|
||||
https://www.youtube.com/channel/UCxLKyBhC6igFhLEb0gxvQNg
|
||||
Music promoted by BreakingCopyright: https://youtu.be/DzYp5uqixz0
|
||||
*/
|
||||
var/list/inside_areas = list()
|
||||
var/list/outside_areas = list()
|
||||
var/list/eligible_areas = list()
|
||||
for (var/z in impacted_z_levels)
|
||||
eligible_areas += SSmapping.areas_in_z["[z]"]
|
||||
for(var/i in 1 to eligible_areas.len)
|
||||
var/area/place = eligible_areas[i]
|
||||
if(place.outdoors)
|
||||
outside_areas += place
|
||||
else
|
||||
inside_areas += place
|
||||
CHECK_TICK
|
||||
|
||||
sound_wo.output_atoms = outside_areas
|
||||
sound_wi.output_atoms = inside_areas
|
||||
|
||||
sound_wo.start()
|
||||
sound_wi.start()
|
||||
|
||||
/datum/weather/oxygen_rain/end()
|
||||
. = ..()
|
||||
sound_wo.stop()
|
||||
sound_wi.stop()
|
||||
|
||||
/datum/weather/oxygen_rain/weather_act(mob/living/L)
|
||||
//This is liquid oxygen after all. (-180C give or take)
|
||||
L.adjust_bodytemperature(-rand(5,10))
|
||||
|
||||
/datum/looping_sound/weak_outside_oxygenrain
|
||||
mid_sounds = list(
|
||||
'sound/weather/oxygenrain/outside/weak_mid1.ogg'=1,
|
||||
'sound/weather/oxygenrain/outside/weak_mid2.ogg'=1
|
||||
)
|
||||
mid_length = 80
|
||||
start_sound = 'sound/weather/oxygenrain/outside/weak_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/oxygenrain/outside/weak_end.ogg'
|
||||
volume = 50
|
||||
|
||||
/datum/looping_sound/weak_inside_oxygenrain
|
||||
mid_sounds = list(
|
||||
'sound/weather/oxygenrain/inside/weak_mid1.ogg'=1,
|
||||
'sound/weather/oxygenrain/inside/weak_mid2.ogg'=1
|
||||
)
|
||||
mid_length = 80
|
||||
start_sound = 'sound/weather/oxygenrain/inside/weak_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/oxygenrain/inside/weak_end.ogg'
|
||||
volume = 30
|
||||
*/
|
||||
18
hyperstation/code/effects/lighting.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
/obj/effect/light/
|
||||
name = "bloom"
|
||||
icon = 'hyperstation/icons/effects/lighting.dmi'
|
||||
icon_state = "light"
|
||||
plane = ABOVE_LIGHTING_PLANE
|
||||
blend_mode = BLEND_ADD
|
||||
mouse_opacity = 0
|
||||
anchored = TRUE //no more flying around.
|
||||
|
||||
/obj/effect/light/medium
|
||||
icon = 'hyperstation/icons/effects/lightingmed.dmi'
|
||||
pixel_x = -16
|
||||
pixel_y = -16
|
||||
|
||||
/obj/effect/light/large
|
||||
icon = 'hyperstation/icons/effects/lightinglarge.dmi'
|
||||
pixel_x = -48
|
||||
pixel_y = -48
|
||||
296
hyperstation/code/game/machinery/lore_terminal.dm
Normal file
@@ -0,0 +1,296 @@
|
||||
GLOBAL_DATUM_INIT(lore_terminal_controller, /datum/lore_controller, new)
|
||||
|
||||
/obj/machinery/computer/lore_terminal
|
||||
name = "Staff info-link terminal"
|
||||
desc = "A small CRT display with an inbuilt microcomputer which is loaded with an extensive database. These terminals contain eveyrthing from information about historical events to instruction manuals for common ship appliances."
|
||||
icon = 'nsv13/icons/obj/computers.dmi'
|
||||
icon_state = "terminal"
|
||||
pixel_y = 26 //So they snap to walls correctly
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
idle_power_usage = 15
|
||||
var/access_tag = "kncommon" //Every subtype of this type will be readable by this console. Use this for away terms as seen here \/
|
||||
var/list/entries = list() //Every entry that we've got.
|
||||
var/in_use = FALSE //Stops sound spam
|
||||
var/datum/looping_sound/computer_click/soundloop
|
||||
|
||||
/obj/machinery/computer/lore_terminal/command //Put sensitive information on this one
|
||||
name = "Command info-link terminal"
|
||||
access_tag = "kncommand"
|
||||
req_access = list(ACCESS_HEADS)
|
||||
|
||||
/obj/machinery/computer/lore_terminal/security
|
||||
name = "Security info-link terminal"
|
||||
access_tag = "knsecurity"
|
||||
req_access = list(ACCESS_SECURITY)
|
||||
|
||||
/obj/machinery/computer/lore_terminal/awaymission //Example for having a terminal preloaded with only a set list of files.
|
||||
access_tag = "awaymission_default"
|
||||
|
||||
/obj/machinery/computer/lore_terminal/Initialize(mapload)
|
||||
. = ..()
|
||||
get_entries()
|
||||
soundloop = new(list(src), FALSE)
|
||||
|
||||
/datum/looping_sound/computer_click
|
||||
mid_sounds = list('nsv13/sound/effects/computer/scroll1.ogg','nsv13/sound/effects/computer/scroll2.ogg','nsv13/sound/effects/computer/scroll3.ogg','nsv13/sound/effects/computer/scroll5.ogg')
|
||||
mid_length = 0.8 SECONDS
|
||||
volume = 30
|
||||
|
||||
/obj/machinery/computer/lore_terminal/proc/get_entries()
|
||||
for(var/X in GLOB.lore_terminal_controller.entries)
|
||||
var/datum/lore_entry/instance = X
|
||||
if(instance.access_tag == access_tag || instance.access_tag == "all")
|
||||
entries += instance
|
||||
|
||||
/obj/machinery/computer/lore_terminal/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(!allowed(user))
|
||||
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
|
||||
playsound(src, sound, 100, 1)
|
||||
to_chat(user, "<span class='warning'>Access denied</span>")
|
||||
return
|
||||
playsound(src, 'nsv13/sound/effects/computer/scroll_start.ogg', 100, 1)
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(!entries.len)
|
||||
get_entries()
|
||||
for(var/X in entries) //Allows you to remove things individually
|
||||
var/datum/lore_entry/content = X
|
||||
dat += "<a href='?src=[REF(src)];selectitem=\ref[content]'>[content.name]</a><br>"
|
||||
var/datum/browser/popup = new(user, "cd C:/entries/local", name, 300, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
|
||||
/obj/machinery/computer/lore_terminal/Topic(href, href_list)
|
||||
if(!in_range(src, usr))
|
||||
return
|
||||
if(in_use)
|
||||
var/sound = 'nsv13/sound/effects/computer/buzz2.ogg'
|
||||
playsound(src, sound, 100, 1)
|
||||
to_chat(usr, "<span class='warning'>ERROR: I/O function busy. A file is still loading...</span>")
|
||||
return
|
||||
var/datum/lore_entry/content = locate(href_list["selectitem"])
|
||||
if(!content || !content?.content)
|
||||
return
|
||||
var/clicks = length(content.content) //Split the content into characters. 1 character = 1 click
|
||||
var/dat = "<!DOCTYPE html>\
|
||||
<html>\
|
||||
<body background='https://cdn.discordapp.com/attachments/573966558548721665/612306341612093489/static.png'>\
|
||||
\
|
||||
<body onload='typeWriter()'>\
|
||||
\
|
||||
<h4>ACCESS FILE: C:/entries/local/[content.name]</h4>\
|
||||
<h3><i>Classification: [content.classified]</i></h3>\
|
||||
<h6>- <20> Seegson systems inc, 2257</h6>\
|
||||
<hr style='border-top: dotted 1px;' />\
|
||||
<h2>[content.title]</h2>\
|
||||
\
|
||||
<p id='demo'></p>\
|
||||
\
|
||||
<script>\
|
||||
var i = 0;\
|
||||
var txt = \"[content.content]\";\
|
||||
var speed = 10;\
|
||||
\
|
||||
function typeWriter() {\
|
||||
if (i < txt.length) {\
|
||||
var char = txt.charAt(i);\
|
||||
if (char == '`') {\
|
||||
document.getElementById('demo').innerHTML += '<br>';\
|
||||
}\
|
||||
else {\
|
||||
document.getElementById('demo').innerHTML += txt.charAt(i);\
|
||||
}\
|
||||
i++;\
|
||||
setTimeout(typeWriter, speed);\
|
||||
}\
|
||||
}\
|
||||
</script>\
|
||||
\
|
||||
\
|
||||
<style>\
|
||||
body {\
|
||||
background-color: black;\
|
||||
background-image: radial-gradient(\
|
||||
rgba(0, 20, 0, 0.75), black 120%\
|
||||
);\
|
||||
height: 100vh;\
|
||||
margin: 0;\
|
||||
overflow: hidden;\
|
||||
padding: 2rem;\
|
||||
color: #36f891;\
|
||||
font: 1.3rem Lucida Console, monospace;\
|
||||
text-shadow: 0 0 5px #355732;\
|
||||
&::after {\
|
||||
content: '';\
|
||||
position: absolute;\
|
||||
top: 0;\
|
||||
left: 0;\
|
||||
width: 100vw;\
|
||||
height: 100vh;\
|
||||
background: repeating-linear-gradient(\
|
||||
0deg,\
|
||||
rgba(black, 0.15),\
|
||||
rgba(black, 0.15) 1px,\
|
||||
transparent 1px,\
|
||||
transparent 2px\
|
||||
);\
|
||||
pointer-events: none;\
|
||||
}\
|
||||
}\
|
||||
::selection {\
|
||||
background: #0080FF;\
|
||||
text-shadow: none;\
|
||||
}\
|
||||
pre {\
|
||||
margin: 0;\
|
||||
}\
|
||||
</style>\
|
||||
</body>\
|
||||
</html>"
|
||||
usr << browse(dat, "window=lore_console[content.name];size=600x600")
|
||||
playsound(src, pick('nsv13/sound/effects/computer/buzz.ogg','nsv13/sound/effects/computer/buzz2.ogg'), 100, TRUE)
|
||||
in_use = TRUE //Stops you from crashing the server with infinite sounds
|
||||
icon_state = "terminal_scroll"
|
||||
clicks = clicks/3
|
||||
var/loops = clicks/3 //Each click sound has 4 clicks in it, so we only need to click 1/4th of the time per character yeet.
|
||||
addtimer(CALLBACK(src,PROC_REF(stop_clicking)), loops)
|
||||
soundloop?.start()
|
||||
|
||||
|
||||
/obj/machinery/computer/lore_terminal/proc/stop_clicking()
|
||||
soundloop?.stop()
|
||||
icon_state = "terminal"
|
||||
in_use = FALSE
|
||||
|
||||
/datum/lore_controller
|
||||
var/name = "Lore archive controller"
|
||||
var/list/entries = list() //All the lore entries we have.
|
||||
|
||||
/datum/lore_controller/New()
|
||||
. = ..()
|
||||
instantiate_lore_entries()
|
||||
|
||||
/datum/lore_controller/proc/instantiate_lore_entries()
|
||||
for(var/instance in subtypesof(/datum/lore_entry))
|
||||
var/datum/lore_entry/S = new instance
|
||||
entries += S
|
||||
|
||||
/datum/lore_entry
|
||||
var/name = "Loredoc.txt" //"File display name" that the term shows (C://blah/yourfile.bmp)
|
||||
var/title = null //What it's all about
|
||||
var/classified = "Declassified" //Fluff, is this a restricted file or not?
|
||||
var/content = null //You may choose to set this here, or via a .txt. file if it's long. Newlines / Enters will break it!
|
||||
var/path = null //The location at which we're stored. If you don't have this, you don't get content
|
||||
var/access_tag = "placeholder" //Set this to match the terminals that you want to be able to access it. EG "ntcommon" for declassified shit.
|
||||
|
||||
/datum/lore_entry/New()
|
||||
. = ..()
|
||||
if(path)
|
||||
content = file2text("[path]")
|
||||
|
||||
/*
|
||||
|
||||
TO GET THE COOL TYPEWRITER EFFECT, I HAD TO STRIP OUT THE HTML FORMATTING STUFF.
|
||||
SPECIAL KEYS RESPOND AS FOLLOWS:
|
||||
|
||||
` = newline (br) (AKA when you press enter)
|
||||
~ = horizontal line (hr)
|
||||
<EFBFBD> = bullet point //Bullet points are not working? - archie
|
||||
|
||||
*/
|
||||
|
||||
/datum/lore_entry/station
|
||||
name = "new_employees_memo.mail"
|
||||
title = "Intercepted message"
|
||||
path = "lore_entries/welcome.txt"
|
||||
access_tag = "kncommon"
|
||||
|
||||
/datum/lore_entry/all
|
||||
name = "nuclear_authdisk_instructions.mail"
|
||||
title = "Handling the Nuclear Authentication Disk and You!"
|
||||
content = "SYSADMIN -> allcrew@seegnet.kin. RE: The Nuclear Authentication Disk. ` Greetings staff members! We're aware of the questions you have in regards to the Nuclear Authentication disk. The disk itself contains the codes needed to unlock nuclear devices used in a Nuclear Emergency and trigger a station self-destruction sequence. ` It is the duty of every member of this crew to take responsibility for the disk in the off chance that station command is currently absent. ` Even though Layenia itself is a mobile facility and prevents Disk Triangulation in most circumstances, it is still important to hold onto the disk even when not needed- it is a good formality and keeps things secure! ` If the disk location is unknown, look for a red pinpointer, the Head of Security and the Captain should always have one in their offices or lockers. These will help you locate the disk. ` If the disk is in enemy hands, call all hands on deck immediately and order a red alert. ` ` Protect the disk with your life, for the lives of the station's crew depend on it. Stay safe through vigilance."
|
||||
access_tag = "all"
|
||||
|
||||
/datum/lore_entry/all/meltdown_proceedures
|
||||
name = "meltdown_proceedures.mail"
|
||||
title = "Emergency proceedures regarding nuclear meltdowns:"
|
||||
path = "lore_entries/meltdowns.txt"
|
||||
|
||||
/datum/lore_entry/command
|
||||
name = "command_memo.mail"
|
||||
title = "Intercepted Message"
|
||||
access_tag = "kncommand"
|
||||
classified = "Restricted"
|
||||
content = "SYSADMIN -> command@seegnet.kin. RE: Orientation. ` Greetings station command staff, congratulations on your placement! It is now company policy to attend all briefings as issued by centcom staff. Please speak to your centcom officer for clarification on the new procedures."
|
||||
|
||||
/datum/lore_entry/command/xeno
|
||||
name = "outpost_27.mail"
|
||||
title = "Investigation Closed"
|
||||
classified = "Classified"
|
||||
content = "SYSADMIN -> command@seegnet.kin. RE: Outpost 27 Investigation. ` Until further notice, all communications, visits and trade with Outpost 27 must be denied. It is recommended that the subject is avoided. Stay safe through vigilance."
|
||||
|
||||
/datum/lore_entry/away_example
|
||||
title = "Intercepted log file"
|
||||
access_tag = "awayexample"
|
||||
|
||||
/datum/lore_entry/away_example/pilot_log
|
||||
name = "pilot_log.txt"
|
||||
content = "They're coming in hot! Prepare for flip and bur']###<23>$55%%% -=File Access Terminated=-"
|
||||
|
||||
/datum/lore_entry/away_example/weapons_log
|
||||
name = "weapon_systems_dump2259/11/25.txt"
|
||||
content = "Life support systems terminated. Railgun system status: A6E3. Torpedo system status: ~@##6#6#^^6 -=File Access Terminated=-"
|
||||
|
||||
/datum/lore_entry/security
|
||||
name = "usage_and_terms.memo"
|
||||
title = "Usage and Terms"
|
||||
access_tag = "knsecurity"
|
||||
path = "lore_entries/security/usageandterms.txt"
|
||||
|
||||
/datum/lore_entry/security/introduction
|
||||
name = "introduction.memo"
|
||||
title = "Security Introduction"
|
||||
path = "lore_entries/security/introduction.txt"
|
||||
|
||||
/datum/lore_entry/security/basicgearandyou
|
||||
name = "gearbasics.memo"
|
||||
title = "Basic Gear and You"
|
||||
path = "lore_entries/security/basicgearandyou.txt"
|
||||
|
||||
/datum/lore_entry/security/advancedgearandyou
|
||||
name = "gearadvanced.memo"
|
||||
title = "Advanced Gear and You"
|
||||
path = "lore_entries/security/advancedgearandyou.txt"
|
||||
|
||||
/datum/lore_entry/security/defensivegearandyou
|
||||
name = "geardefensive.memo"
|
||||
title = "Defensive Gear and You"
|
||||
path = "lore_entries/security/defensivegearandyou.txt"
|
||||
|
||||
/datum/lore_entry/security/sop
|
||||
name = "standard_operating_procedure.txt"
|
||||
title = "Standard Operating Procedure"
|
||||
path = "lore_entries/security/wip.txt"
|
||||
|
||||
/datum/lore_entry/security/lowcrime
|
||||
name = "low_infractions.txt"
|
||||
title = "Minor Infractions"
|
||||
path = "lore_entries/security/wip.txt"
|
||||
|
||||
/datum/lore_entry/security/mediumcrime
|
||||
name = "medium_infractions.txt"
|
||||
title = "Medium-risk Infractions"
|
||||
path = "lore_entries/security/wip.txt"
|
||||
|
||||
/datum/lore_entry/security/highcrime
|
||||
name = "high_infractions.txt"
|
||||
title = "Dangerous Infractions"
|
||||
path = "lore_entries/security/wip.txt"
|
||||
|
||||
/datum/lore_entry/security/deltacrime
|
||||
name = "delta_infractions.txt"
|
||||
title = "Zealot-class Notice and Warning"
|
||||
path = "lore_entries/security/wip.txt"
|
||||
77
hyperstation/code/game/objects/items/cosmetics.dm
Normal file
@@ -0,0 +1,77 @@
|
||||
//hyperstation 13 nail polish
|
||||
|
||||
/obj/item/nailpolish
|
||||
name = "nail polish"
|
||||
desc = "Paint with a fine brush to do your nails, or someone elses."
|
||||
icon = 'hyperstation/icons/obj/cosmetic.dmi'
|
||||
icon_state = "nailcap"
|
||||
item_state = "nailpolish"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/paint = "black"
|
||||
price = 5
|
||||
var/mutable_appearance/bottle //show the colour on the bottle.
|
||||
|
||||
/obj/item/nailpolish/red
|
||||
name = "red nail polish"
|
||||
paint = "red"
|
||||
|
||||
/obj/item/nailpolish/blue
|
||||
name = "blue nail polish"
|
||||
paint = "blue"
|
||||
|
||||
/obj/item/nailpolish/aqua
|
||||
name = "cyan nail polish"
|
||||
paint = "aqua"
|
||||
|
||||
/obj/item/nailpolish/black
|
||||
name = "black nail polish"
|
||||
paint = "black"
|
||||
|
||||
/obj/item/nailpolish/white
|
||||
name = "white nail polish"
|
||||
paint = "white"
|
||||
|
||||
/obj/item/nailpolish/navy
|
||||
name = "navy nail polish"
|
||||
paint = "navy"
|
||||
|
||||
/obj/item/nailpolish/yellow
|
||||
name = "yellow nail polish"
|
||||
paint = "yellow"
|
||||
|
||||
/obj/item/nailpolish/purple
|
||||
name = "purple nail polish"
|
||||
paint = "purple"
|
||||
|
||||
/obj/item/nailpolish/Initialize(mapload)
|
||||
. = ..()
|
||||
bottle = mutable_appearance('hyperstation/icons/obj/cosmetic.dmi', "nailpolish")
|
||||
bottle.color = paint
|
||||
add_overlay(bottle)
|
||||
|
||||
|
||||
/obj/item/nailpolish/attack(mob/M, mob/user)
|
||||
if(!ismob(M))
|
||||
return
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.nail_style) //to stop stacking bugs
|
||||
to_chat(user, "<span class='warning'>Remove the old nail polish first!</span>")
|
||||
|
||||
if(H == user)
|
||||
user.visible_message("<span class='notice'>[user] does [user.p_their()] nails with \the [src].</span>", \
|
||||
"<span class='notice'>You take a moment to apply \the [src]. Perfect!</span>")
|
||||
H.nail_style = "nails"
|
||||
H.nail_color = paint
|
||||
H.update_body()
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins to do [H]'s nails with \the [src].</span>", \
|
||||
"<span class='notice'>You begin to apply \the [src] on [H]'s nails...</span>")
|
||||
if(do_after(user, 20, target = H))
|
||||
user.visible_message("[user] does [H]'s nails with \the [src].", \
|
||||
"<span class='notice'>You apply \the [src] on [H]'s nails.</span>")
|
||||
H.nail_style = "nails"
|
||||
H.nail_color = paint
|
||||
H.update_body()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Where are the nail on that?</span>")
|
||||
44
hyperstation/code/game/objects/items/storage/big_bag.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
/obj/item/storage/backpack/gigantic
|
||||
name = "enormous backpack"
|
||||
desc = "An absolutely massive backpack for particularly large crewmen."
|
||||
icon_state = "explorerpack"
|
||||
item_state = "explorerpack"
|
||||
|
||||
/obj/item/storage/backpack/gigantic/ComponentInitialize()
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.allow_big_nesting = TRUE
|
||||
STR.max_combined_w_class = 35
|
||||
STR.max_w_class = WEIGHT_CLASS_HUGE
|
||||
|
||||
/obj/item/storage/backpack/gigantic/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(M.size_multiplier >= 2.0)
|
||||
return ..()
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/item/storage/backpack/gigantic/proc/fallOff(mob/living/wearer)
|
||||
wearer.dropItemToGround(src, TRUE)
|
||||
playsound(src.loc, 'sound/items/handling/cloth_drop.ogg', 50, TRUE)
|
||||
playsound(src.loc, 'sound/items/handling/toolbelt_drop.ogg', 50, TRUE)
|
||||
wearer.visible_message("<span class='warning'>The [src.name] slips off [wearer]'s now too-small body and falls to the ground!'</span>", "<span class='warning'>The [src.name] slips off your now too-small body and falls to the ground!'</span>")
|
||||
|
||||
/obj/item/storage/backpack/gigantic/equipped(mob/equipper, slot)
|
||||
. = ..()
|
||||
if(slot ==ITEM_SLOT_BACK)
|
||||
RegisterSignal(equipper, COMSIG_MOBSIZE_CHANGED,PROC_REF(fallOff))
|
||||
else
|
||||
UnregisterSignal(equipper, COMSIG_MOBSIZE_CHANGED)
|
||||
|
||||
|
||||
/obj/item/storage/backpack/gigantic/dropped(mob/user, silent)
|
||||
UnregisterSignal(user, COMSIG_MOBSIZE_CHANGED)
|
||||
|
||||
|
||||
/obj/item/storage/backpack/gigantic/satchel
|
||||
name = "enormous satchel"
|
||||
desc = "An absolutely massive satchel for particularly large crewmen."
|
||||
icon_state = "satchel-explorer"
|
||||
item_state = "securitypack"
|
||||
162
hyperstation/code/game/objects/railings.dm
Normal file
@@ -0,0 +1,162 @@
|
||||
//ported from virgo
|
||||
|
||||
/obj/structure/railing
|
||||
name = "railing"
|
||||
desc = "A railing to stop people from falling"
|
||||
|
||||
icon = 'hyperstation/icons/obj/railings.dmi'
|
||||
var/icon_modifier = "grey_"
|
||||
icon_state = "grey_railing0"
|
||||
|
||||
density = FALSE
|
||||
layer = 4
|
||||
anchored = TRUE
|
||||
flags_1 = ON_BORDER_1
|
||||
max_integrity = 250
|
||||
var/heat_resistance = 800
|
||||
var/health = 70
|
||||
var/maxhealth = 70
|
||||
|
||||
|
||||
resistance_flags = ACID_PROOF
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
|
||||
CanAtmosPass = ATMOS_PASS_PROC
|
||||
var/real_explosion_block //ignore this, just use explosion_block
|
||||
var/breaksound = "shatter"
|
||||
var/hitsound = 'sound/effects/Glasshit.ogg'
|
||||
rad_insulation = RAD_VERY_LIGHT_INSULATION
|
||||
rad_flags = RAD_PROTECT_CONTENTS
|
||||
var/check = 0
|
||||
var/static/list/freepass = typecacheof(list(
|
||||
/obj/singularity,
|
||||
/obj/effect/projectile,
|
||||
/obj/effect/portal,
|
||||
/obj/effect/abstract,
|
||||
/obj/effect/hotspot,
|
||||
/obj/effect/landmark,
|
||||
/obj/effect/temp_visual,
|
||||
/obj/effect/light_emitter/tendril,
|
||||
/obj/effect/collapse,
|
||||
/obj/effect/particle_effect/ion_trails,
|
||||
/obj/effect/dummy/phased_mob,
|
||||
/obj/effect/immovablerod,
|
||||
/obj/effect/crystalline_reentry
|
||||
)) //Gotta make sure certain things can phase through it otherwise the railings also block them.
|
||||
|
||||
/obj/structure/railing/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS) || is_type_in_typecache(mover, freepass))
|
||||
return TRUE
|
||||
if(get_dir(loc, target) == dir)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/railing/CheckExit(atom/movable/O, turf/target)
|
||||
if(istype(O) && (O.pass_flags & PASSGLASS) || is_type_in_typecache(O, freepass))
|
||||
return TRUE
|
||||
if(get_dir(O.loc, target) == dir)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/railing/Initialize(mapload)
|
||||
. = ..()
|
||||
if(src.anchored)
|
||||
update_icon(0)
|
||||
|
||||
/obj/structure/railing/proc/NeighborsCheck(var/UpdateNeighbors = 1)
|
||||
check = 0
|
||||
//if (!anchored) return
|
||||
var/Rturn = turn(src.dir, -90)
|
||||
var/Lturn = turn(src.dir, 90)
|
||||
|
||||
for(var/obj/structure/railing/R in src.loc)
|
||||
if ((R.dir == Lturn) && R.anchored)
|
||||
check |= 32
|
||||
if (UpdateNeighbors)
|
||||
R.update_icon(0)
|
||||
if ((R.dir == Rturn) && R.anchored)
|
||||
check |= 2
|
||||
if (UpdateNeighbors)
|
||||
R.update_icon(0)
|
||||
|
||||
for (var/obj/structure/railing/R in get_step(src, Lturn))
|
||||
if ((R.dir == src.dir) && R.anchored)
|
||||
check |= 16
|
||||
if (UpdateNeighbors)
|
||||
R.update_icon(0)
|
||||
for (var/obj/structure/railing/R in get_step(src, Rturn))
|
||||
if ((R.dir == src.dir) && R.anchored)
|
||||
check |= 1
|
||||
if (UpdateNeighbors)
|
||||
R.update_icon(0)
|
||||
|
||||
for (var/obj/structure/railing/R in get_step(src, (Lturn + src.dir)))
|
||||
if ((R.dir == Rturn) && R.anchored)
|
||||
check |= 64
|
||||
if (UpdateNeighbors)
|
||||
R.update_icon(0)
|
||||
for (var/obj/structure/railing/R in get_step(src, (Rturn + src.dir)))
|
||||
if ((R.dir == Lturn) && R.anchored)
|
||||
check |= 4
|
||||
if (UpdateNeighbors)
|
||||
R.update_icon(0)
|
||||
|
||||
/obj/structure/railing/update_icon(var/UpdateNeighgors = 1)
|
||||
NeighborsCheck(UpdateNeighgors)
|
||||
overlays.Cut()
|
||||
if (!check || !anchored)//|| !anchored
|
||||
icon_state = "[icon_modifier]railing0"
|
||||
else
|
||||
icon_state = "[icon_modifier]railing1"
|
||||
if (check & 32)
|
||||
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]corneroverlay")
|
||||
if ((check & 16) || !(check & 32) || (check & 64))
|
||||
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]frontoverlay_l")
|
||||
if (!(check & 2) || (check & 1) || (check & 4))
|
||||
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]frontoverlay_r")
|
||||
if(check & 4)
|
||||
switch (src.dir)
|
||||
if (NORTH)
|
||||
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = 32)
|
||||
if (SOUTH)
|
||||
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = -32)
|
||||
if (EAST)
|
||||
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = -32)
|
||||
if (WEST)
|
||||
overlays += image ('hyperstation/icons/obj/railings.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = 32)
|
||||
|
||||
/obj/structure/railing/examine(mob/user)
|
||||
. = ..()
|
||||
if(health < maxhealth)
|
||||
switch(health / maxhealth)
|
||||
if(0.0 to 0.5)
|
||||
. += "<span class='warning'>It looks severely damaged!</span>"
|
||||
if(0.25 to 0.5)
|
||||
. += "<span class='warning'>It looks damaged!</span>"
|
||||
if(0.5 to 1.0)
|
||||
. += "<span class='notice'>It has a few scrapes and dents.</span>"
|
||||
|
||||
/obj/structure/railing/take_damage(amount)
|
||||
health -= amount
|
||||
if(health <= 0)
|
||||
visible_message("<span class='warning'>\The [src] breaks down!</span>")
|
||||
playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
|
||||
new /obj/item/stack/rods(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/railing/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
if(!istype(user))
|
||||
return
|
||||
if(!isliving(user))
|
||||
return
|
||||
|
||||
usr.visible_message("<span class='warning'>[user] starts climbing onto \the [src]!</span>")
|
||||
|
||||
if(!do_after(user, 20))
|
||||
return
|
||||
|
||||
if(get_turf(user) == get_turf(src))
|
||||
usr.forceMove(get_step(src, src.dir))
|
||||
else
|
||||
usr.forceMove(get_turf(src))
|
||||
|
||||
usr.visible_message("<span class='warning'>[user] climbed over \the [src]!</span>")
|
||||
11
hyperstation/code/game/objects/structures/bench.dm
Normal file
@@ -0,0 +1,11 @@
|
||||
/obj/structure/chair/bench
|
||||
name = "wooden bench"
|
||||
icon_state = "bench_middle"
|
||||
icon = 'hyperstation/icons/obj/bench.dmi'
|
||||
buildstackamount = 1
|
||||
buildstacktype = /obj/item/stack/sheet/mineral/wood
|
||||
|
||||
/obj/structure/chair/bench/left
|
||||
icon_state = "bench_left"
|
||||
/obj/structure/chair/bench/right
|
||||
icon_state = "bench_right"
|
||||
144
hyperstation/code/game/objects/structures/ghost_role_spawners.dm
Normal file
@@ -0,0 +1,144 @@
|
||||
//Duo malfunctioning cryostasis sleepers: Spawns in big makeshift shelters in lavaland.
|
||||
/obj/effect/mob_spawn/human/duohermit
|
||||
name = "malfunctioning cryostasis sleeper"
|
||||
desc = "A humming sleeper with a silhouetted occupant inside. Its stasis function is broken and it's likely being used as a bed."
|
||||
mob_name = "a stranded hermit"
|
||||
job_description = "Lavaland Hermit"
|
||||
icon = 'icons/obj/lavaland/spawners.dmi'
|
||||
icon_state = "cryostasis_sleeper"
|
||||
roundstart = FALSE
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
short_desc = "You are lost."
|
||||
flavour_text = "You and another have been stranded in this planet for quite some time now. Each day you barely scrape by, and between the terrible \
|
||||
conditions of your makeshift shelter, the hostile creatures, and the ash drakes swooping down from the cloudless skies, all you can wish for is the feel of soft grass between your toes and \
|
||||
the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you and your friend got here... "
|
||||
assignedrole = "Hermit"
|
||||
mirrorcanloadappearance = TRUE
|
||||
|
||||
/obj/effect/mob_spawn/human/duohermit/Initialize(mapload)
|
||||
. = ..()
|
||||
var/arrpee = rand(1,3)
|
||||
switch(arrpee)
|
||||
if(1)
|
||||
flavour_text += "you were an intern at a rather odd deep space facility. You weren't quite sure how things worked or what they were doing there, but it was your first day on the \
|
||||
job. A day that was abruptly interrupted by gunfire and alarms. Luckily enough, your handy crowbar skills managed to get you to an escape pod before it was too late.</b>"
|
||||
outfit.uniform = /obj/item/clothing/under/assistantformal
|
||||
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
outfit.back = /obj/item/storage/backpack
|
||||
if(2)
|
||||
flavour_text += "you were a volunteer test subject for a state of the art deep space facility. You didn't care much about who you were working with, but in the end, the paycheck \
|
||||
was really, really good. To this day, you're not quite sure which sort of prototype implants were used on you, as you seem to remember little but the headache that struck you once \
|
||||
the escape pod finally hit the ground and your seatbelt failed to keep you buckled.</b>"
|
||||
outfit.uniform = /obj/item/clothing/under/rank/scientist
|
||||
outfit.suit = /obj/item/clothing/suit/toggle/labcoat
|
||||
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
outfit.back = /obj/item/storage/backpack
|
||||
if(3)
|
||||
flavour_text += "you were a doctor at a state of the art deep space facility. For who exactly you were conducting research for, not even you are quite sure. Only that the paycheck \
|
||||
at the end of the month was good enough. In the end, when said facility was attacked by Nanotransen, you and another were the only ones to have made it out alive. Or so it seemed.</b>"
|
||||
outfit.uniform = /obj/item/clothing/under/rank/medical
|
||||
outfit.suit = /obj/item/clothing/suit/toggle/labcoat
|
||||
outfit.back = /obj/item/storage/backpack/medic
|
||||
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
|
||||
/obj/effect/mob_spawn/human/duohermit/Destroy()
|
||||
new/obj/structure/fluff/empty_cryostasis_sleeper(get_turf(src))
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/human/duohermit/special(mob/living/carbon/human/new_spawn)
|
||||
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
|
||||
|
||||
//Exiles: Stranded exiles that have been left in Snowdin. Can be easily adapted for other roles as well.
|
||||
/obj/effect/mob_spawn/human/exiled
|
||||
name = "used bed"
|
||||
desc = "Still warm."
|
||||
mob_name = "exiled"
|
||||
job_description = "Exiles"
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "bed"
|
||||
roundstart = FALSE
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
short_desc = "You've been left behind."
|
||||
flavour_text = "As the last escape shuttle left the sector, you were left for dead, stranded in a cold hell where you make do, until hopefully someone finds you. \
|
||||
Every day, you pause and recollect your memories from before it all happened... "
|
||||
assignedrole = "Arctic Exile"
|
||||
mirrorcanloadappearance = TRUE
|
||||
|
||||
/obj/effect/mob_spawn/human/exiled/Initialize(mapload)
|
||||
. = ..()
|
||||
var/arrpee = rand(1,1)
|
||||
switch(arrpee)
|
||||
if(1)
|
||||
flavour_text += "You were a lowly engineer, hired by GATO to make sure the turbines from their mining operation remained functional. \
|
||||
You remember the day the mining team descended for the very last time into the depths of the shafts, only to never return. \
|
||||
The agonizing screams from whatever now haunts those mines still brings a shiver down your spine."
|
||||
outfit.uniform = /obj/item/clothing/under/assistantformal
|
||||
outfit.suit = /obj/item/clothing/suit/hooded/wintercoat
|
||||
outfit.shoes = /obj/item/clothing/shoes/winterboots
|
||||
outfit.back = /obj/item/storage/backpack
|
||||
outfit.implants = list(/obj/item/implant/exile) //Made it so they cannot simply exit through the gateway at will.
|
||||
|
||||
/obj/effect/mob_spawn/human/exiled/Destroy()
|
||||
new/obj/structure/bed(get_turf(src))
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/human/exiled/special(mob/living/carbon/human/new_spawn)
|
||||
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
|
||||
|
||||
//Villagers: Once a group of servants that worshiped their 'Gods-Kings', but now finally free after their overlords have abandoned the planet.
|
||||
|
||||
/obj/effect/mob_spawn/human/villager
|
||||
name = "used bed"
|
||||
desc = "Still warm."
|
||||
mob_name = "villager"
|
||||
job_description = "Villagers"
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "bed"
|
||||
roundstart = FALSE
|
||||
death = FALSE
|
||||
mob_species = /datum/species/human
|
||||
short_desc = "You're finally free."
|
||||
flavour_text = "After the God-Kings have abandoned the land, your people are finally free from their oppression. \
|
||||
Still, the reasons for their departure are a mystery, and now your people need to work together to survive in this world."
|
||||
assignedrole = "Free villager"
|
||||
mirrorcanloadappearance = TRUE
|
||||
|
||||
/obj/effect/mob_spawn/human/villager/Initialize(mapload)
|
||||
. = ..()
|
||||
var/arrpee = rand(1,3)
|
||||
switch(arrpee)
|
||||
if(1)
|
||||
flavour_text += "You were a guard, serving your gods to keep control of you own people. \
|
||||
Now that they left, you work to defend the village."
|
||||
outfit.head = /obj/item/clothing/head/pharaoh
|
||||
outfit.uniform = /obj/item/clothing/under/tunic
|
||||
outfit.shoes = /obj/item/clothing/shoes/sandal
|
||||
outfit.back = /obj/item/storage/backpack/satchel/leather
|
||||
outfit.implants = list(/obj/item/implant/exile) //Made it so they cannot simply exit through the gateway at will.
|
||||
if(2)
|
||||
flavour_text += "You were a farmer, working extensively for years in the field to feed your people. \
|
||||
The work hasn't changed much since the departure of the gods..."
|
||||
outfit.head = /obj/item/clothing/head/rice_hat
|
||||
outfit.uniform = /obj/item/clothing/under/tunic
|
||||
outfit.shoes = /obj/item/clothing/shoes/sandal
|
||||
outfit.back = /obj/item/storage/backpack/satchel/leather
|
||||
outfit.implants = list(/obj/item/implant/exile) //Made it so they cannot simply exit through the gateway at will.
|
||||
if(3)
|
||||
flavour_text += "You were a servant, doing any necessary work that was thrown at you. \
|
||||
At least it gave you experience in a bit of everything, which can be useful in these new times."
|
||||
outfit.uniform = /obj/item/clothing/under/mummy
|
||||
outfit.uniform = /obj/item/clothing/under/tunic
|
||||
outfit.shoes = /obj/item/clothing/shoes/sandal
|
||||
outfit.back = /obj/item/storage/backpack/satchel/leather
|
||||
outfit.implants = list(/obj/item/implant/exile) //Made it so they cannot simply exit through the gateway at will.
|
||||
|
||||
/obj/effect/mob_spawn/human/villager/Destroy()
|
||||
new/obj/structure/bed(get_turf(src))
|
||||
return ..()
|
||||
|
||||
/obj/effect/mob_spawn/human/villager/special(mob/living/carbon/human/new_spawn)
|
||||
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
|
||||
120
hyperstation/code/game/objects/structures/sauna_oven.dm
Normal file
@@ -0,0 +1,120 @@
|
||||
#define SAUNA_H2O_TEMP T20C + 20
|
||||
#define SAUNA_LOG_FUEL 150
|
||||
#define SAUNA_PAPER_FUEL 5
|
||||
#define SAUNA_MAXIMUM_FUEL 3000
|
||||
#define SAUNA_WATER_PER_WATER_UNIT 5
|
||||
|
||||
/obj/structure/sauna_oven
|
||||
name = "sauna oven"
|
||||
desc = "A modest sauna oven with rocks. Add some fuel, pour some water and enjoy the moment."
|
||||
icon = 'hyperstation/icons/obj/structures/sauna_oven.dmi'
|
||||
icon_state = "sauna_oven"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/lit = FALSE
|
||||
var/fuel_amount = 0
|
||||
var/water_amount = 0
|
||||
|
||||
/obj/structure/sauna_oven/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>The rocks are [water_amount ? "moist" : "dry"].</span>"
|
||||
. += "<span class='notice'>There's [fuel_amount ? "some fuel" : "no fuel"] in the oven.</span>"
|
||||
|
||||
/obj/structure/sauna_oven/Destroy()
|
||||
if(lit)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/structure/sauna_oven/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(lit)
|
||||
lit = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
user.visible_message("<span class='notice'>[user] turns on [src].</span>", "<span class='notice'>You turn on [src].</span>")
|
||||
else if (fuel_amount)
|
||||
lit = TRUE
|
||||
START_PROCESSING(SSobj, src)
|
||||
user.visible_message("<span class='notice'>[user] turns off [src].</span>", "<span class='notice'>You turn off [src].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/structure/sauna_oven/update_overlays()
|
||||
. = ..()
|
||||
if(lit)
|
||||
. += "sauna_oven_on_overlay"
|
||||
|
||||
/obj/structure/sauna_oven/update_icon()
|
||||
..()
|
||||
icon_state = "[lit ? "sauna_oven_on" : initial(icon_state)]"
|
||||
|
||||
/obj/structure/sauna_oven/attackby(obj/item/T, mob/user)
|
||||
if(T.tool_behaviour == TOOL_WRENCH)
|
||||
to_chat(user, "<span class='notice'>You begin to deconstruct [src].</span>")
|
||||
if(T.use_tool(src, user, 60, volume=50))
|
||||
to_chat(user, "<span class='notice'>You successfully deconstructed [src].</span>")
|
||||
new /obj/item/stack/sheet/mineral/wood(get_turf(src), 30)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
else if(istype(T, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/reagent_container = T
|
||||
if(!reagent_container.is_open_container())
|
||||
return ..()
|
||||
if(reagent_container.reagents.has_reagent(/datum/reagent/water))
|
||||
reagent_container.reagents.remove_reagent(/datum/reagent/water, 5)
|
||||
user.visible_message("<span class='notice'>[user] pours some \
|
||||
water into [src].</span>", "<span class='notice'>You pour \
|
||||
some water to [src].</span>")
|
||||
water_amount += 5 * SAUNA_WATER_PER_WATER_UNIT
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There's no water in [reagent_container]</span>")
|
||||
return FALSE
|
||||
|
||||
else if(istype(T, /obj/item/stack/sheet/mineral/wood))
|
||||
var/obj/item/stack/sheet/mineral/wood/wood = T
|
||||
if(fuel_amount > SAUNA_MAXIMUM_FUEL)
|
||||
to_chat(user, "<span class='warning'>You can't fit any more of [T] in [src]!</span>")
|
||||
return FALSE
|
||||
fuel_amount += SAUNA_LOG_FUEL * wood.amount
|
||||
wood.use(wood.amount)
|
||||
user.visible_message("<span class='notice'>[user] tosses some \
|
||||
wood into [src].</span>", "<span class='notice'>You add \
|
||||
some fuel to [src].</span>")
|
||||
return TRUE
|
||||
else if(istype(T, /obj/item/paper_bin))
|
||||
var/obj/item/paper_bin/paper_bin = T
|
||||
user.visible_message("<span class='notice'>[user] throws [T] into \
|
||||
[src].</span>", "<span class='notice'>You add [T] to [src].\
|
||||
</span>")
|
||||
fuel_amount += SAUNA_PAPER_FUEL * paper_bin.total_paper
|
||||
qdel(paper_bin)
|
||||
return TRUE
|
||||
else if(istype(T, /obj/item/paper))
|
||||
user.visible_message("<span class='notice'>[user] throws [T] into \
|
||||
[src].</span>", "<span class='notice'>You throw [T] into [src].\
|
||||
</span>")
|
||||
fuel_amount += SAUNA_PAPER_FUEL
|
||||
qdel(T)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/sauna_oven/process()
|
||||
if(water_amount)
|
||||
water_amount--
|
||||
var/turf/pos = get_turf(src)
|
||||
if(pos)
|
||||
pos.atmos_spawn_air("water_vapor=10;TEMP=[SAUNA_H2O_TEMP]")
|
||||
fuel_amount--
|
||||
if(fuel_amount <= 0)
|
||||
lit = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
|
||||
#undef SAUNA_H2O_TEMP
|
||||
#undef SAUNA_LOG_FUEL
|
||||
#undef SAUNA_PAPER_FUEL
|
||||
#undef SAUNA_MAXIMUM_FUEL
|
||||
#undef SAUNA_WATER_PER_WATER_UNIT
|
||||
339
hyperstation/code/gamemode/traitor_lewd.dm
Normal file
@@ -0,0 +1,339 @@
|
||||
//Jay Sparrow
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/lewd = list()
|
||||
|
||||
|
||||
|
||||
/datum/mind/
|
||||
var/sexed = FALSE //General flag for completion check
|
||||
|
||||
//TODO - Move this somewhere else
|
||||
GLOBAL_LIST_INIT(hyper_special_roles, list(
|
||||
ROLE_LEWD_TRAITOR = /datum/game_mode/traitor/lewd
|
||||
))
|
||||
|
||||
|
||||
/datum/game_mode/traitor/lewd
|
||||
name = "lewd traitor"
|
||||
config_tag = "lewd traitor"
|
||||
antag_flag = ROLE_LEWD_TRAITOR
|
||||
false_report_weight = 20 //Reports of traitors are pretty common.
|
||||
restricted_jobs = list("Cyborg")
|
||||
protected_jobs = list() //Anyone can be lewd op. Even heads.
|
||||
required_players = 0
|
||||
required_enemies = 0
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "There are lewd agents on the station!\n\
|
||||
<span class='danger'>Traitors</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the traitors succeed!"
|
||||
|
||||
//var/list/datum/mind/lewd
|
||||
traitors_possible = 10 //hard limit on traitors if scaling is turned off //Let it be high for now. Testing phase.
|
||||
num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual.
|
||||
antag_datum = /datum/antagonist/traitor/lewd //what type of antag to create
|
||||
|
||||
/datum/antagonist/traitor/lewd
|
||||
name = "Lewd Traitor"
|
||||
roundend_category = "traitors"
|
||||
antagpanel_category = "Traitor"
|
||||
job_rank = ROLE_LEWD_TRAITOR
|
||||
//antag_moodlet = /datum/mood_event/focused //No special moodlet yet
|
||||
special_role = ROLE_LEWD_TRAITOR
|
||||
employer = "An interested voyeur"
|
||||
give_objectives = TRUE
|
||||
should_give_codewords = FALSE
|
||||
should_equip = TRUE
|
||||
traitor_kind = TRAITOR_HUMAN //Set on initial assignment
|
||||
can_hijack = HIJACK_NEUTRAL
|
||||
|
||||
//Custom uplink list - aaaaaaaaaaaaaa
|
||||
var/list/lewd_uplink_list = list()
|
||||
var/list/lewd_uplink_list_raw = list(
|
||||
/datum/uplink_item/bundles_TC/random,
|
||||
/datum/uplink_item/bundles_TC/telecrystal,
|
||||
/datum/uplink_item/bundles_TC/telecrystal/five,
|
||||
/datum/uplink_item/bundles_TC/telecrystal/twenty,
|
||||
/datum/uplink_item/dangerous/foamsmg,
|
||||
/datum/uplink_item/dangerous/foammachinegun,
|
||||
/datum/uplink_item/dangerous/foampistol,
|
||||
/datum/uplink_item/dangerous/phantomthief,
|
||||
/datum/uplink_item/stealthy_weapons/dart_pistol,
|
||||
/datum/uplink_item/stealthy_weapons/crossbow,
|
||||
/datum/uplink_item/stealthy_weapons/sleepy_pen,
|
||||
/datum/uplink_item/stealthy_weapons/suppressor,
|
||||
/datum/uplink_item/stealthy_weapons/soap,
|
||||
/datum/uplink_item/stealthy_weapons/soap_clusterbang,
|
||||
/datum/uplink_item/ammo/pistolzzz,
|
||||
/datum/uplink_item/ammo/shotgun/stun,
|
||||
/datum/uplink_item/ammo/toydarts,
|
||||
/datum/uplink_item/stealthy_tools/ai_detector,
|
||||
/datum/uplink_item/stealthy_tools/chameleon,
|
||||
/datum/uplink_item/stealthy_tools/chameleon_proj,
|
||||
/datum/uplink_item/stealthy_tools/emplight,
|
||||
/datum/uplink_item/stealthy_tools/syndigaloshes,
|
||||
/datum/uplink_item/stealthy_tools/jammer,
|
||||
/datum/uplink_item/stealthy_tools/smugglersatchel,
|
||||
/datum/uplink_item/device_tools/binary,
|
||||
/datum/uplink_item/device_tools/compressionkit,
|
||||
/datum/uplink_item/device_tools/briefcase_launchpad,
|
||||
/datum/uplink_item/device_tools/camera_bug,
|
||||
/datum/uplink_item/device_tools/military_belt,
|
||||
/datum/uplink_item/device_tools/frame,
|
||||
/datum/uplink_item/device_tools/toolbox,
|
||||
/datum/uplink_item/device_tools/medkit,
|
||||
/datum/uplink_item/device_tools/surgerybag,
|
||||
/datum/uplink_item/device_tools/encryptionkey,
|
||||
/datum/uplink_item/device_tools/thermal,
|
||||
/datum/uplink_item/implants/radio,
|
||||
/datum/uplink_item/implants/reviver,
|
||||
/datum/uplink_item/implants/stealthimplant,
|
||||
/datum/uplink_item/implants/thermals,
|
||||
/datum/uplink_item/implants/uplink,
|
||||
/datum/uplink_item/implants/xray,
|
||||
/datum/uplink_item/role_restricted/goldenbox,
|
||||
/datum/uplink_item/role_restricted/chemical_gun,
|
||||
/datum/uplink_item/badass/syndiecash,
|
||||
/datum/uplink_item/badass/phantomthief,
|
||||
/datum/uplink_item/badass/syndiecards,
|
||||
/datum/uplink_item/badass/syndiecigs)
|
||||
|
||||
/datum/game_mode/traitor/lewd/generate_report()
|
||||
return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \
|
||||
GATO employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions."
|
||||
|
||||
/datum/mind/proc/make_LewdTraitor()
|
||||
if(!(has_antag_datum(/datum/antagonist/traitor/lewd)))
|
||||
add_antag_datum(/datum/antagonist/traitor/lewd)
|
||||
|
||||
/datum/admins/proc/makeLewdtraitors()
|
||||
to_chat(GLOB.admins, "makeLewd_traitors called")
|
||||
var/datum/game_mode/traitor/lewd/temp = new
|
||||
|
||||
//if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
//continue
|
||||
|
||||
//if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
//continue
|
||||
|
||||
var/list/mob/living/carbon/human/candidates = list()
|
||||
var/mob/living/carbon/human/H = null
|
||||
var/list/mob/living/carbon/human/targets = list()
|
||||
//var/mob/living/carbon/human/T = null
|
||||
|
||||
for(var/mob/living/carbon/human/applicant in GLOB.player_list)
|
||||
if(isReadytoRumble(applicant, ROLE_LEWD_TRAITOR))
|
||||
if(temp.age_check(applicant.client))
|
||||
if(!(applicant.job in temp.restricted_jobs))
|
||||
candidates += applicant
|
||||
|
||||
for(var/mob/living/carbon/human/target in GLOB.player_list)
|
||||
if(target.client?.prefs?.noncon)
|
||||
if(!(target.job in temp.restricted_jobs))
|
||||
targets += target
|
||||
|
||||
if(candidates.len)
|
||||
var/numTraitors = min(candidates.len, targets.len, 1) //This number affects the maximum number of traitors. We want 1 for right now.
|
||||
if(numTraitors == 0)
|
||||
to_chat(GLOB.admins, "No lewd traitors created. Are there any valid targets?")
|
||||
return FALSE
|
||||
for(var/i = 0, i<numTraitors, i++)
|
||||
H = pick(candidates)
|
||||
H.mind.make_LewdTraitor()
|
||||
candidates.Remove(H)
|
||||
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
return FALSE
|
||||
|
||||
/datum/antagonist/traitor/lewd/proc/forge_objectives()
|
||||
forge_single_objective()
|
||||
|
||||
|
||||
/datum/antagonist/traitor/lewd/forge_human_objectives()
|
||||
forge_single_objective()
|
||||
|
||||
/datum/antagonist/traitor/lewd/forge_single_objective()
|
||||
var/datum/objective/noncon/noncon_objective = new
|
||||
noncon_objective.owner = owner
|
||||
noncon_objective.target = noncon_objective.find_target()
|
||||
add_objective(noncon_objective)
|
||||
return
|
||||
|
||||
/datum/antagonist/traitor/lewd/greet()
|
||||
to_chat(owner.current, "<span class='userlove'>You are the [owner.special_role].</span>")
|
||||
owner.announce_objectives()
|
||||
if(should_give_codewords)
|
||||
give_codewords()
|
||||
|
||||
/datum/antagonist/traitor/lewd/on_gain()
|
||||
if(owner.current && isAI(owner.current))
|
||||
traitor_kind = TRAITOR_AI
|
||||
|
||||
SSticker.mode.traitors += owner
|
||||
owner.special_role = special_role
|
||||
if(give_objectives)
|
||||
forge_objectives()
|
||||
finalize_traitor()
|
||||
|
||||
/datum/antagonist/traitor/lewd/finalize_traitor()
|
||||
switch(traitor_kind)
|
||||
if(TRAITOR_AI)
|
||||
add_law_zero()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
owner.current.grant_language(/datum/language/codespeak)
|
||||
if(TRAITOR_HUMAN)
|
||||
if(should_equip)
|
||||
equip(silent)
|
||||
for(var/obj/I in owner.current.GetAllContents())
|
||||
var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
|
||||
if(hidden_uplink)
|
||||
lewd_uplink_list = get_custom_uplink_items(lewd_uplink_list_raw, /datum/game_mode/traitor/lewd, TRUE, FALSE)
|
||||
hidden_uplink.uplink_items = lewd_uplink_list
|
||||
hidden_uplink.telecrystals = 12
|
||||
|
||||
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
greet()
|
||||
|
||||
/datum/objective/noncon/New(var/datum/mind/_owner)
|
||||
GLOB.objectives += src // CITADEL EDIT FOR CRYOPODS
|
||||
if(_owner)
|
||||
owner = _owner
|
||||
|
||||
|
||||
|
||||
//GS13 - this shit's just fucking weird lol, gtfo
|
||||
|
||||
// /datum/objective/noncon/find_target()
|
||||
// //..()
|
||||
// //to_chat(world, "<span class='boldannounce'>TEST: noncon/find_target() called</span>")
|
||||
// var/list/datum/mind/targets = list()
|
||||
// var/list/datum/mind/owners = get_owners()
|
||||
// for(var/datum/mind/candidate in SSticker.minds)
|
||||
// if (!(candidate in owners) && ishuman(candidate.current) && (candidate.current.client))
|
||||
// if(candidate.current.client?.prefs?.noncon == 1)
|
||||
// targets += candidate
|
||||
// if(targets.len > 0)
|
||||
// target = pick(targets)
|
||||
// else
|
||||
// target = null
|
||||
// update_explanation_text()
|
||||
// return target
|
||||
|
||||
|
||||
// /datum/objective/noncon/check_completion()
|
||||
// if(!target)
|
||||
// return TRUE
|
||||
// else
|
||||
// return target.sexed
|
||||
|
||||
// /datum/objective/noncon/update_explanation_text()
|
||||
// if(target)
|
||||
// explanation_text = "Locate [target.name], and sate your lust."
|
||||
// else
|
||||
// explanation_text = "Free Lewd Objective"
|
||||
|
||||
/datum/antagonist/traitor/lewd/roundend_report()
|
||||
var/list/result = list()
|
||||
|
||||
var/traitorwin = TRUE
|
||||
|
||||
result += printplayer(owner)
|
||||
|
||||
var/TC_uses = 0
|
||||
var/uplink_true = FALSE
|
||||
var/purchases = ""
|
||||
LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
|
||||
var/datum/uplink_purchase_log/H = GLOB.uplink_purchase_logs_by_key[owner.key]
|
||||
if(H)
|
||||
TC_uses = H.total_spent
|
||||
uplink_true = TRUE
|
||||
purchases += H.generate_render(FALSE)
|
||||
|
||||
var/objectives_text = ""
|
||||
if(objectives.len)//If the traitor had no objectives, don't need to process this.
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.check_completion())
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
|
||||
else
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
traitorwin = FALSE
|
||||
count++
|
||||
|
||||
if(uplink_true)
|
||||
var/uplink_text = "(used [TC_uses] TC) [purchases]"
|
||||
if(TC_uses==0 && traitorwin)
|
||||
var/static/icon/badass = icon('icons/badass.dmi', "badass")
|
||||
uplink_text += "<BIG>[icon2html(badass, world)]</BIG>"
|
||||
result += uplink_text
|
||||
|
||||
result += objectives_text
|
||||
|
||||
var/special_role_text = lowertext(name)
|
||||
|
||||
if(traitorwin)
|
||||
result += "<span class='greentext'>The [special_role_text] was successful!</span>"
|
||||
else
|
||||
result += "<span class='redtext'>The [special_role_text] has failed!</span>"
|
||||
SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
|
||||
|
||||
return result.Join("<br>")
|
||||
|
||||
|
||||
/proc/get_custom_uplink_items(var/list/custom_uplink_list = null, var/datum/game_mode/gamemode = null, allow_sales = TRUE, allow_restricted = TRUE)
|
||||
var/list/filtered_uplink_items = list()
|
||||
var/list/sale_items = list()
|
||||
|
||||
if(!custom_uplink_list)
|
||||
for(var/path in GLOB.uplink_items)
|
||||
custom_uplink_list += new path
|
||||
for(var/path in custom_uplink_list)
|
||||
var/datum/uplink_item/I = new path
|
||||
if(!I.item)
|
||||
continue
|
||||
if(I.include_modes.len)
|
||||
if(!gamemode && SSticker.mode && !(SSticker.mode.type in I.include_modes))
|
||||
continue
|
||||
if(gamemode && !(gamemode in I.include_modes))
|
||||
continue
|
||||
if(I.exclude_modes.len)
|
||||
if(!gamemode && SSticker.mode && (SSticker.mode.type in I.exclude_modes))
|
||||
continue
|
||||
if(gamemode && (gamemode in I.exclude_modes))
|
||||
continue
|
||||
if(I.player_minimum && I.player_minimum > GLOB.joined_player_list.len)
|
||||
continue
|
||||
if (I.restricted && !allow_restricted)
|
||||
continue
|
||||
|
||||
if(!filtered_uplink_items[I.category])
|
||||
filtered_uplink_items[I.category] = list()
|
||||
filtered_uplink_items[I.category][I.name] = I
|
||||
if(I.limited_stock < 0 && !I.cant_discount && I.item && I.cost > 1)
|
||||
sale_items += I
|
||||
if(allow_sales)
|
||||
for(var/i in 1 to 2) //Smaller list, fewer discounts
|
||||
var/datum/uplink_item/I = pick_n_take(sale_items)
|
||||
var/datum/uplink_item/A = new I.type
|
||||
var/discount = A.get_discount()
|
||||
var/list/disclaimer = list("Void where prohibited.", "Not recommended for children.", "Contains small parts.", "Check local laws for legality in region.", "Do not taunt.", "Not responsible for direct, indirect, incidental or consequential damages resulting from any defect, error or failure to perform.", "Keep away from fire or flames.", "Product is provided \"as is\" without any implied or expressed warranties.", "As seen on TV.", "For recreational use only.", "Use only as directed.", "16% sales tax will be charged for orders originating within Space Nebraska.")
|
||||
A.limited_stock = 1
|
||||
I.refundable = FALSE //THIS MAN USES ONE WEIRD TRICK TO GAIN FREE TC, CODERS HATES HIM!
|
||||
A.refundable = FALSE
|
||||
if(A.cost >= 20) //Tough love for nuke ops
|
||||
discount *= 0.5
|
||||
A.cost = max(round(A.cost * discount),1)
|
||||
A.category = "Discounted Gear"
|
||||
A.name += " ([round(((initial(A.cost)-A.cost)/initial(A.cost))*100)]% off!)"
|
||||
A.desc += " Normally costs [initial(A.cost)] TC. All sales final. [pick(disclaimer)]"
|
||||
A.item = I.item
|
||||
|
||||
if(!filtered_uplink_items[A.category])
|
||||
filtered_uplink_items[A.category] = list()
|
||||
filtered_uplink_items[A.category][A.name] = A
|
||||
return filtered_uplink_items
|
||||
|
||||
84
hyperstation/code/gamemode/traitor_thief.dm
Normal file
@@ -0,0 +1,84 @@
|
||||
//Jay Sparrow
|
||||
//A less murder traitor for low chaos dynamic rounds.
|
||||
|
||||
/datum/game_mode/traitor/thief
|
||||
name = "thief traitor"
|
||||
config_tag = "thief traitor"
|
||||
antag_flag = ROLE_TRAITOR
|
||||
false_report_weight = 20 //Reports of traitors are pretty common.
|
||||
restricted_jobs = list("AI","Cyborg")
|
||||
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
required_players = 0
|
||||
required_enemies = 0
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "There are enemy agents on the station!\n\
|
||||
<span class='danger'>Traitors</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the traitors succeed!"
|
||||
|
||||
traitors_possible = 3 //hard limit on traitors if scaling is turned off //Let it be high for now. Testing phase.
|
||||
num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual.
|
||||
antag_datum = /datum/antagonist/traitor/thief //what type of antag to create
|
||||
|
||||
/datum/antagonist/traitor/thief
|
||||
name = "Thief Traitor"
|
||||
roundend_category = "traitors"
|
||||
antagpanel_category = "Traitor"
|
||||
job_rank = ROLE_TRAITOR
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
special_role = ROLE_TRAITOR
|
||||
employer = "The Syndicate"
|
||||
give_objectives = TRUE
|
||||
should_give_codewords = TRUE
|
||||
should_equip = TRUE
|
||||
traitor_kind = TRAITOR_HUMAN //Set on initial assignment
|
||||
can_hijack = HIJACK_NEUTRAL
|
||||
|
||||
|
||||
/datum/game_mode/traitor/thief/generate_report()
|
||||
return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \
|
||||
GATO employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions."
|
||||
|
||||
/datum/mind/proc/make_ThiefTraitor()
|
||||
if(!(has_antag_datum(/datum/antagonist/traitor/thief)))
|
||||
add_antag_datum(/datum/antagonist/traitor/thief)
|
||||
|
||||
|
||||
/datum/antagonist/traitor/thief/proc/forge_objectives()
|
||||
forge_single_objective()
|
||||
forge_single_objective()
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
|
||||
|
||||
/datum/antagonist/traitor/thief/forge_human_objectives()
|
||||
forge_single_objective()
|
||||
forge_single_objective()
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
|
||||
/datum/antagonist/traitor/thief/forge_single_objective()
|
||||
if(prob(15) && !(locate(/datum/objective/download) in owner.objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
|
||||
var/datum/objective/download/download_objective = new
|
||||
download_objective.owner = owner
|
||||
download_objective.gen_amount_goal()
|
||||
add_objective(download_objective)
|
||||
else
|
||||
var/datum/objective/steal/steal_objective = new
|
||||
steal_objective.owner = owner
|
||||
steal_objective.find_target()
|
||||
add_objective(steal_objective)
|
||||
return
|
||||
|
||||
|
||||
/datum/antagonist/traitor/thief/on_gain()
|
||||
if(owner.current && isAI(owner.current))
|
||||
traitor_kind = TRAITOR_AI
|
||||
|
||||
SSticker.mode.traitors += owner
|
||||
owner.special_role = special_role
|
||||
if(give_objectives)
|
||||
forge_objectives()
|
||||
finalize_traitor()
|
||||
50
hyperstation/code/mobs/carrion.dm
Normal file
@@ -0,0 +1,50 @@
|
||||
//mob based off the game Carrion.
|
||||
//replica sprite made by quotefox
|
||||
|
||||
/mob/living/simple_animal/hostile/carrion
|
||||
name = "mass of red tentacles"
|
||||
desc = "A creature composed of tentacles and teeth, you aren't sure where it starts and where it ends."
|
||||
icon = 'hyperstation/icons/mobs/carrion.dmi'
|
||||
icon_state = "c_idle"
|
||||
icon_living = "c_idle"
|
||||
icon_dead = "idle"
|
||||
gender = NEUTER
|
||||
speak_chance = 0
|
||||
turns_per_move = 2
|
||||
turns_per_move = 3
|
||||
maxHealth = 300
|
||||
health = 300
|
||||
see_in_dark = 7
|
||||
response_help = "pets"
|
||||
response_disarm = "pushes aside"
|
||||
response_harm = "attacks"
|
||||
melee_damage_lower = 12
|
||||
melee_damage_upper = 20
|
||||
attacktext = "attacks"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
faction = list("hostile")
|
||||
ranged = 1
|
||||
harm_intent_damage = 5
|
||||
obj_damage = 60
|
||||
a_intent = INTENT_HARM
|
||||
ventcrawler = 1
|
||||
death_sound = 'sound/voice/ed209_20sec.ogg'
|
||||
deathmessage = "lets out scream and its tentacles shrivel away..."
|
||||
move_to_delay = 4
|
||||
loot = list(/obj/effect/gibspawner/human)
|
||||
|
||||
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 150
|
||||
maxbodytemp = 500
|
||||
do_footstep = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/carrion/OpenFire(atom/the_target)
|
||||
var/dist = get_dist(src,the_target)
|
||||
Beam(the_target, "tentacle", time=dist*2, maxdistance=dist, beam_sleep_time = 5)
|
||||
the_target.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/carrion/Initialize(mapload)
|
||||
//Move the sprite into position, cant use Pixel_X and Y, causes issues with the tenticle sprite!
|
||||
..()
|
||||
var/matrix/M = src.transform
|
||||
src.transform = M.Translate(-32,-32)
|
||||
56
hyperstation/code/mobs/dancer.dm
Normal file
@@ -0,0 +1,56 @@
|
||||
/mob/living/dancercaptain
|
||||
name = "Captain Beats"
|
||||
desc = "A captain cursed to dance for all eternity!"
|
||||
icon = 'hyperstation/icons/mobs/dancer/captain.dmi'
|
||||
icon_state = "idle"
|
||||
var/danceaction = 1
|
||||
var/lastaction = 0 //when the last action was!
|
||||
var/actiontime = 4
|
||||
var/list/dancefloor_turfs
|
||||
var/list/dancefloor_turfs_types
|
||||
var/dancefloor_exists = FALSE
|
||||
|
||||
/mob/living/dancercaptain/Move(atom/newloc, direct)
|
||||
|
||||
if(!danceaction)
|
||||
if(!(world.time > lastaction))
|
||||
return // no move for you!
|
||||
|
||||
animate(src, pixel_x, pixel_y = pixel_y + 10, time = 0.7, 0)
|
||||
. = ..()
|
||||
danceaction = 0 //you did your move
|
||||
lastaction = world.time+actiontime //next action time
|
||||
sleep(1)
|
||||
animate(src, pixel_x, pixel_y = pixel_y - 10, time = 0.7, 0)
|
||||
sleep(1)
|
||||
|
||||
LAZYINITLIST(dancefloor_turfs)
|
||||
LAZYINITLIST(dancefloor_turfs_types)
|
||||
|
||||
if(dancefloor_exists) //remove the old one!
|
||||
dancefloor_exists = FALSE
|
||||
for(var/i in 1 to dancefloor_turfs.len)
|
||||
var/turf/T = dancefloor_turfs[i]
|
||||
T.ChangeTurf(dancefloor_turfs_types[i])
|
||||
var/list/funky_turfs = RANGE_TURFS(2, src)
|
||||
|
||||
|
||||
dancefloor_exists = TRUE
|
||||
var/i = 1
|
||||
dancefloor_turfs.len = funky_turfs.len
|
||||
dancefloor_turfs_types.len = funky_turfs.len
|
||||
for(var/t in funky_turfs)
|
||||
if(!(istype(t, /turf/closed))) //dont change walls
|
||||
var/turf/T = t
|
||||
dancefloor_turfs[i] = T
|
||||
dancefloor_turfs_types[i] = T.type
|
||||
T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b)
|
||||
i++
|
||||
|
||||
|
||||
/mob/living/dancercaptain/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
lastaction = round(world.time) //round to the nearest second! to keep in beat!
|
||||
|
||||
/mob/living/dancercaptain/proc/mtimer()
|
||||
33
hyperstation/code/mobs/emote.dm
Normal file
@@ -0,0 +1,33 @@
|
||||
/datum/emote/living/chirp
|
||||
key = "chirp"
|
||||
key_third_person = "chirps!"
|
||||
message = "chirps!"
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
muzzle_ignore = FALSE
|
||||
restraint_check = FALSE
|
||||
mob_type_allowed_typecache = list(/mob/living/carbon, /mob/living/silicon/pai)
|
||||
|
||||
/datum/emote/living/chirp/run_emote(mob/living/user, params)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(user.nextsoundemote >= world.time)
|
||||
return
|
||||
user.nextsoundemote = world.time + 7
|
||||
playsound(user, 'sound/voice/chirp.ogg', 50, 1, -1)
|
||||
|
||||
/datum/emote/living/caw
|
||||
key = "caw"
|
||||
key_third_person = "caws!"
|
||||
message = "caws!"
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
muzzle_ignore = FALSE
|
||||
restraint_check = FALSE
|
||||
mob_type_allowed_typecache = list(/mob/living/carbon, /mob/living/silicon/pai)
|
||||
|
||||
/datum/emote/living/caw/run_emote(mob/living/user, params)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(user.nextsoundemote >= world.time)
|
||||
return
|
||||
user.nextsoundemote = world.time + 7
|
||||
playsound(user, 'sound/voice/caw.ogg', 50, 1, -1)
|
||||
311
hyperstation/code/mobs/hugbot.dm
Normal file
@@ -0,0 +1,311 @@
|
||||
//HUGBOT
|
||||
//HUGBOT PATHFINDING
|
||||
//HUGBOT ASSEMBLY
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot
|
||||
name = "\improper Hugbot"
|
||||
desc = "A little cudly robot. He looks excited."
|
||||
icon = 'hyperstation/icons/mobs/aibots.dmi'
|
||||
icon_state = "hugbot0"
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
health = 20
|
||||
maxHealth = 20
|
||||
pass_flags = PASSMOB
|
||||
|
||||
status_flags = (CANPUSH | CANSTUN)
|
||||
|
||||
bot_type = HUG_BOT
|
||||
model = "Hugbot"
|
||||
bot_core_type = /obj/machinery/bot_core/hugbot
|
||||
window_id = "autohug"
|
||||
window_name = "Automatic Hugging Unit v1.0 Alpha"
|
||||
path_image_color = "#FFDDDD"
|
||||
|
||||
base_speed = 4
|
||||
|
||||
var/stationary_mode = 0 //If enabled, the Hugbot will not move automatically.
|
||||
var/mob/living/carbon/patient = null
|
||||
var/mob/living/carbon/oldpatient = null
|
||||
var/last_found = 0
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/update_icon()
|
||||
cut_overlays()
|
||||
if(!on)
|
||||
icon_state = "hugbot0"
|
||||
return
|
||||
if(IsStun())
|
||||
icon_state = "hugbota"
|
||||
return
|
||||
if(mode == BOT_HEALING)
|
||||
icon_state = "hugbots[stationary_mode]"
|
||||
return
|
||||
else if(stationary_mode) //Bot has yellow light to indicate stationary mode.
|
||||
icon_state = "hugbot2"
|
||||
else
|
||||
icon_state = "hugbot1"
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/Initialize(mapload, new_skin)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/update_canmove()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/bot_reset()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/proc/soft_reset() //Allows the medibot to still actively perform its medical duties without being completely halted as a hard reset does.
|
||||
path = list()
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
last_found = world.time
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/set_custom_texts()
|
||||
|
||||
text_hack = "You bypass [name]'s manipulator pressure sensors."
|
||||
text_dehack = "You rewire [name]'s manipulator pressure sensors."
|
||||
text_dehack_fail = "[name] seems damaged and does not respond to reprogramming!"
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/get_controls(mob/user)
|
||||
var/dat
|
||||
dat += hack(user)
|
||||
dat += showpai(user)
|
||||
dat += "<TT><B>Hugging Unit Controls v1.0 Alpha</B></TT><BR><BR>"
|
||||
dat += "Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>"
|
||||
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
dat += "Patrol Station: <a href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</a><br>"
|
||||
dat += "Stationary Mode: <a href='?src=[REF(src)];stationary=1'>[stationary_mode ? "Yes" : "No"]</a><br>"
|
||||
|
||||
return dat
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/Topic(href, href_list)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
update_controls()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
var/current_health = health
|
||||
..()
|
||||
if(health < current_health) //if medbot took some damage
|
||||
step_to(src, (get_step_away(src,user)))
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/emag_act(mob/user)
|
||||
..()
|
||||
if(emagged == 2)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You short out [src]'s manipulator pressure sensors.</span>")
|
||||
audible_message("<span class='danger'>[src]'s arm twitches violently!</span>")
|
||||
flick("medibot_spark", src)
|
||||
playsound(src, "sparks", 75, 1)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/proc/assess_patient(mob/living/carbon/C)
|
||||
//Time to see if they need medical help!
|
||||
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
return FALSE //welp too late for them!
|
||||
|
||||
if(!(loc == C.loc) && !(isturf(C.loc) && isturf(loc)))
|
||||
return FALSE
|
||||
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
|
||||
if(emagged != 2) // EVERYONE GETS HUGS!
|
||||
for(var/datum/mood_event/i in mood.mood_events)
|
||||
if (i.description == "<span class='nicegreen'>Hugs are nice.</span>\n" )
|
||||
return FALSE
|
||||
else if (C.IsKnockdown())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/process_scan(mob/living/carbon/human/H)
|
||||
if(H.stat == DEAD)
|
||||
return
|
||||
|
||||
if((H == oldpatient) && (world.time < last_found + 200))
|
||||
return
|
||||
|
||||
if(assess_patient(H))
|
||||
last_found = world.time
|
||||
return H
|
||||
else
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/handle_automated_action()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(mode == BOT_HEALING)
|
||||
medicate_patient(patient)
|
||||
return
|
||||
|
||||
if(IsStun())
|
||||
oldpatient = patient
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(frustration > 8)
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
|
||||
if(QDELETED(patient))
|
||||
var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
|
||||
patient = scan(/mob/living/carbon/human, oldpatient, scan_range)
|
||||
oldpatient = patient
|
||||
|
||||
if(patient && (get_dist(src,patient) <= 1)) //Patient is next to us, begin treatment!
|
||||
if(mode != BOT_HEALING)
|
||||
mode = BOT_HEALING
|
||||
update_icon()
|
||||
frustration = 0
|
||||
medicate_patient(patient)
|
||||
return
|
||||
|
||||
//Patient has moved away from us!
|
||||
else if(patient && path.len && (get_dist(patient,path[path.len]) > 2))
|
||||
path = list()
|
||||
mode = BOT_IDLE
|
||||
last_found = world.time
|
||||
|
||||
else if(stationary_mode && patient) //Since we cannot move in this mode, ignore the patient and wait for another.
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(patient && path.len == 0 && (get_dist(src,patient) > 1))
|
||||
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,id=access_card)
|
||||
mode = BOT_MOVING
|
||||
if(!path.len) //try to get closer if you can't reach the patient directly
|
||||
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,1,id=access_card)
|
||||
if(!path.len) //Do not chase a patient we cannot reach.
|
||||
soft_reset()
|
||||
|
||||
if(path.len > 0 && patient)
|
||||
if(!bot_move(path[path.len]))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(path.len > 8 && patient)
|
||||
frustration++
|
||||
|
||||
if(auto_patrol && !stationary_mode && !patient)
|
||||
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
|
||||
start_patrol()
|
||||
|
||||
if(mode == BOT_PATROL)
|
||||
bot_patrol()
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/UnarmedAttack(atom/A)
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
patient = C
|
||||
mode = BOT_HEALING
|
||||
update_icon()
|
||||
medicate_patient(C)
|
||||
update_icon()
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/proc/medicate_patient(mob/living/carbon/C)
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(!istype(C))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>[src] hugs [C] to make [C.p_them()] feel better!</span>", \
|
||||
"<span class='notice'>You hug [C] to make [C.p_them()] feel better!</span>")
|
||||
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
|
||||
|
||||
if (emagged != 2)
|
||||
C.AdjustStun(-60)
|
||||
C.AdjustKnockdown(-60)
|
||||
C.AdjustUnconscious(-60)
|
||||
C.AdjustSleeping(-100)
|
||||
if(recoveringstam)
|
||||
C.adjustStaminaLoss(-15)
|
||||
else if(resting)
|
||||
C.resting = 0
|
||||
C.update_canmove()
|
||||
else
|
||||
C.Knockdown(100)
|
||||
C.Stun(100)
|
||||
C.update_canmove()
|
||||
|
||||
playsound(C.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
oldpatient = patient
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/hugbot/explode()
|
||||
on = FALSE
|
||||
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
|
||||
do_sparks(3, TRUE, src)
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/hugbot
|
||||
req_one_access = list(ACCESS_ROBOTICS)
|
||||
|
||||
/obj/item/bot_assembly/hugbot
|
||||
desc = "It's a box of hugs with an arm attached."
|
||||
name = "incomplete hugbot assembly"
|
||||
icon = 'hyperstation/icons/mobs/aibots.dmi'
|
||||
icon_state = "hugbot_arm"
|
||||
created_name = "Hugbot"
|
||||
|
||||
/obj/item/bot_assembly/hugbot/attackby(obj/item/W, mob/user, params)
|
||||
..()
|
||||
if(istype(W, /obj/item/assembly/prox_sensor))
|
||||
if(!can_finish_build(W, user))
|
||||
return
|
||||
var/mob/living/simple_animal/bot/hugbot/A = new(drop_location())
|
||||
A.name = created_name
|
||||
A.robot_arm = W.type
|
||||
to_chat(user, "<span class='notice'>You add [W] to [src]. Beep boop!</span>")
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/storage/box/hug/attackby(obj/item/I, mob/user, params)
|
||||
if((istype(I, /obj/item/bodypart/l_arm/robot)) || (istype(I, /obj/item/bodypart/r_arm/robot)))
|
||||
if(contents.len) //prevent accidently deleting contents
|
||||
to_chat(user, "<span class='warning'>You need to empty [src] out first!</span>")
|
||||
return
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
return
|
||||
qdel(I)
|
||||
to_chat(user, "<span class='notice'>You add [I] to the [src]! You've got a hugbot assembly now!</span>")
|
||||
var/obj/item/bot_assembly/hugbot/A = new
|
||||
qdel(src)
|
||||
user.put_in_hands(A)
|
||||
else
|
||||
return ..()
|
||||
414
hyperstation/code/mobs/mimic.dm
Normal file
@@ -0,0 +1,414 @@
|
||||
/mob/living/simple_animal/hostile/hs13mimic
|
||||
name = "Mimic"
|
||||
icon = 'hyperstation/icons/mobs/mimic.dmi'
|
||||
desc = "A writhing mass of black flesh, unlikely to be happy to see you."
|
||||
icon_state = "mimic"
|
||||
icon_living = "mimic"
|
||||
icon_dead = "mimic_dead"
|
||||
gender = NEUTER
|
||||
speak_chance = 0
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
turns_per_move = 5
|
||||
move_to_delay = 1
|
||||
speed = 0
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
pass_flags = PASSTABLE
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 2)
|
||||
response_help = "prods"
|
||||
response_disarm = "pushes aside"
|
||||
response_harm = "smacks"
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 12
|
||||
attacktext = "stings"
|
||||
attack_sound = 'hyperstation/sound/creatures/mimic/mimic_attack.ogg'
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
blood_volume = 0
|
||||
faction = list("mimic")
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
vision_range = 1
|
||||
aggro_vision_range = 9
|
||||
wander = TRUE
|
||||
minbodytemp = 250 //weak to cold
|
||||
maxbodytemp = 1500
|
||||
pressure_resistance = 1200
|
||||
sight = SEE_MOBS
|
||||
var/stealthed = TRUE
|
||||
var/knockdown_people = 1
|
||||
var/playerTransformCD = 50
|
||||
var/playerTfTime
|
||||
var/static/mimic_blacklisted_transform_items = typecacheof(list(
|
||||
/obj/item/projectile,
|
||||
/obj/item/radio/intercom,
|
||||
/mob/living/simple_animal/bot))
|
||||
var/transformsound = 'hyperstation/sound/creatures/mimic/mimic_transform.ogg'
|
||||
var/playstyle_string = "<span class='boldannounce'>You are a mimic</span></b>, a tricky creature that can take the form of \
|
||||
almost any item nearby by shift-clicking it. While morphed, you move slowly and do less damage. \
|
||||
Finally, you can restore yourself to your original form while morphed by shift-clicking yourself. \
|
||||
Attacking carbon lifeforms will heal you at the cost of destructuring their DNA. \
|
||||
You can also change your form to that of simple animals, but be wary that anyone examining you can \
|
||||
find out.</b>"
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/Initialize(mapload)
|
||||
. = ..()
|
||||
trytftorandomobject() // When initialized, make sure they take the form of something.
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/Login()
|
||||
. = ..()
|
||||
SEND_SOUND(src, sound('sound/ambience/antag/ling_aler.ogg'))
|
||||
to_chat(src, src.playstyle_string)
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
if(stealthed && stat == CONSCIOUS)
|
||||
if(M.a_intent == INTENT_HELP)//They're trying to pick us up! We tricked them boys! *plays runescape sea shanty*
|
||||
target = M
|
||||
guaranteedknockdown(M)
|
||||
trigger() // Bring our friends if any!
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/AttackingTarget()
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(.)
|
||||
if(stealthed && knockdown_people) //Guaranteed knockdown if we get the first hit while disguised. Typically, only players can do this since NPC mimics transform first before attacking.
|
||||
restore()
|
||||
C.Knockdown(40)
|
||||
C.visible_message("<span class='danger'>\The [src] knocks down \the [C]!</span>", \
|
||||
"<span class='userdanger'>\The [src] knocks you down!</span>")
|
||||
else if(knockdown_people && prob(15))
|
||||
C.Knockdown(40)
|
||||
C.visible_message("<span class='danger'>\The [src] knocks down \the [C]!</span>", \
|
||||
"<span class='userdanger'>\The [src] knocks you down!</span>")
|
||||
if(C.nutrition >= 15)
|
||||
C.nutrition -= (rand(7,15)) //They lose 7-15 nutrition
|
||||
adjustBruteLoss(-3) //We heal 3 damage
|
||||
C.adjustCloneLoss(rand(2,4)) //They also take a bit of cellular damage.
|
||||
if(isanimal(target))
|
||||
var/mob/living/simple_animal/A = target
|
||||
if(.)
|
||||
if(stealthed)
|
||||
restore()
|
||||
if(A.stat == CONSCIOUS)
|
||||
adjustBruteLoss(-3) //We heal 3 damage
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
trigger()
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/FindTarget()
|
||||
. = ..()
|
||||
if(.)
|
||||
trigger() //We have a target! Trigger!
|
||||
else if(!target && !stealthed) //Has no target, isn't stealthed, let's search for an object to transform
|
||||
trytftorandomobject()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/death(gibbed)
|
||||
restore() //We died. Restore form.
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_health()
|
||||
if(stealthed)
|
||||
var/image/holder = hud_list[HEALTH_HUD]
|
||||
holder.icon_state = null
|
||||
return //we hide medical hud while morphed
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_status()
|
||||
if(stealthed)
|
||||
var/image/holder = hud_list[STATUS_HUD]
|
||||
holder.icon_state = null
|
||||
return //we hide medical hud while morphed
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/mimicTransformList() //The list of default things to transform needs to be bigger, consider this in the future.
|
||||
var/transformitem = rand(1,100)
|
||||
medhudupdate()
|
||||
wander = FALSE
|
||||
vision_range = initial(vision_range)
|
||||
switch(transformitem)
|
||||
if(1 to 10)
|
||||
name = "drinking glass"
|
||||
icon = 'icons/obj/drinks.dmi'
|
||||
icon_state = "glass_empty"
|
||||
desc = "Your standard drinking glass."
|
||||
if(11 to 20)
|
||||
name = "insulated gloves"
|
||||
icon = 'icons/obj/clothing/gloves.dmi'
|
||||
icon_state = "yellow"
|
||||
desc = "These gloves will protect the wearer from electric shock."
|
||||
if(21 to 30)
|
||||
name = "stunbaton"
|
||||
desc = "A stun baton for incapacitating people with."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "stunbaton"
|
||||
if(31 to 40)
|
||||
name = "pen"
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "pen"
|
||||
desc = "It's a black ink pen, modified for use with both paper and Nanotransen-brand Digital-Readpads™!"
|
||||
if(41 to 50)
|
||||
name = "newspaper"
|
||||
desc = "An issue of The Catpaw, the newspaper circulating aboard GATO stations."
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "newspaper"
|
||||
if(51 to 60)
|
||||
name = "stechkin pistol" //greytider bait
|
||||
desc = "A small, easily concealable 10mm handgun. Has a threaded barrel for suppressors."
|
||||
icon = 'icons/obj/guns/projectile.dmi'
|
||||
icon_state = "pistol"
|
||||
if(61 to 70)
|
||||
name = "emergency oxygen tank"
|
||||
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
|
||||
icon = 'icons/obj/tank.dmi'
|
||||
icon_state = "emergency"
|
||||
if(71 to 80)
|
||||
name = "drinking glass"
|
||||
icon = 'icons/obj/drinks.dmi'
|
||||
icon_state = "glass_empty"
|
||||
desc = "Your standard drinking glass."
|
||||
if(81 to 90)
|
||||
name = "fleshlight"
|
||||
icon = 'hyperstation/icons/obj/fleshlight.dmi'
|
||||
icon_state = "fleshlight_totallynotamimic"
|
||||
desc = "A sex toy disguised as a flashlight, used to stimulate someones penis, complete with colour changing sleeve."
|
||||
if(91 to 100)
|
||||
icon = 'modular_citadel/icons/obj/genitals/dildo.dmi'
|
||||
switch(rand(1,3)) //switch within a switch hmmmmmmmmmm
|
||||
if(1)
|
||||
icon_state = "dildo_knotted_2"
|
||||
name = "small knotted dildo"
|
||||
if(2)
|
||||
icon_state = "dildo_flared_4"
|
||||
name = "huge flared dildo"
|
||||
if(3)
|
||||
icon_state = "dildo_knotted_3"
|
||||
name = "big knotted dildo"
|
||||
desc = "Floppy!"
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/guaranteedknockdown(mob/living/carbon/human/M)
|
||||
M.Knockdown(40)
|
||||
M.visible_message("<span class='danger'>\The [src] knocks down \the [M]!</span>", \
|
||||
"<span class='userdanger'>\The [src] tricks you, knocking you down!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/medhudupdate()
|
||||
med_hud_set_health()
|
||||
med_hud_set_status()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/restore()
|
||||
//back to normal mimic sprite
|
||||
stealthed = FALSE
|
||||
medhudupdate()
|
||||
name = initial(name)
|
||||
icon = 'hyperstation/icons/mobs/mimic.dmi'
|
||||
icon_state = "mimic"
|
||||
desc = initial(desc)
|
||||
speed = initial(speed)
|
||||
wander = TRUE
|
||||
vision_range = 9
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/trigger()
|
||||
if(stealthed && stat == CONSCIOUS)
|
||||
visible_message("<span class='danger'>The [src] Reveals itself to be a Mimic!</span>")
|
||||
restore()
|
||||
playsound(loc, transformsound, 75, TRUE)
|
||||
triggerOthers(target) // Friends too!
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/triggerOthers(passtarget) //
|
||||
for(var/mob/living/simple_animal/hostile/hs13mimic/C in oview(5, src.loc))
|
||||
if(passtarget && C.target == null && !(isdead(target)))
|
||||
C.target = passtarget
|
||||
C.trigger()
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/trytftorandomobject()
|
||||
stealthed = TRUE
|
||||
medhudupdate()
|
||||
var/list/obj/item/listItems = list()
|
||||
for(var/obj/item/I in oview(9,src.loc))
|
||||
if(allowed(I))
|
||||
listItems += I
|
||||
if(LAZYLEN(listItems))
|
||||
var/obj/item/changedReference = pick(listItems)
|
||||
wander = FALSE
|
||||
vision_range = initial(vision_range)
|
||||
name = changedReference.name
|
||||
icon = changedReference.icon
|
||||
icon_state = changedReference.icon_state
|
||||
desc = changedReference.desc
|
||||
else
|
||||
mimicTransformList() //Couldn't find any valid items, let's go for the default list then.
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/proc/allowed(atom/movable/A)
|
||||
return !is_type_in_typecache(A, mimic_blacklisted_transform_items) && (isitem(A) || isanimal(A))
|
||||
|
||||
//One leader mimic spawns per mimic event spawn, they are able to consume and transform themselves into the station's dead pets. Buckle up.
|
||||
/mob/living/simple_animal/hostile/hs13mimic/leader
|
||||
var/mob/living/consumptionTarget = null
|
||||
var/consuming = FALSE
|
||||
health = 38 //They have a teeeny tiny more health.
|
||||
maxHealth = 38
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/leader/Life()
|
||||
. = ..()
|
||||
if(!consuming)
|
||||
if(!consumptionTarget)
|
||||
for(var/mob/living/simple_animal/pet/A in oview(5, src))
|
||||
if(A.stat == DEAD)
|
||||
consumptionTarget = A
|
||||
break
|
||||
if(!target && consumptionTarget) //Don't try to consume anything if we're currently attacking something.
|
||||
var/target_distance = get_dist(targets_from, consumptionTarget)
|
||||
if(target_distance > minimum_distance)
|
||||
Goto(consumptionTarget,move_to_delay,minimum_distance)
|
||||
else
|
||||
tryConsume(consumptionTarget)
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/leader/proc/tryConsume(var/mob/living/simple_animal/pet/A)
|
||||
src.visible_message("<span class='warning'>[A] is being consumed...</span>",
|
||||
"<span class='notice'>You start to consume the dead [A]...</span>", "You hear strange fleshy sounds.")
|
||||
consuming = TRUE
|
||||
if(do_after(src, 100, target = A))
|
||||
stealthed = TRUE
|
||||
speed = 5
|
||||
wander = TRUE
|
||||
name = A.name
|
||||
desc = A.desc
|
||||
icon = A.icon
|
||||
icon_state = A.icon_living
|
||||
desc += "<span class='warning'> But something about it seems wrong...</span>"
|
||||
qdel(A)
|
||||
consuming = FALSE
|
||||
consumptionTarget = FALSE
|
||||
return TRUE
|
||||
consuming = FALSE
|
||||
return FALSE
|
||||
|
||||
//Player control code
|
||||
|
||||
/mob/living/simple_animal/hostile/hs13mimic/ShiftClickOn(atom/movable/A)
|
||||
if(playerTfTime <= world.time && stat == CONSCIOUS)
|
||||
if(A == src)
|
||||
restore()
|
||||
playerTfTime = world.time + playerTransformCD
|
||||
return
|
||||
if(istype(A) && allowed(A))
|
||||
stealthed = TRUE
|
||||
SEND_SOUND(src, sound(transformsound,volume=50))
|
||||
name = A.name
|
||||
icon = A.icon
|
||||
icon_state = A.icon_state
|
||||
desc = A.desc
|
||||
speed = 5
|
||||
playerTfTime = world.time + playerTransformCD
|
||||
if(isanimal(A))
|
||||
var/mob/living/simple_animal/animal = A
|
||||
icon_state = animal.icon_living
|
||||
desc += "<span class='warning'> But something about it seems wrong...</span>"
|
||||
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You need to wait a little longer before you can shift into something else!</span>")
|
||||
..()
|
||||
|
||||
//Event control
|
||||
|
||||
/datum/round_event_control/mimic_infestation
|
||||
name = "Mimic Infestation"
|
||||
typepath = /datum/round_event/mimic_infestation
|
||||
weight = 5
|
||||
max_occurrences = 1
|
||||
min_players = 15
|
||||
|
||||
/datum/round_event/mimic_infestation
|
||||
announceWhen = 200
|
||||
var/static/list/mimic_station_areas_blacklist = typecacheof(/area/space,
|
||||
/area/shuttle,
|
||||
/area/mine,
|
||||
/area/holodeck,
|
||||
/area/ruin,
|
||||
/area/hallway,
|
||||
/area/hallway/primary,
|
||||
/area/hallway/secondary,
|
||||
/area/hallway/secondary/entry,
|
||||
/area/engine/supermatter,
|
||||
/area/engine/atmospherics_engine,
|
||||
/area/engine/engineering/reactor_core,
|
||||
/area/engine/engineering/reactor_control,
|
||||
/area/ai_monitored/turret_protected,
|
||||
/area/layenia/cloudlayer,
|
||||
/area/asteroid/nearstation,
|
||||
/area/science/server,
|
||||
/area/science/explab,
|
||||
/area/science/xenobiology,
|
||||
/area/security/processing)
|
||||
var/spawncount = 1
|
||||
fakeable = FALSE
|
||||
|
||||
/datum/round_event/mimic_infestation/setup()
|
||||
announceWhen = rand(announceWhen, announceWhen + 50)
|
||||
spawncount = rand(4, 7)
|
||||
|
||||
/datum/round_event/mimic_infestation/announce(fake)
|
||||
priority_announce("Unidentified lifesigns detected aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/ai/aliens.ogg')
|
||||
|
||||
/datum/round_event/mimic_infestation/start()
|
||||
var/list/area/stationAreas = list()
|
||||
var/list/area/eligible_areas = list()
|
||||
for(var/area/A in world) // Get the areas in the Z level
|
||||
if(A.z == SSmapping.station_start)
|
||||
stationAreas += A
|
||||
for(var/area/place in stationAreas) // first we check if it's a valid area
|
||||
if(place.outdoors)
|
||||
continue
|
||||
if(place.areasize < 16)
|
||||
continue
|
||||
if(is_type_in_typecache(place, mimic_station_areas_blacklist))
|
||||
continue
|
||||
eligible_areas += place
|
||||
for(var/area/place in eligible_areas) // now we check if there are people in that area
|
||||
var/numOfPeople
|
||||
for(var/mob/living/carbon/H in place)
|
||||
numOfPeople++
|
||||
break
|
||||
if(numOfPeople > 0)
|
||||
eligible_areas -= place
|
||||
|
||||
var/validFound = FALSE
|
||||
var/list/turf/validTurfs = list()
|
||||
var/area/pickedArea
|
||||
while(!validFound || !eligible_areas.len)
|
||||
pickedArea = pick_n_take(eligible_areas)
|
||||
var/list/turf/t = get_area_turfs(pickedArea, SSmapping.station_start)
|
||||
for(var/turf/thisTurf in t) // now we check if it's a closed turf, cold turf or occupied turf and yeet it
|
||||
if(isopenturf(thisTurf))
|
||||
var/turf/open/tempGet = thisTurf
|
||||
if(tempGet.air.temperature <= T0C)
|
||||
t -= thisTurf
|
||||
continue
|
||||
if(isclosedturf(thisTurf))
|
||||
t -= thisTurf
|
||||
else
|
||||
for(var/obj/O in thisTurf)
|
||||
if(O.density && !(istype(O, /obj/structure/table)))
|
||||
t -= thisTurf
|
||||
break
|
||||
if(t.len >= spawncount) //Is the number of available turfs equal or bigger than spawncount?
|
||||
validFound = TRUE
|
||||
validTurfs = t
|
||||
|
||||
if(!eligible_areas.len)
|
||||
message_admins("No eligible areas for spawning mimics.")
|
||||
return WAITING_FOR_SOMETHING
|
||||
|
||||
notify_ghosts("A group of mimics has spawned in [pickedArea]!", source=pickedArea, action=NOTIFY_ATTACK, flashwindow = FALSE)
|
||||
while(spawncount > 0 && validTurfs.len)
|
||||
spawncount--
|
||||
var/turf/pickedTurf = pick_n_take(validTurfs)
|
||||
if(spawncount != 0)
|
||||
var/spawn_type = /mob/living/simple_animal/hostile/hs13mimic
|
||||
spawn_atom_to_turf(spawn_type, pickedTurf, 1, FALSE)
|
||||
else
|
||||
var/spawn_type = /mob/living/simple_animal/hostile/hs13mimic/leader
|
||||
spawn_atom_to_turf(spawn_type, pickedTurf, 1, FALSE)
|
||||
return SUCCESSFUL_SPAWN
|
||||
49
hyperstation/code/modules/admin/verbs/hyperverbs.dm
Normal file
@@ -0,0 +1,49 @@
|
||||
/client/proc/spawn_floor_cluwne()
|
||||
set category = "Fun"
|
||||
set name = "Unleash Targeted Floor Cluwne"
|
||||
set desc = "Pick a specific target. Be warned: spawning more than one may cause issues!"
|
||||
var/target
|
||||
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
target = input("Any specific target in mind? Please note only live, non cluwned, human targets are valid.", "Target", target) as null|anything in GLOB.player_list
|
||||
if(target && ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/mob/living/simple_animal/hostile/floor_cluwne/FC = new /mob/living/simple_animal/hostile/floor_cluwne(H.loc)
|
||||
FC.forced = TRUE
|
||||
FC.Acquire_Victim(H)
|
||||
FC.target = H
|
||||
FC.current_victim = H
|
||||
log_admin("[key_name(usr)] spawned floor cluwne.")
|
||||
message_admins("[key_name(usr)] spawned floor cluwne.")
|
||||
deadchat_broadcast("<span class='deadsay'><b>Floor Cluwne</b> has just been spawned!</span>")
|
||||
|
||||
/client/proc/spawn_random_floor_cluwne()
|
||||
set category = "Fun"
|
||||
set name = "Unleash Random Floor Cluwne"
|
||||
set desc = "Goes after a random player in your Z level. Be warned: spawning more than one may cause issues!"
|
||||
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(usr)
|
||||
new /mob/living/simple_animal/hostile/floor_cluwne(T)
|
||||
log_admin("[key_name(usr)] spawned a random target floor cluwne.")
|
||||
message_admins("[key_name(usr)] spawned a random target floor cluwne.")
|
||||
|
||||
/client/proc/spawn_twitch_plays_clowncar()
|
||||
set category = "Fun"
|
||||
set name = "Spawn Twich Plays: Clown Car Edition"
|
||||
set desc = "A clown car that weights the direction it goes based on the keys ghosts are pushing. Terrible idea? Maybe."
|
||||
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(usr)
|
||||
var/obj/vehicle/sealed/car/clowncar/twitch_plays/G = new /obj/vehicle/sealed/car/clowncar/twitch_plays(T)
|
||||
var/area/A = get_area(G)
|
||||
log_admin("[key_name(usr)] spawned a twitch plays clown car.")
|
||||
message_admins("[key_name(usr)] spawned a twitch plays clown car. Some soundtrack is likely recommended for the fuckshit that's about to unfold.")
|
||||
notify_ghosts("A Ghost Controlled Clown Car has been spawned at \the [A.name]! Double click it to orbit and wrestle its direction with other ghosts!", 'yogstation/sound/misc/bikehorn_creepy.ogg', source = G, action = NOTIFY_JUMP, flashwindow = FALSE)
|
||||
|
||||
277
hyperstation/code/modules/antagonists/wendigo/datums_hud.dm
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
Holds things like antag datums, game modes, abilities, and everything
|
||||
related to the antag that could be a datum
|
||||
*/
|
||||
|
||||
//ANTAGONIST
|
||||
/datum/antagonist/wendigo
|
||||
name = "wendigo"
|
||||
antagpanel_category = "Wendigo"
|
||||
|
||||
/datum/antagonist/wendigo/on_gain()
|
||||
if(istype(owner.current, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/wendigo/new_owner = new/mob/living/carbon/wendigo(get_turf(owner.current))
|
||||
var/mob/current_body = owner.current
|
||||
current_body.transfer_ckey(new_owner)
|
||||
current_body.Destroy()
|
||||
owner = new_owner.mind
|
||||
owner.current = new_owner
|
||||
..()
|
||||
|
||||
|
||||
//HUD
|
||||
//Contents: Intentions, Hands, Dropping/Throwing/Pulling, Inventory Equip
|
||||
// Health + Souls on the bottom of screen
|
||||
//TODO: Health doll, Soul counter (not devil)
|
||||
|
||||
/datum/hud/wendigo/New(mob/living/carbon/wendigo/owner)
|
||||
..()
|
||||
var/obj/screen/using
|
||||
var/obj/screen/inventory/inv_box
|
||||
|
||||
var/widescreenlayout = FALSE //adds support for different hud layouts depending on widescreen pref
|
||||
if(owner.client && owner.client.prefs && owner.client?.prefs?.widescreenpref)
|
||||
widescreenlayout = FALSE
|
||||
|
||||
//CRAFTING
|
||||
using = new /obj/screen/craft
|
||||
using.icon = ui_style
|
||||
if(!widescreenlayout)
|
||||
using.screen_loc = ui_boxcraft
|
||||
static_inventory += using
|
||||
|
||||
//LANG MENU
|
||||
using = new/obj/screen/language_menu
|
||||
using.icon = ui_style
|
||||
if(!widescreenlayout)
|
||||
using.screen_loc = ui_boxlang
|
||||
static_inventory += using
|
||||
|
||||
//AREA EDITOR
|
||||
using = new /obj/screen/area_creator
|
||||
using.icon = ui_style
|
||||
if(!widescreenlayout)
|
||||
using.screen_loc = ui_boxarea
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/voretoggle()
|
||||
using.icon = tg_ui_icon_to_cit_ui(ui_style)
|
||||
using.screen_loc = ui_voremode
|
||||
if(!widescreenlayout)
|
||||
using.screen_loc = ui_boxvore
|
||||
static_inventory += using
|
||||
|
||||
//INTENTS & ACTIONS
|
||||
action_intent = new /obj/screen/act_intent/segmented
|
||||
action_intent.icon_state = mymob.a_intent
|
||||
static_inventory += action_intent
|
||||
|
||||
using = new /obj/screen/human/equip()
|
||||
using.icon = ui_style
|
||||
using.screen_loc = ui_equip_position(mymob)
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/mov_intent
|
||||
using.icon = tg_ui_icon_to_cit_ui(ui_style)
|
||||
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
|
||||
using.screen_loc = ui_movi
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/resist()
|
||||
using.icon = ui_style
|
||||
using.screen_loc = ui_overridden_resist
|
||||
hotkeybuttons += using
|
||||
|
||||
using = new /obj/screen/restbutton()
|
||||
using.icon = tg_ui_icon_to_cit_ui(ui_style)
|
||||
using.screen_loc = ui_pull_resist
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/combattoggle()
|
||||
using.icon = tg_ui_icon_to_cit_ui(ui_style)
|
||||
using.screen_loc = ui_combat_toggle
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/drop()
|
||||
using.icon = ui_style
|
||||
using.screen_loc = ui_drop_throw
|
||||
static_inventory += using
|
||||
|
||||
pull_icon = new /obj/screen/pull()
|
||||
pull_icon.icon = ui_style
|
||||
pull_icon.update_icon(mymob)
|
||||
pull_icon.screen_loc = ui_pull_resist
|
||||
static_inventory += pull_icon
|
||||
|
||||
throw_icon = new /obj/screen/throw_catch()
|
||||
throw_icon.icon = ui_style
|
||||
throw_icon.screen_loc = ui_drop_throw
|
||||
hotkeybuttons += throw_icon
|
||||
|
||||
//////
|
||||
//INVENTORY
|
||||
//////
|
||||
build_hand_slots()
|
||||
|
||||
using = new /obj/screen/human/toggle()
|
||||
using.icon = ui_style
|
||||
using.screen_loc = ui_inventory
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/swap_hand()
|
||||
using.icon = ui_style
|
||||
using.icon_state = "swap_1"
|
||||
using.screen_loc = ui_swaphand_position(owner,1)
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/swap_hand()
|
||||
using.icon = ui_style
|
||||
using.icon_state = "swap_2"
|
||||
using.screen_loc = ui_swaphand_position(owner,2)
|
||||
static_inventory += using
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "neck"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "neck"
|
||||
inv_box.screen_loc = ui_neck
|
||||
inv_box.slot_id =ITEM_SLOT_NECK
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "back"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "back"
|
||||
inv_box.screen_loc = ui_back
|
||||
inv_box.slot_id =ITEM_SLOT_BACK
|
||||
static_inventory += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "gloves"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "gloves"
|
||||
inv_box.screen_loc = ui_gloves
|
||||
inv_box.slot_id =ITEM_SLOT_GLOVES
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "eyes"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "glasses"
|
||||
inv_box.screen_loc = ui_glasses
|
||||
inv_box.slot_id =ITEM_SLOT_GLASSES
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "ears"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "ears"
|
||||
inv_box.screen_loc = ui_ears
|
||||
inv_box.slot_id =ITEM_SLOT_EARS
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "head"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "head"
|
||||
inv_box.screen_loc = ui_head
|
||||
inv_box.slot_id =ITEM_SLOT_HEAD
|
||||
toggleable_inventory += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "belt"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.icon_state = "belt"
|
||||
inv_box.screen_loc = ui_belt
|
||||
inv_box.slot_id =ITEM_SLOT_BELT
|
||||
static_inventory += inv_box
|
||||
|
||||
//INFO DISPLAY
|
||||
|
||||
internals = new /obj/screen/internals()
|
||||
infodisplay += internals
|
||||
|
||||
healths = new /obj/screen/healths()
|
||||
infodisplay += healths
|
||||
|
||||
healthdoll = new /obj/screen/healthdoll()
|
||||
infodisplay += healthdoll
|
||||
|
||||
zone_select = new /obj/screen/zone_sel()
|
||||
zone_select.icon = ui_style
|
||||
zone_select.update_icon(mymob)
|
||||
static_inventory += zone_select
|
||||
|
||||
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
|
||||
if(inv.slot_id)
|
||||
inv.hud = src
|
||||
inv_slots[inv.slot_id] = inv
|
||||
inv.update_icon()
|
||||
|
||||
/datum/hud/wendigo/hidden_inventory_update(mob/viewer)
|
||||
if(!mymob)
|
||||
return
|
||||
var/mob/living/carbon/wendigo/W = mymob
|
||||
|
||||
var/mob/screenmob = viewer || W
|
||||
|
||||
if(screenmob.hud_used.inventory_shown && screenmob.hud_used.hud_shown)
|
||||
if(W.gloves)
|
||||
W.gloves.screen_loc = ui_gloves
|
||||
screenmob.client.screen += W.gloves
|
||||
if(W.ears)
|
||||
W.ears.screen_loc = ui_ears
|
||||
screenmob.client.screen += W.ears
|
||||
if(W.glasses)
|
||||
W.glasses.screen_loc = ui_glasses
|
||||
screenmob.client.screen += W.glasses
|
||||
if(W.wear_neck)
|
||||
W.wear_neck.screen_loc = ui_neck
|
||||
screenmob.client.screen += W.wear_neck
|
||||
if(W.head)
|
||||
W.head.screen_loc = ui_head
|
||||
screenmob.client.screen += W.head
|
||||
else
|
||||
if(W.gloves) screenmob.client.screen -= W.gloves
|
||||
if(W.ears) screenmob.client.screen -= W.ears
|
||||
if(W.glasses) screenmob.client.screen -= W.glasses
|
||||
if(W.wear_neck) screenmob.client.screen -= W.wear_neck
|
||||
if(W.head) screenmob.client.screen -= W.head
|
||||
|
||||
/datum/hud/wendigo/persistent_inventory_update(mob/viewer)
|
||||
if(!mymob)
|
||||
return
|
||||
..()
|
||||
var/mob/living/carbon/wendigo/W = mymob
|
||||
|
||||
var/mob/screenmob = viewer || W
|
||||
|
||||
if(screenmob.hud_used)
|
||||
if(screenmob.hud_used.hud_shown)
|
||||
if(W.belt)
|
||||
W.belt.screen_loc = ui_belt
|
||||
screenmob.client.screen += W.belt
|
||||
if(W.back)
|
||||
W.back.screen_loc = ui_back
|
||||
screenmob.client.screen += W.back
|
||||
else
|
||||
if(W.belt)
|
||||
screenmob.client.screen -= W.belt
|
||||
if(W.back)
|
||||
screenmob.client.screen -= W.back
|
||||
|
||||
if(hud_version != HUD_STYLE_NOHUD)
|
||||
for(var/obj/item/I in W.held_items)
|
||||
I.screen_loc = ui_hand_position(W.get_held_index_of_item(I))
|
||||
screenmob.client.screen += I
|
||||
else
|
||||
for(var/obj/item/I in W.held_items)
|
||||
I.screen_loc = null
|
||||
screenmob.client.screen -= I
|
||||
|
||||
/datum/hud/wendigo/show_hud(version = 0,mob/viewmob)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/mob/screenmob = viewmob || mymob
|
||||
hidden_inventory_update(screenmob)
|
||||
@@ -0,0 +1,14 @@
|
||||
/obj/structure/soul_storage
|
||||
name = "soul storage"
|
||||
desc = "Stores souls!"
|
||||
var/list/souls = list()
|
||||
|
||||
//This is a big WIP. I don't even want it having the name "soul storage" but it'll do for now
|
||||
|
||||
/obj/structure/soul_storage/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.wendigo_soul_storages += src
|
||||
|
||||
/obj/structure/soul_storage/Destroy()
|
||||
GLOB.wendigo_soul_storages -= src
|
||||
return ..()
|
||||
@@ -0,0 +1,11 @@
|
||||
/mob/living/carbon/wendigo/UnarmedAttack(atom/A, proximity)
|
||||
A.attack_hand(src)
|
||||
|
||||
/mob/living/carbon/wendigo/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(incapacitated() || lying)
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
if(be_close && !in_range(M, src))
|
||||
to_chat(src, "<span class='warning'>You are too far away!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -0,0 +1,115 @@
|
||||
#define DEFAULT_MOVESPEED 1.5
|
||||
//The mob itself
|
||||
/mob/living/carbon/wendigo
|
||||
name = "wendigo"
|
||||
gender = FEMALE
|
||||
unique_name = FALSE
|
||||
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD, NANITE_HUD, DIAG_NANITE_FULL_HUD,ANTAG_HUD,GLAND_HUD,SENTIENT_DISEASE_HUD)
|
||||
hud_type = /datum/hud/wendigo
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
|
||||
appearance_flags = TILE_BOUND|PIXEL_SCALE|LONG_GLIDE
|
||||
status_flags = CANSTUN //cant be knocked down, unconscious, or be pushed
|
||||
maxHealth = 200
|
||||
icon = 'hyperstation/icons/mobs/wendigo.dmi'
|
||||
icon_state = "reference"
|
||||
|
||||
bodyparts = list(/obj/item/bodypart/chest/wendigo, /obj/item/bodypart/head/wendigo,
|
||||
/obj/item/bodypart/l_arm/wendigo, /obj/item/bodypart/r_arm/wendigo,
|
||||
/obj/item/bodypart/l_leg/wendigo, /obj/item/bodypart/r_leg/wendigo)
|
||||
var/obj/item/belt = null
|
||||
var/datum/physiology/physiology
|
||||
var/obj/structure/soul_storage/connected_link
|
||||
var/fake_breast_size = 5 //She doesn't actually have the organ, but we cache her breast size for rp reasons
|
||||
var/fake_penis_size = 8
|
||||
|
||||
/mob/living/carbon/wendigo/Initialize(mapload)
|
||||
. = ..()
|
||||
/* //TODO: Uncomment when objectives + forest get finished
|
||||
if(!connected_link)
|
||||
if(!GLOB.wendigo_soul_storages.len)
|
||||
connected_link = new /obj/structure/soul_storage(get_turf(src))
|
||||
else
|
||||
connected_link = pick(GLOB.wendigo_soul_storages)
|
||||
gender = pick(FEMALE, MALE)
|
||||
*/
|
||||
if(gender == MALE)
|
||||
fake_breast_size = 0
|
||||
else
|
||||
fake_penis_size = 0
|
||||
real_name = name
|
||||
//DAMAGE RESISTANCE
|
||||
physiology = new()
|
||||
physiology.brute_mod = 0.7
|
||||
physiology.burn_mod = 1.25
|
||||
physiology.tox_mod = -1
|
||||
physiology.oxy_mod = 1
|
||||
physiology.clone_mod = 0
|
||||
physiology.stamina_mod = 0 //Running and attacking, prods
|
||||
physiology.heat_mod = 2 //IM MELTIIINNNGGGG-!
|
||||
physiology.cold_mod = 0
|
||||
physiology.siemens_coeff = 0.2
|
||||
physiology.stun_mod = 0 //prods n aggressive grab
|
||||
//physiology.bleed_mod = 2
|
||||
physiology.speed_mod = 0.9 //Should be faster than a normal person's walking speed
|
||||
physiology.hunger_mod = 2 //We're gonna have a FEAST TONIGHT!
|
||||
physiology.do_after_speed = 1
|
||||
|
||||
//Traits & Bodyparts
|
||||
create_bodyparts()
|
||||
create_internal_organs()
|
||||
ADD_TRAIT(src, TRAIT_NOCLONE, "initialize")
|
||||
add_verb(src, /mob/living/proc/mob_sleep)
|
||||
add_verb(src, /mob/living/proc/lay_down)
|
||||
add_movespeed_modifier("MOVESPEED_DEFAULT", multiplicative_slowdown=DEFAULT_MOVESPEED)
|
||||
update_body_parts()
|
||||
|
||||
/mob/living/carbon/wendigo/Destroy()
|
||||
QDEL_NULL(physiology)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/wendigo/update_body_parts()
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
BP.update_limb()
|
||||
|
||||
/mob/living/carbon/wendigo/update_move_intent_slowdown()
|
||||
var/mod = 0
|
||||
if(m_intent == MOVE_INTENT_WALK)
|
||||
mod = (CONFIG_GET(number/movedelay/walk_delay) / 2) //complete copy besides this part
|
||||
else
|
||||
mod = 1.30
|
||||
if(!isnum(mod))
|
||||
mod = 1
|
||||
add_movespeed_modifier(MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED, TRUE, 100, override = TRUE, multiplicative_slowdown = mod)
|
||||
|
||||
/mob/living/carbon/wendigo/update_movespeed(resort=TRUE)
|
||||
return (..() * physiology.speed_mod)
|
||||
|
||||
/mob/living/carbon/wendigo/can_hold_items()
|
||||
return TRUE
|
||||
/mob/living/carbon/wendigo/IsAdvancedToolUser()
|
||||
return TRUE
|
||||
/mob/living/carbon/wendigo/can_be_pulled()
|
||||
return FALSE
|
||||
/mob/living/carbon/wendigo/is_literate()
|
||||
return TRUE
|
||||
/mob/living/carbon/wendigo/canBeHandcuffed()
|
||||
return TRUE
|
||||
/mob/living/carbon/wendigo/update_inv_handcuffed()
|
||||
return
|
||||
/mob/living/carbon/wendigo/update_inv_legcuffed()
|
||||
return
|
||||
|
||||
//
|
||||
//ORGANS
|
||||
//
|
||||
/mob/living/carbon/wendigo/create_internal_organs()
|
||||
internal_organs += new /obj/item/organ/eyes/wendigo
|
||||
internal_organs += new /obj/item/organ/liver/wendigo
|
||||
|
||||
internal_organs += new /obj/item/organ/tongue
|
||||
internal_organs += new /obj/item/organ/lungs
|
||||
internal_organs += new /obj/item/organ/heart
|
||||
internal_organs += new /obj/item/organ/stomach
|
||||
internal_organs += new /obj/item/organ/ears
|
||||
..()
|
||||
86
hyperstation/code/modules/antagonists/wendigo/mob/examine.dm
Normal file
@@ -0,0 +1,86 @@
|
||||
/mob/living/carbon/wendigo/examine(mob/user)
|
||||
var/t_He = p_they(TRUE)
|
||||
var/t_His = p_their(TRUE)
|
||||
var/t_his = p_their()
|
||||
var/t_him = p_them()
|
||||
|
||||
. = list("<span class='info'>*---------*\nThis is [icon2html(src, user)] \a <EM>[src]</EM>!")
|
||||
|
||||
if(handcuffed)
|
||||
. += "<span class='warning'>[t_He] is [icon2html(handcuffed, user)] handcuffed!</span>"
|
||||
if(legcuffed)
|
||||
. += "<span class='warning'>[t_He] has [icon2html(legcuffed, user)] leg cuffs!</span>"
|
||||
if(head)
|
||||
. += "[t_He] is wearing [head.get_examine_string(user)] on [t_his] head."
|
||||
if(wear_neck)
|
||||
. += "[t_He] is wearing [wear_neck.get_examine_string(user)] around [t_his] neck."
|
||||
|
||||
for(var/obj/item/I in held_items)
|
||||
if(!(I.item_flags & ABSTRACT))
|
||||
. += "[t_He] is holding [I.get_examine_string(user)] in [t_his] [get_held_index_name(get_held_index_of_item(I))]."
|
||||
|
||||
if(back)
|
||||
. += "[t_He] has [back.get_examine_string(user)] on [t_his] back."
|
||||
|
||||
if(stat == DEAD)
|
||||
. += "<span class='deadsay'>[t_He] is limp and unresponsive, with no signs of life.</span>"
|
||||
|
||||
var/list/msg = ("<span class='warning'>")
|
||||
var/temp_hp = getBruteLoss()
|
||||
if(!(user == src && src.hal_screwyhud == SCREWYHUD_HEALTHY))
|
||||
if(temp_hp)
|
||||
if(temp_hp <= 25) msg += "[t_He] has minor bruising.\n"
|
||||
else if(temp_hp <= 75) msg += "[t_He] has <B>moderate</B> bruising!\n"
|
||||
else msg += "<B>[t_He] has severe bruising!</B>\n"
|
||||
temp_hp = getFireLoss()
|
||||
if(temp_hp)
|
||||
if(temp_hp <= 25) msg += "[t_He] has minor burns.\n"
|
||||
else if(temp_hp <= 50) msg += "[t_He] has <B>moderate</B> burns!\n"
|
||||
else msg += "<B>[t_He] has severe burns!</B>\n"
|
||||
if(fire_stacks > 0)
|
||||
msg += "[t_He] is covered in something flammable.\n"
|
||||
if(fire_stacks < 0)
|
||||
msg += "[t_He] looks a little soaked.\n"
|
||||
if(pulledby)
|
||||
if(pulledby.grab_state)
|
||||
msg += "[t_He] is restrained by [pulledby]'s grip.\n"
|
||||
|
||||
msg += "</span>"
|
||||
. += msg
|
||||
|
||||
if(stat == UNCONSCIOUS)
|
||||
. += "[t_He] isn't responding to anything around [t_him] and seems to be asleep."
|
||||
else if(InCritical())
|
||||
. += "[t_His] breathing is shallow and labored."
|
||||
|
||||
|
||||
if(fake_breast_size < 16)
|
||||
. += "You see a pair of breasts. You estimate them to be [ascii2text(round(fake_breast_size)+63)]-cups."
|
||||
else if(!fake_breast_size && gender == FEMALE)
|
||||
. += "You see a pair of breasts. They're small and flatchested, however."
|
||||
else
|
||||
. += "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(fake_breast_size)]cm in diameter."
|
||||
|
||||
if(fake_penis_size)
|
||||
. += "You see a flaccid human penis. You estimate it's about [round(fake_penis_size, 0.25)] inch[round(fake_penis_size, 0.25) != 1 ? "es" : ""] long." //would put girth here but lazy
|
||||
|
||||
if(connected_link)
|
||||
if(connected_link.souls.len > 5)
|
||||
. += "<span class='warning'><B>[t_His] eyes are glowing a deadly red.</B></span>"
|
||||
else
|
||||
var/A = "<span class='deadsay'>"
|
||||
switch(connected_link.souls.len)
|
||||
if(0)
|
||||
A += "[t_He] looks malnourished and weak."
|
||||
if(1)
|
||||
A += "[t_He] looks hungry."
|
||||
if(2 to 4)
|
||||
A += "[t_He] is salivating."
|
||||
if(5)
|
||||
A += "[t_His] eyes are glowing red."
|
||||
. += "[A]</span>"
|
||||
else
|
||||
. += "<span class='deadsay'>[t_He] looks lost.</span>"
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, .)
|
||||
. += "*---------*</span>"
|
||||
@@ -0,0 +1,55 @@
|
||||
//Snowflake metabolization with naughty organ manipulation
|
||||
/mob/living/carbon/wendigo/proc/metabolize_hunger()
|
||||
if(HAS_TRAIT(src, TRAIT_NOHUNGER))
|
||||
return
|
||||
|
||||
if(connected_link)
|
||||
if(connected_link.souls.len > 3)
|
||||
nutrition = min(800, nutrition + (HUNGER_FACTOR*connected_link.souls.len))
|
||||
nutrition = max(0, nutrition - (HUNGER_FACTOR / (physiology.hunger_mod / (connected_link.souls.len + 1))))
|
||||
else
|
||||
nutrition = max(0, nutrition - (HUNGER_FACTOR / physiology.hunger_mod))
|
||||
|
||||
switch(nutrition)
|
||||
if(NUTRITION_LEVEL_WELL_FED to INFINITY)
|
||||
throw_alert("nutrition", /obj/screen/alert/full)
|
||||
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
|
||||
throw_alert("nutrition", /obj/screen/alert/sated)
|
||||
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
|
||||
throw_alert("nutrition", /obj/screen/alert/hungry)
|
||||
if(0 to NUTRITION_LEVEL_STARVING)
|
||||
throw_alert("nutrition", /obj/screen/alert/starving)
|
||||
|
||||
/mob/living/carbon/wendigo/reagent_check(datum/reagent/R)
|
||||
if(istype(R, /datum/reagent/fermi))
|
||||
var/had_changed = FALSE
|
||||
if(R.type == /datum/reagent/fermi/penis_enlarger)
|
||||
fake_penis_size += 0.25
|
||||
had_changed = "penis_enlarger"
|
||||
if(R.type == /datum/reagent/fermi/PEsmaller)
|
||||
fake_penis_size = max(0, fake_penis_size - 0.25)
|
||||
had_changed = "PEsmaller"
|
||||
if(R.type == /datum/reagent/fermi/breast_enlarger)
|
||||
fake_breast_size += 0.25
|
||||
had_changed = "breast_enlarger"
|
||||
if(R.type == /datum/reagent/fermi/BEsmaller)
|
||||
fake_breast_size = max(0, fake_breast_size - 0.25)
|
||||
had_changed = "BEsmaller"
|
||||
|
||||
if(had_changed)
|
||||
R.volume -= R.metabolization_rate
|
||||
if(round(fake_penis_size, 1) == fake_penis_size && fake_penis_size)
|
||||
switch(had_changed)
|
||||
if("penis_enlarger")
|
||||
to_chat(src, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("swells up to", "flourishes into", "expands into", "bursts forth into", "grows eagerly into", "amplifys into")] a [fake_penis_size] inch penis.</b></span>")
|
||||
if("PEsmaller")
|
||||
if(fake_penis_size > 0)
|
||||
to_chat(src, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("shrinks down to", "decreases into", "diminishes into", "deflates into", "shrivels regretfully into", "contracts into")] a [fake_penis_size] inch penis.</b></span>")
|
||||
else if(round(fake_breast_size, 1) == fake_breast_size && fake_breast_size)
|
||||
switch(had_changed)
|
||||
if("breast_enlarger")
|
||||
to_chat(src, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [ascii2text(round(fake_breast_size)+63)]-cup.</b></span>")
|
||||
if("BEsmaller)")
|
||||
if(fake_breast_size > 0)
|
||||
to_chat(src, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [ascii2text(round(fake_breast_size)+63)]-cup.</b></span>")
|
||||
return TRUE
|
||||
125
hyperstation/code/modules/antagonists/wendigo/mob/mob_defense.dm
Normal file
@@ -0,0 +1,125 @@
|
||||
/mob/living/carbon/wendigo/handle_environment(datum/gas_mixture/environment)
|
||||
if(!environment)
|
||||
return
|
||||
|
||||
var/loc_temp = get_temperature(environment)
|
||||
|
||||
if(stat != DEAD)
|
||||
adjust_bodytemperature(natural_bodytemperature_stabilization())
|
||||
|
||||
if(!on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases
|
||||
if(loc_temp < bodytemperature)
|
||||
adjust_bodytemperature(max((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR, BODYTEMP_COOLING_MAX))
|
||||
else
|
||||
adjust_bodytemperature(min((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR, BODYTEMP_HEATING_MAX))
|
||||
|
||||
|
||||
if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !HAS_TRAIT(src, TRAIT_RESISTHEAT))
|
||||
switch(bodytemperature)
|
||||
if(280 to 300)
|
||||
throw_alert("temp", /obj/screen/alert/hot, 1)
|
||||
apply_damage(HEAT_DAMAGE_LEVEL_1*physiology.heat_mod, BURN)
|
||||
if(300 to 350)
|
||||
throw_alert("temp", /obj/screen/alert/hot, 2)
|
||||
apply_damage(HEAT_DAMAGE_LEVEL_2*physiology.heat_mod, BURN)
|
||||
if(350 to INFINITY)
|
||||
throw_alert("temp", /obj/screen/alert/hot, 3)
|
||||
if(on_fire)
|
||||
apply_damage(HEAT_DAMAGE_LEVEL_3*physiology.heat_mod, BURN)
|
||||
else
|
||||
apply_damage(HEAT_DAMAGE_LEVEL_2*physiology.heat_mod, BURN)
|
||||
|
||||
else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(src, TRAIT_RESISTCOLD))
|
||||
if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
|
||||
switch(bodytemperature)
|
||||
if(200 to 260)
|
||||
throw_alert("temp", /obj/screen/alert/cold, 1)
|
||||
apply_damage(COLD_DAMAGE_LEVEL_1*physiology.cold_mod, BURN)
|
||||
if(0 to 120)
|
||||
throw_alert("temp", /obj/screen/alert/cold, 2)
|
||||
apply_damage(COLD_DAMAGE_LEVEL_2*physiology.cold_mod, BURN)
|
||||
if(-INFINITY to 0)
|
||||
throw_alert("temp", /obj/screen/alert/cold, 3)
|
||||
apply_damage(COLD_DAMAGE_LEVEL_3*physiology.cold_mod, BURN)
|
||||
else
|
||||
clear_alert("temp")
|
||||
|
||||
else
|
||||
clear_alert("temp")
|
||||
|
||||
//Account for massive pressure differences
|
||||
|
||||
var/pressure = environment.return_pressure()
|
||||
var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob.
|
||||
switch(adjusted_pressure)
|
||||
if(HAZARD_HIGH_PRESSURE to INFINITY)
|
||||
adjustBruteLoss(min((((adjusted_pressure / HAZARD_HIGH_PRESSURE)-1)*PRESSURE_DAMAGE_COEFFICIENT)*physiology.pressure_mod, MAX_HIGH_PRESSURE_DAMAGE))
|
||||
throw_alert("pressure", /obj/screen/alert/highpressure, 2)
|
||||
if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
|
||||
throw_alert("pressure", /obj/screen/alert/highpressure, 1)
|
||||
if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
|
||||
clear_alert("pressure")
|
||||
if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
|
||||
throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
|
||||
else
|
||||
adjustBruteLoss( LOW_PRESSURE_DAMAGE*physiology.pressure_mod )
|
||||
throw_alert("pressure", /obj/screen/alert/lowpressure, 2)
|
||||
|
||||
return
|
||||
|
||||
/mob/living/carbon/wendigo/handle_breath_temperature(datum/gas_mixture/breath)
|
||||
if(abs(BODYTEMP_NORMAL - breath.temperature) > 50)
|
||||
switch(breath.temperature)
|
||||
if(-INFINITY to 0)
|
||||
adjustFireLoss(3)
|
||||
if(0 to 120) //We flourish in a cold environment
|
||||
adjustFireLoss(1.5)
|
||||
if(298 to 350) //But hoo boy do we not like the heat
|
||||
adjustFireLoss(2)
|
||||
if(350 to 800)
|
||||
adjustFireLoss(3)
|
||||
if(800 to INFINITY)
|
||||
adjustFireLoss(8)
|
||||
|
||||
/mob/living/carbon/wendigo/handle_fire()
|
||||
if(..())
|
||||
return
|
||||
adjust_bodytemperature(BODYTEMP_HEATING_MAX*physiology.heat_mod)
|
||||
return
|
||||
|
||||
/mob/living/carbon/wendigo/adjustBruteLoss(amount, updating_health, forced)
|
||||
return ..(amount*physiology.brute_mod, updating_health, forced)
|
||||
|
||||
/mob/living/carbon/wendigo/adjustFireLoss(amount, updating_health, forced)
|
||||
return ..(amount*physiology.burn_mod, updating_health, forced)
|
||||
|
||||
/mob/living/carbon/wendigo/adjustToxLoss(amount, updating_health, forced)
|
||||
return ..(amount*physiology.tox_mod, updating_health, forced)
|
||||
|
||||
/mob/living/carbon/wendigo/adjustOxyLoss(amount, updating_health, forced)
|
||||
return ..(amount*physiology.oxy_mod, updating_health, forced)
|
||||
|
||||
/mob/living/carbon/wendigo/adjustCloneLoss(amount, updating_health, forced)
|
||||
return ..(amount*physiology.clone_mod, updating_health, forced)
|
||||
|
||||
/mob/living/carbon/wendigo/adjustStaminaLoss(amount, updating_health, forced)
|
||||
return ..(amount*physiology.stamina_mod, updating_health, forced)
|
||||
|
||||
/mob/living/carbon/wendigo/do_after_coefficent()
|
||||
. = ..()
|
||||
. *= physiology.do_after_speed
|
||||
|
||||
/mob/living/carbon/wendigo/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
|
||||
return ..(shock_damage, source, physiology.siemens_coeff, safety, override, tesla_shock, illusion, stun)
|
||||
|
||||
/mob/living/carbon/wendigo/Stun(amount, updating, ignore_canstun)
|
||||
return ..(amount*physiology.stun_mod, updating, ignore_canstun)
|
||||
|
||||
/mob/living/carbon/wendigo/Knockdown(amount, updating, ignore_canknockdown, override_hardstun, override_stamdmg)
|
||||
return ..(amount*physiology.stun_mod, updating, ignore_canknockdown, override_hardstun, override_stamdmg)
|
||||
|
||||
/mob/living/carbon/wendigo/Unconscious(amount, updating, ignore_canunconscious)
|
||||
return ..(amount*physiology.stun_mod, updating, ignore_canunconscious)
|
||||
|
||||
/mob/living/carbon/wendigo/bleed(amt)
|
||||
return ..(amt*physiology.bleed_mod)
|
||||
100
hyperstation/code/modules/antagonists/wendigo/mob/mob_equip.dm
Normal file
@@ -0,0 +1,100 @@
|
||||
/mob/living/carbon/wendigo/can_equip(obj/item/I, slot, disable_warning)
|
||||
switch(slot)
|
||||
if(SLOT_HANDS)
|
||||
if(get_empty_held_indexes())
|
||||
return TRUE
|
||||
return FALSE
|
||||
if(SLOT_GLASSES)
|
||||
if(glasses)
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_EYES))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(SLOT_NECK)
|
||||
if(wear_neck)
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_NECK))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(SLOT_EARS)
|
||||
if(ears)
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_EARS))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(SLOT_GLOVES)
|
||||
if(gloves)
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_GLOVES))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(SLOT_BACK)
|
||||
if(back)
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_BACK))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(SLOT_IN_BACKPACK)
|
||||
if(back)
|
||||
if(SEND_SIGNAL(back, COMSIG_TRY_STORAGE_CAN_INSERT, I, src, TRUE))
|
||||
return TRUE
|
||||
return FALSE
|
||||
if(SLOT_HEAD)
|
||||
if(head)
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_HEAD))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(SLOT_BELT)
|
||||
if(belt)
|
||||
return FALSE
|
||||
if(!(I.slot_flags & ITEM_SLOT_BELT))
|
||||
return FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/wendigo/equip_to_slot(obj/item/I, slot)
|
||||
if(!..())
|
||||
return
|
||||
switch(slot)
|
||||
if(SLOT_GLASSES)
|
||||
glasses = I
|
||||
update_inv_glasses()
|
||||
if(SLOT_EARS)
|
||||
ears = I
|
||||
update_inv_ears()
|
||||
if(SLOT_GLOVES)
|
||||
gloves = I
|
||||
update_inv_gloves()
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/wendigo/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
|
||||
. = ..()
|
||||
if(!. || !I)
|
||||
return
|
||||
|
||||
else if(I == gloves)
|
||||
gloves = null
|
||||
if(!QDELETED(src))
|
||||
update_inv_gloves()
|
||||
else if(I == glasses)
|
||||
glasses = null
|
||||
var/obj/item/clothing/glasses/G = I
|
||||
if(G.tint)
|
||||
update_tint()
|
||||
if(G.vision_correction)
|
||||
if(HAS_TRAIT(src, TRAIT_NEARSIGHT))
|
||||
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
|
||||
adjust_eye_damage(0)
|
||||
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
|
||||
update_sight()
|
||||
if(!QDELETED(src))
|
||||
update_inv_glasses()
|
||||
else if(I == ears)
|
||||
ears = null
|
||||
if(!QDELETED(src))
|
||||
update_inv_ears()
|
||||
else if(I == belt)
|
||||
belt = null
|
||||
if(!QDELETED(src))
|
||||
update_inv_belt()
|
||||
@@ -0,0 +1,58 @@
|
||||
/obj/item/organ/liver/wendigo
|
||||
name = "rotten liver"
|
||||
desc = "A liver from a wendigo. It looks like a spoiled tomato."
|
||||
decay_factor = 0
|
||||
|
||||
/obj/item/organ/liver/wendigo/on_life()
|
||||
var/mob/living/carbon/C = owner
|
||||
if(istype(C))
|
||||
damage = initial(maxHealth)
|
||||
|
||||
if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER))
|
||||
//handle liver toxin filtration
|
||||
for(var/datum/reagent/toxin/T in C.reagents.reagent_list)
|
||||
var/thisamount = C.reagents.get_reagent_amount(T.type)
|
||||
if (thisamount && thisamount <= toxTolerance)
|
||||
C.reagents.remove_reagent(T.type, 1)
|
||||
|
||||
C.reagents.metabolize(C, can_overdose=FALSE)
|
||||
if(istype(C, /mob/living/carbon/wendigo))
|
||||
var/mob/living/carbon/wendigo/A = C
|
||||
A.metabolize_hunger()
|
||||
|
||||
/obj/item/organ/eyes/wendigo
|
||||
sight_flags = SEE_MOBS
|
||||
|
||||
/obj/item/bodypart/head/wendigo
|
||||
dismemberable = FALSE
|
||||
max_damage = INFINITY
|
||||
animal_origin = WENDIGO_BODYPART
|
||||
|
||||
/obj/item/bodypart/chest/wendigo
|
||||
dismemberable = FALSE
|
||||
max_damage = INFINITY
|
||||
animal_origin = WENDIGO_BODYPART
|
||||
|
||||
/obj/item/bodypart/l_arm/wendigo
|
||||
dismemberable = FALSE
|
||||
max_damage = INFINITY
|
||||
attack_verb = list("slashed", "clawed", "mauled")
|
||||
animal_origin = WENDIGO_BODYPART
|
||||
|
||||
/obj/item/bodypart/r_arm/wendigo
|
||||
dismemberable = FALSE
|
||||
max_damage = INFINITY
|
||||
attack_verb = list("slashed", "clawed", "mauled")
|
||||
animal_origin = WENDIGO_BODYPART
|
||||
|
||||
/obj/item/bodypart/l_leg/wendigo
|
||||
dismemberable = FALSE
|
||||
max_damage = INFINITY
|
||||
attack_verb = list("pounded", "stomped", "stamped", "kicked")
|
||||
animal_origin = WENDIGO_BODYPART
|
||||
|
||||
/obj/item/bodypart/r_leg/wendigo
|
||||
dismemberable = FALSE
|
||||
max_damage = INFINITY
|
||||
attack_verb = list("pounded", "stomped", "stamped", "kicked")
|
||||
animal_origin = WENDIGO_BODYPART
|
||||
@@ -0,0 +1,370 @@
|
||||
#define HEAD_X_OFFSET_NORTH 2
|
||||
#define HEAD_Y_OFFSET_NORTH 8
|
||||
#define HEAD_X_OFFSET_EAST 2
|
||||
#define HEAD_Y_OFFSET_EAST 8
|
||||
#define HEAD_X_OFFSET_SOUTH 8
|
||||
#define HEAD_Y_OFFSET_SOUTH 2
|
||||
#define HEAD_X_OFFSET_WEST 8
|
||||
#define HEAD_Y_OFFSET_WEST -2
|
||||
|
||||
#define LHAND_X_OFFSET_NORTH -5
|
||||
#define LHAND_Y_OFFSET_NORTH 3
|
||||
#define LHAND_X_OFFSET_EAST -2
|
||||
#define LHAND_Y_OFFSET_EAST 3
|
||||
#define LHAND_X_OFFSET_SOUTH 8
|
||||
#define LHAND_Y_OFFSET_SOUTH 3
|
||||
#define LHAND_X_OFFSET_WEST -2
|
||||
#define LHAND_Y_OFFSET_WEST 3
|
||||
|
||||
#define RHAND_X_OFFSET_NORTH 8
|
||||
#define RHAND_Y_OFFSET_NORTH 3
|
||||
#define RHAND_X_OFFSET_EAST 2
|
||||
#define RHAND_Y_OFFSET_EAST 3
|
||||
#define RHAND_X_OFFSET_SOUTH -5
|
||||
#define RHAND_Y_OFFSET_SOUTH 3
|
||||
#define RHAND_X_OFFSET_WEST 2
|
||||
#define RHAND_Y_OFFSET_WEST 3
|
||||
|
||||
#define EARS_X_OFFSET_NORTH 0
|
||||
#define EARS_Y_OFFSET_NORTH 0
|
||||
#define EARS_X_OFFSET_EAST 0
|
||||
#define EARS_Y_OFFSET_EAST 0
|
||||
#define EARS_X_OFFSET_SOUTH 0
|
||||
#define EARS_Y_OFFSET_SOUTH 0
|
||||
#define EARS_X_OFFSET_WEST 0
|
||||
#define EARS_Y_OFFSET_WEST 0
|
||||
|
||||
#define GLASSES_X_OFFSET_NORTH 5
|
||||
#define GLASSES_Y_OFFSET_NORTH 10
|
||||
#define GLASSES_X_OFFSET_EAST 1
|
||||
#define GLASSES_Y_OFFSET_EAST 10
|
||||
#define GLASSES_X_OFFSET_SOUTH -2
|
||||
#define GLASSES_Y_OFFSET_SOUTH 10
|
||||
#define GLASSES_X_OFFSET_WEST -1
|
||||
#define GLASSES_Y_OFFSET_WEST 10
|
||||
|
||||
#define BELT_X_OFFSET_NORTH 0
|
||||
#define BELT_Y_OFFSET_NORTH 10
|
||||
#define BELT_X_OFFSET_EAST 0
|
||||
#define BELT_Y_OFFSET_EAST 0
|
||||
#define BELT_X_OFFSET_SOUTH 0
|
||||
#define BELT_Y_OFFSET_SOUTH 0
|
||||
#define BELT_X_OFFSET_WEST 0
|
||||
#define BELT_Y_OFFSET_WEST 0
|
||||
|
||||
#define BACK_X_OFFSET_NORTH 1
|
||||
#define BACK_Y_OFFSET_NORTH 8
|
||||
#define BACK_X_OFFSET_EAST 0
|
||||
#define BACK_Y_OFFSET_EAST 8
|
||||
#define BACK_X_OFFSET_SOUTH 1
|
||||
#define BACK_Y_OFFSET_SOUTH 8
|
||||
#define BACK_X_OFFSET_WEST 0
|
||||
#define BACK_Y_OFFSET_WEST 8
|
||||
|
||||
#define NECK_X_OFFSET_NORTH 2
|
||||
#define NECK_Y_OFFSET_NORTH 10
|
||||
#define NECK_X_OFFSET_EAST 0
|
||||
#define NECK_Y_OFFSET_EAST 10
|
||||
#define NECK_X_OFFSET_SOUTH 2
|
||||
#define NECK_Y_OFFSET_SOUTH 10
|
||||
#define NECK_X_OFFSET_WEST 0
|
||||
#define NECK_Y_OFFSET_WEST 10
|
||||
|
||||
/mob/living/carbon/wendigo/setDir(newdir, ismousemovement)
|
||||
if(dir == newdir)
|
||||
return //Don't spend time regenerating icons when we don't move
|
||||
. = ..()
|
||||
regenerate_icons()
|
||||
|
||||
/mob/living/carbon/wendigo/regenerate_icons()
|
||||
if(!..())
|
||||
update_inv_head()
|
||||
update_inv_gloves()
|
||||
update_inv_ears()
|
||||
update_inv_glasses()
|
||||
update_inv_belt()
|
||||
update_inv_back()
|
||||
update_inv_neck()
|
||||
update_transform()
|
||||
|
||||
/mob/living/carbon/wendigo/update_inv_gloves()
|
||||
if(gloves)
|
||||
gloves.screen_loc = ui_gloves
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += gloves
|
||||
|
||||
//GLASSES
|
||||
/mob/living/carbon/wendigo/update_inv_glasses()
|
||||
if(glasses)
|
||||
glasses.screen_loc = ui_glasses
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += glasses
|
||||
|
||||
//EARS
|
||||
/mob/living/carbon/wendigo/update_inv_ears()
|
||||
remove_overlay(EARS_LAYER)
|
||||
if(ears)
|
||||
if(client && hud_used)
|
||||
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS]
|
||||
inv.update_icon()
|
||||
ears.screen_loc = ui_ears //move the item to the appropriate screen loc
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += ears
|
||||
|
||||
overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = ((ears.alternate_worn_icon) ? ears.alternate_worn_icon : 'icons/mob/ears.dmi'))
|
||||
var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
ears_overlay.pixel_x += EARS_X_OFFSET_NORTH
|
||||
ears_overlay.pixel_y += EARS_Y_OFFSET_NORTH
|
||||
if(EAST)
|
||||
ears_overlay.pixel_x += EARS_X_OFFSET_EAST
|
||||
ears_overlay.pixel_y += EARS_Y_OFFSET_EAST
|
||||
if(SOUTH)
|
||||
ears_overlay.pixel_x += EARS_X_OFFSET_SOUTH
|
||||
ears_overlay.pixel_y += EARS_Y_OFFSET_SOUTH
|
||||
if(WEST)
|
||||
ears_overlay.pixel_x += EARS_X_OFFSET_WEST
|
||||
ears_overlay.pixel_y += EARS_Y_OFFSET_WEST
|
||||
overlays_standing[EARS_LAYER] = ears_overlay
|
||||
apply_overlay(EARS_LAYER)
|
||||
|
||||
//BELT
|
||||
/mob/living/carbon/wendigo/update_inv_belt()
|
||||
remove_overlay(BELT_LAYER)
|
||||
|
||||
if(belt)
|
||||
belt.screen_loc = ui_belt
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += belt
|
||||
|
||||
var/t_state = belt.item_state
|
||||
if(!t_state)
|
||||
t_state = belt.icon_state
|
||||
|
||||
overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = ((belt.alternate_worn_icon) ? belt.alternate_worn_icon : 'icons/mob/belt.dmi'))
|
||||
var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
belt_overlay.pixel_x += BELT_X_OFFSET_NORTH
|
||||
belt_overlay.pixel_y += BELT_Y_OFFSET_NORTH
|
||||
if(EAST)
|
||||
belt_overlay.pixel_x += BELT_X_OFFSET_EAST
|
||||
belt_overlay.pixel_y += BELT_Y_OFFSET_EAST
|
||||
if(SOUTH)
|
||||
belt_overlay.pixel_x += BELT_X_OFFSET_SOUTH
|
||||
belt_overlay.pixel_y += BELT_Y_OFFSET_SOUTH
|
||||
if(WEST)
|
||||
belt_overlay.pixel_x += BELT_X_OFFSET_WEST
|
||||
belt_overlay.pixel_y += BELT_Y_OFFSET_WEST
|
||||
overlays_standing[BELT_LAYER] = belt_overlay
|
||||
apply_overlay(BELT_LAYER)
|
||||
|
||||
//BACK
|
||||
/mob/living/carbon/wendigo/update_inv_back()
|
||||
..()
|
||||
if(back)
|
||||
back.screen_loc = ui_back
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += back
|
||||
var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
|
||||
if(back_overlay)
|
||||
remove_overlay(BACK_LAYER)
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
back_overlay.pixel_x += BACK_X_OFFSET_NORTH
|
||||
back_overlay.pixel_y += BACK_Y_OFFSET_NORTH
|
||||
if(EAST)
|
||||
back_overlay.pixel_x += BACK_X_OFFSET_EAST
|
||||
back_overlay.pixel_y += BACK_Y_OFFSET_EAST
|
||||
if(SOUTH)
|
||||
back_overlay.pixel_x += BACK_X_OFFSET_SOUTH
|
||||
back_overlay.pixel_y += BACK_Y_OFFSET_SOUTH
|
||||
if(WEST)
|
||||
back_overlay.pixel_x += BACK_X_OFFSET_WEST
|
||||
back_overlay.pixel_y += BACK_Y_OFFSET_WEST
|
||||
overlays_standing[BACK_LAYER] = back_overlay
|
||||
apply_overlay(BACK_LAYER)
|
||||
|
||||
//NECK
|
||||
/mob/living/carbon/wendigo/update_inv_neck()
|
||||
..()
|
||||
if(wear_neck)
|
||||
wear_neck.screen_loc = ui_neck
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += wear_neck
|
||||
var/mutable_appearance/neck_overlay = overlays_standing[NECK_LAYER]
|
||||
if(neck_overlay)
|
||||
remove_overlay(NECK_LAYER)
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
neck_overlay.pixel_x += NECK_X_OFFSET_NORTH
|
||||
neck_overlay.pixel_y += NECK_Y_OFFSET_NORTH
|
||||
if(EAST)
|
||||
neck_overlay.pixel_x += NECK_X_OFFSET_EAST
|
||||
neck_overlay.pixel_y += NECK_Y_OFFSET_EAST
|
||||
if(SOUTH)
|
||||
neck_overlay.pixel_x += NECK_X_OFFSET_SOUTH
|
||||
neck_overlay.pixel_y += NECK_Y_OFFSET_SOUTH
|
||||
if(WEST)
|
||||
neck_overlay.pixel_x += NECK_X_OFFSET_WEST
|
||||
neck_overlay.pixel_y += NECK_Y_OFFSET_WEST
|
||||
overlays_standing[NECK_LAYER] = neck_overlay
|
||||
apply_overlay(NECK_LAYER)
|
||||
|
||||
//HANDS
|
||||
/mob/living/carbon/wendigo/update_inv_hands()
|
||||
remove_overlay(HANDS_LAYER)
|
||||
if (handcuffed)
|
||||
drop_all_held_items()
|
||||
return
|
||||
|
||||
var/list/hands = list()
|
||||
for(var/obj/item/I in held_items)
|
||||
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
|
||||
I.screen_loc = ui_hand_position(get_held_index_of_item(I))
|
||||
client.screen += I
|
||||
if(observers && observers.len)
|
||||
for(var/M in observers)
|
||||
var/mob/dead/observe = M
|
||||
if(observe.client && observe.client.eye == src)
|
||||
observe.client.screen += I
|
||||
else
|
||||
observers -= observe
|
||||
if(!observers.len)
|
||||
observers = null
|
||||
break
|
||||
|
||||
var/t_state = I.item_state
|
||||
if(!t_state)
|
||||
t_state = I.icon_state
|
||||
|
||||
var/icon_file = I.lefthand_file
|
||||
var/righthand = 0
|
||||
if(get_held_index_of_item(I) % 2 == 0)
|
||||
icon_file = I.righthand_file
|
||||
righthand = 1
|
||||
|
||||
var/mutable_appearance/thing = I.build_worn_icon(state = t_state, default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE)
|
||||
if(righthand)
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
thing.pixel_x += RHAND_X_OFFSET_NORTH
|
||||
thing.pixel_y += RHAND_Y_OFFSET_NORTH
|
||||
if(EAST)
|
||||
thing = null //ghetto
|
||||
if(SOUTH)
|
||||
thing.pixel_x += RHAND_X_OFFSET_SOUTH
|
||||
thing.pixel_y += RHAND_Y_OFFSET_SOUTH
|
||||
if(WEST)
|
||||
thing.pixel_x += RHAND_X_OFFSET_WEST
|
||||
thing.pixel_y += RHAND_Y_OFFSET_WEST
|
||||
else
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
thing.pixel_x += LHAND_X_OFFSET_NORTH
|
||||
thing.pixel_y += LHAND_Y_OFFSET_NORTH
|
||||
if(EAST)
|
||||
thing.pixel_x += LHAND_X_OFFSET_EAST
|
||||
thing.pixel_y += LHAND_Y_OFFSET_EAST
|
||||
if(SOUTH)
|
||||
thing.pixel_x += LHAND_X_OFFSET_SOUTH
|
||||
thing.pixel_y += LHAND_Y_OFFSET_SOUTH
|
||||
if(WEST)
|
||||
thing = null //ghetto
|
||||
|
||||
hands += thing
|
||||
|
||||
overlays_standing[HANDS_LAYER] = hands
|
||||
apply_overlay(HANDS_LAYER)
|
||||
|
||||
//HEAD
|
||||
/mob/living/carbon/wendigo/update_inv_head()
|
||||
remove_overlay(HEAD_LAYER)
|
||||
|
||||
if(head)
|
||||
head.screen_loc = ui_head
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(hud_used.inventory_shown)
|
||||
client.screen += head
|
||||
var/mutable_appearance/head_icon = head.build_worn_icon(state = head.icon_state, default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/head.dmi')
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
head_icon.pixel_x += HEAD_X_OFFSET_NORTH
|
||||
head_icon.pixel_y += HEAD_Y_OFFSET_NORTH
|
||||
if(EAST)
|
||||
head_icon.pixel_x += HEAD_X_OFFSET_EAST
|
||||
head_icon.pixel_y += HEAD_Y_OFFSET_EAST
|
||||
if(SOUTH)
|
||||
head_icon.pixel_x += HEAD_X_OFFSET_SOUTH
|
||||
head_icon.pixel_y += HEAD_Y_OFFSET_SOUTH
|
||||
if(WEST)
|
||||
head_icon.pixel_x += HEAD_X_OFFSET_WEST
|
||||
head_icon.pixel_y += HEAD_Y_OFFSET_WEST
|
||||
overlays_standing[SLOT_HEAD] = head_icon
|
||||
update_hud_head(head)
|
||||
|
||||
apply_overlay(HEAD_LAYER)
|
||||
|
||||
#undef LHAND_X_OFFSET_NORTH
|
||||
#undef LHAND_Y_OFFSET_NORTH
|
||||
#undef LHAND_X_OFFSET_EAST
|
||||
#undef LHAND_Y_OFFSET_EAST
|
||||
#undef LHAND_X_OFFSET_SOUTH
|
||||
#undef LHAND_Y_OFFSET_SOUTH
|
||||
#undef LHAND_X_OFFSET_WEST
|
||||
#undef LHAND_Y_OFFSET_WEST
|
||||
#undef RHAND_X_OFFSET_NORTH
|
||||
#undef RHAND_Y_OFFSET_NORTH
|
||||
#undef RHAND_X_OFFSET_EAST
|
||||
#undef RHAND_Y_OFFSET_EAST
|
||||
#undef RHAND_X_OFFSET_SOUTH
|
||||
#undef RHAND_Y_OFFSET_SOUTH
|
||||
#undef RHAND_X_OFFSET_WEST
|
||||
#undef RHAND_Y_OFFSET_WEST
|
||||
#undef EARS_X_OFFSET_NORTH
|
||||
#undef EARS_Y_OFFSET_NORTH
|
||||
#undef EARS_X_OFFSET_EAST
|
||||
#undef EARS_Y_OFFSET_EAST
|
||||
#undef EARS_X_OFFSET_SOUTH
|
||||
#undef EARS_Y_OFFSET_SOUTH
|
||||
#undef EARS_X_OFFSET_WEST
|
||||
#undef EARS_Y_OFFSET_WEST
|
||||
#undef GLASSES_X_OFFSET_NORTH
|
||||
#undef GLASSES_Y_OFFSET_NORTH
|
||||
#undef GLASSES_X_OFFSET_EAST
|
||||
#undef GLASSES_Y_OFFSET_EAST
|
||||
#undef GLASSES_X_OFFSET_SOUTH
|
||||
#undef GLASSES_Y_OFFSET_SOUTH
|
||||
#undef GLASSES_X_OFFSET_WEST
|
||||
#undef GLASSES_Y_OFFSET_WEST
|
||||
#undef BELT_X_OFFSET_NORTH
|
||||
#undef BELT_Y_OFFSET_NORTH
|
||||
#undef BELT_X_OFFSET_EAST
|
||||
#undef BELT_Y_OFFSET_EAST
|
||||
#undef BELT_X_OFFSET_SOUTH
|
||||
#undef BELT_Y_OFFSET_SOUTH
|
||||
#undef BELT_X_OFFSET_WEST
|
||||
#undef BELT_Y_OFFSET_WEST
|
||||
#undef BACK_X_OFFSET_NORTH
|
||||
#undef BACK_Y_OFFSET_NORTH
|
||||
#undef BACK_X_OFFSET_EAST
|
||||
#undef BACK_Y_OFFSET_EAST
|
||||
#undef BACK_X_OFFSET_SOUTH
|
||||
#undef BACK_Y_OFFSET_SOUTH
|
||||
#undef BACK_X_OFFSET_WEST
|
||||
#undef BACK_Y_OFFSET_WEST
|
||||
#undef NECK_X_OFFSET_NORTH
|
||||
#undef NECK_Y_OFFSET_NORTH
|
||||
#undef NECK_X_OFFSET_EAST
|
||||
#undef NECK_Y_OFFSET_EAST
|
||||
#undef NECK_X_OFFSET_SOUTH
|
||||
#undef NECK_Y_OFFSET_SOUTH
|
||||
#undef NECK_X_OFFSET_WEST
|
||||
#undef NECK_Y_OFFSET_WEST
|
||||
704
hyperstation/code/modules/arousal/arousalhud.dm
Normal file
@@ -0,0 +1,704 @@
|
||||
//Hyperstation Arousal hud
|
||||
//This needs alot of attention, im a bad coder. a shitty attempt at making a more user friendly/modern hud
|
||||
//if you wanna use this on your own server go ahead, but alittle credit would always be nice! -quotefox
|
||||
//This still uses alot of cits arousal system!
|
||||
|
||||
/obj/screen/arousal/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = {"<B>Genitals</B><BR><HR>"}
|
||||
|
||||
var/mob/living/carbon/U = user
|
||||
for(var/obj/item/organ/genital/G in U.internal_organs)
|
||||
if(!G.nochange)
|
||||
if(!G.dontlist)
|
||||
// GS13: Fix spelling
|
||||
dat += "<a href='byond://?src=[REF(src)];hide[G.name]=1'>[G.mode == "hidden" ? "[G.name] <font color='red'>(Hidden)</font>" : (G.mode == "clothes" ? "[G.name] <font color='yellow'>(Hidden by Clothes)</font>" : (G.mode == "visible" ? "[G.name] <font color='green'>(Visible)</font>" : "[G.name] <font color='green'>(Visible)</font>"))]</a><BR>"
|
||||
|
||||
dat += {"<BR><B>Contexual Options</B><BR><HR>"}
|
||||
var/obj/item/organ/genital/penis/P = user.getorganslot("penis")
|
||||
//Options
|
||||
dat += "<a href='byond://?src=[REF(src)];masturbate=1'>Masturbate</A>"
|
||||
dat += "(Stimulate a sexual organ with your hands.)<BR>"
|
||||
|
||||
dat += "<a href='byond://?src=[REF(src)];climax=1'>Climax</A>"
|
||||
dat += "(Orgasm from a sexual organ.)<BR>"
|
||||
|
||||
dat += "<a href='byond://?src=[REF(src)];container=1'>Fill container</A>"
|
||||
dat += "(Use a container in your hand to collect your seminal fluid.)<BR>"
|
||||
|
||||
var/mob/living/carbon/human/C = usr
|
||||
if(C && C.w_uniform || C.wear_suit) //if they are wearing cloths
|
||||
dat += "<a href='byond://?src=[REF(src)];clothesplosion=1'>Explode out of clothes</A>"
|
||||
dat += "(Flex your body to cause your clothes to burst apart.)<BR>"
|
||||
|
||||
if(user.pulling)
|
||||
dat += "<a href='byond://?src=[REF(src)];kiss=1'>Kiss [user.pulling]</A>"
|
||||
dat += "(Kiss a partner, or object.)<BR>"
|
||||
dat += "<a href='byond://?src=[REF(src)];feed=1'>Feed [user.pulling]</A>"
|
||||
dat += "(Feed a partner.)<BR>"
|
||||
dat += "<a href='byond://?src=[REF(src)];feedfrom=1'>Feed from [user.pulling]</A>"
|
||||
dat += "(Feed a partner.)<BR>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Kiss</span></A>"
|
||||
dat += "(Requires a partner)<BR>"
|
||||
dat += "<span class='linkOff'>Feed others</span></A>"
|
||||
dat += "(Requires a partner)<BR>"
|
||||
dat += "<span class='linkOff'>Feed from others</span></A>"
|
||||
dat += "(Requires a partner)<BR>"
|
||||
dat += "<a href='byond://?src=[REF(src)];feedyourself=1'>Feed yourself</A>"
|
||||
dat += "(Feed yourself with your own genitals)<BR>"
|
||||
|
||||
var/obj/item/organ/genital/belly/Belly = user.getorganslot("belly")
|
||||
if(Belly)
|
||||
if(Belly.inflatable)
|
||||
// GS13: Fix description
|
||||
dat += "<a href='byond://?src=[REF(src)];shrink_belly=1'>Decrease belly size</A>"
|
||||
dat += "(Shrink your belly down a size)<BR>"
|
||||
dat += "<a href='byond://?src=[REF(src)];inflate_belly=1'>Increase belly size</A>"
|
||||
dat += "(Bloat your belly up a size)<BR>"
|
||||
|
||||
if(user.pulling)
|
||||
dat += "<a href='byond://?src=[REF(src)];climaxover=1'>Climax over [user.pulling]</A>" //you can cum on objects if you really want...
|
||||
dat += "(Orgasm over a person or object.)<BR>"
|
||||
if(isliving(user.pulling))
|
||||
if(iscarbon(user.pulling))
|
||||
dat += "<a href='byond://?src=[REF(src)];climaxwith=1'>Climax with [user.pulling]</A>"
|
||||
dat += {"(Orgasm with another person.)<BR>"}
|
||||
|
||||
var/mob/living/carbon/human/H = user.pulling
|
||||
if(H.breedable && P && H)
|
||||
dat += "<a href='byond://?src=[REF(src)];impreg=1'>Impregnate [U.pulling] ([clamp(U.impregchance,0,100)]%)</A>"
|
||||
dat += "(Climax inside another person, and attempt to knock them up.)<BR>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Climax over</span></A>"
|
||||
dat += "(Requires a partner)<BR>"
|
||||
dat += "<span class='linkOff'>Climax with</span></A>"
|
||||
dat += "(Requires a partner)<BR>"
|
||||
|
||||
//old code needs to be cleaned
|
||||
if(P)
|
||||
if(P.condom == 1)
|
||||
dat += "<a href='byond://?src=[REF(src)];removecondom=1'>Remove condom (penis)</A><BR>"
|
||||
if(P.sounding == 1)
|
||||
dat += "<a href='byond://?src=[REF(src)];removesound=1'>Remove sounding rod (penis)</A><BR>"
|
||||
for(var/obj/item/organ/genital/G in U.internal_organs)
|
||||
if(G.equipment) //they have equipment
|
||||
dat += "<a href='byond://?src=[REF(src)];removeequipment[G.name]=1;'>Remove [G.equipment.name] ([G.name])</A><BR>"
|
||||
|
||||
dat += {"<HR>"}//Newline for the objects
|
||||
//bottom options
|
||||
dat += "<a href='byond://?src=[REF(src)];refresh=1'>Refresh</A>"
|
||||
dat += "<a href='byond://?src=[REF(src)];omenu=1'>Old Menu</A>"
|
||||
dat += "<a href='byond://?src=[REF(src)];underwear=1'>Toggle Undergarments </A>"
|
||||
dat += "<BR>"
|
||||
|
||||
var/datum/browser/popup = new(user, "arousal", "Arousal Panel")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state), 500,600)
|
||||
|
||||
popup.open()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/screen/arousal/Topic(href, href_list)
|
||||
. = ..() //Sanity checks.
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if (!H)
|
||||
return
|
||||
if(usr.stat==1) //No sleep-masturbation, you're unconscious.
|
||||
to_chat(usr, "<span class='warning'>You must be conscious to do that!</span>")
|
||||
usr << browse(null, "window=arousal") //closes the window
|
||||
return
|
||||
if(usr.stat==3)
|
||||
to_chat(usr, "<span class='warning'>You must be alive to do that!</span>")
|
||||
usr << browse(null, "window=arousal") //closes the window
|
||||
return
|
||||
|
||||
if(href_list["hidepenis"])
|
||||
var/obj/item/organ/genital/penis/P = usr.getorganslot("penis")
|
||||
var/picked_visibility = input(usr, "Choose visibility", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
P.toggle_visibility(picked_visibility)
|
||||
|
||||
if(href_list["hidevagina"])
|
||||
var/obj/item/organ/genital/vagina/V = usr.getorganslot("vagina")
|
||||
var/picked_visibility = input(usr, "Choose visibility", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
V.toggle_visibility(picked_visibility)
|
||||
|
||||
if(href_list["hidebreasts"])
|
||||
var/obj/item/organ/genital/breasts/B = usr.getorganslot("breasts")
|
||||
var/picked_visibility = input(usr, "Choose visibility", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
B.toggle_visibility(picked_visibility)
|
||||
|
||||
if(href_list["hidebelly"])
|
||||
var/obj/item/organ/genital/belly/E = usr.getorganslot("belly")
|
||||
var/picked_visibility = input(usr, "Choose visibility", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
E.toggle_visibility(picked_visibility)
|
||||
|
||||
if(href_list["hideanus"])
|
||||
var/obj/item/organ/genital/anus/A = usr.getorganslot("anus")
|
||||
var/picked_visibility = input(usr, "Choose visibility", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
A.toggle_visibility(picked_visibility)
|
||||
|
||||
if(href_list["hidetesticles"])
|
||||
var/obj/item/organ/genital/testicles/T = usr.getorganslot("testicles")
|
||||
var/picked_visibility = input(usr, "Choose visibility", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
T.toggle_visibility(picked_visibility)
|
||||
|
||||
if(href_list["masturbate"])
|
||||
if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
|
||||
H.solomasturbate()
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You aren't aroused enough for that! </span>")
|
||||
return
|
||||
|
||||
if(href_list["container"])
|
||||
if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
|
||||
H.cumcontainer()
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You aren't aroused enough for that! </span>")
|
||||
return
|
||||
|
||||
if(href_list["clothesplosion"])
|
||||
if (H.arousalloss >= (H.max_arousal / 100) * 33) //Requires 33% arousal.
|
||||
H.clothesplosion()
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You aren't aroused enough for that! </span>")
|
||||
return
|
||||
|
||||
if(href_list["climax"])
|
||||
if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
|
||||
H.climaxalone(FALSE)
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You aren't aroused enough for that! </span>")
|
||||
return
|
||||
|
||||
if(href_list["climaxover"])
|
||||
if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
|
||||
H.climaxover(usr.pulling)
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You aren't aroused enough for that! </span>")
|
||||
return
|
||||
|
||||
if(href_list["climaxwith"])
|
||||
if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
|
||||
H.climaxwith(usr.pulling)
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You aren't aroused enough for that! </span>")
|
||||
return
|
||||
|
||||
if(href_list["impreg"])
|
||||
if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal.
|
||||
H.impregwith(usr.pulling)
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You aren't aroused enough for that! </span>")
|
||||
return
|
||||
|
||||
if(href_list["kiss"])
|
||||
if(usr.pulling)
|
||||
kiss()
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You cannot do this alone!</span>")
|
||||
return
|
||||
|
||||
if(href_list["feed"])
|
||||
if(usr.pulling)
|
||||
feed()
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You cannot do this alone!</span>")
|
||||
return
|
||||
|
||||
if(href_list["feedfrom"])
|
||||
if(usr.pulling)
|
||||
feedfrom()
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You cannot do this alone!</span>")
|
||||
return
|
||||
|
||||
if(href_list["feedyourself"])
|
||||
feedyourself()
|
||||
return
|
||||
|
||||
if(href_list["shrink_belly"])
|
||||
var/obj/item/organ/genital/belly/E = usr.getorganslot("belly")
|
||||
if(E.size > 0)
|
||||
to_chat(usr, "<span class='userlove'>You feel your belly diminish.</span>")
|
||||
E.size -= 1
|
||||
H.update_genitals()
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Your belly is already at the minimum size! </span>")
|
||||
|
||||
if(href_list["inflate_belly"])
|
||||
var/obj/item/organ/genital/belly/E = usr.getorganslot("belly")
|
||||
if(E.size < 11)
|
||||
to_chat(usr, "<span class='userlove'>You feel your belly bloat out..</span>")
|
||||
E.size += 1
|
||||
H.update_genitals()
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Your belly is already at the maximum size! </span>")
|
||||
|
||||
|
||||
if(href_list["removecondom"])
|
||||
H.menuremovecondom()
|
||||
|
||||
if(href_list["removesound"])
|
||||
H.menuremovesounding()
|
||||
|
||||
if(href_list["removeequipmentpenis"])
|
||||
var/obj/item/organ/genital/penis/O = usr.getorganslot("penis")
|
||||
var/obj/item/I = O.equipment
|
||||
usr.put_in_hands(I)
|
||||
O.equipment = null
|
||||
|
||||
if(href_list["removeequipmentbreasts"])
|
||||
var/obj/item/organ/genital/breasts/O = usr.getorganslot("breasts")
|
||||
var/obj/item/I = O.equipment
|
||||
usr.put_in_hands(I)
|
||||
O.equipment = null
|
||||
|
||||
|
||||
if(href_list["removeequipmentvagina"])
|
||||
var/obj/item/organ/genital/vagina/O = usr.getorganslot("vagina")
|
||||
var/obj/item/I = O.equipment
|
||||
usr.put_in_hands(I)
|
||||
if(istype(I, /obj/item/portalpanties))
|
||||
var/obj/item/portalpanties/P = I
|
||||
P.remove()
|
||||
O.equipment = null
|
||||
|
||||
if(href_list["removeequipmentbelly"])
|
||||
var/obj/item/organ/genital/belly/O = usr.getorganslot("belly")
|
||||
var/obj/item/I = O.equipment
|
||||
usr.put_in_hands(I)
|
||||
O.equipment = null
|
||||
|
||||
if(href_list["removeequipmentanus"])
|
||||
var/obj/item/organ/genital/anus/O = usr.getorganslot("anus")
|
||||
var/obj/item/I = O.equipment
|
||||
usr.put_in_hands(I)
|
||||
O.equipment = null
|
||||
|
||||
|
||||
if(href_list["omenu"])
|
||||
usr << browse(null, "window=arousal") //closes the window
|
||||
H.mob_climax()
|
||||
return
|
||||
|
||||
if(href_list["underwear"])
|
||||
H.underwear_toggle()
|
||||
return
|
||||
|
||||
src.ui_interact(usr)
|
||||
|
||||
|
||||
obj/screen/arousal/proc/kiss()
|
||||
if(usr.restrained(TRUE))
|
||||
to_chat(usr, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if (H)
|
||||
H.kisstarget(H.pulling)
|
||||
|
||||
obj/screen/arousal/proc/feed()
|
||||
if(usr.restrained(TRUE))
|
||||
to_chat(usr, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if (H)
|
||||
H.genitalfeed(H.pulling)
|
||||
|
||||
obj/screen/arousal/proc/feedfrom()
|
||||
if(usr.restrained(TRUE))
|
||||
to_chat(usr, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if (H)
|
||||
H.genitalfeedfrom(H.pulling)
|
||||
|
||||
obj/screen/arousal/proc/feedyourself()
|
||||
if(usr.restrained(TRUE))
|
||||
to_chat(usr, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if (H)
|
||||
H.genitalfeedyourself()
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/menuremovecondom()
|
||||
|
||||
if(restrained(TRUE))
|
||||
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/free_hands = get_num_arms()
|
||||
if(!free_hands)
|
||||
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return
|
||||
var/obj/item/organ/genital/penis/P = getorganslot("penis")
|
||||
if(!P.condom)
|
||||
to_chat(src, "<span class='warning'>You don't have a condom on!</span>")
|
||||
return
|
||||
if(P.condom)
|
||||
to_chat(src, "<span class='warning'>You tug the condom off the end of your penis!</span>")
|
||||
removecondom()
|
||||
src.ui_interact(usr) //reopen dialog
|
||||
return
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/menuremovesounding()
|
||||
|
||||
if(restrained(TRUE))
|
||||
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/free_hands = get_num_arms()
|
||||
if(!free_hands)
|
||||
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return
|
||||
var/obj/item/organ/genital/penis/P = getorganslot("penis")
|
||||
if(!P.sounding)
|
||||
to_chat(src, "<span class='warning'>You don't have a rod inside!</span>")
|
||||
return
|
||||
if(P.sounding)
|
||||
to_chat(src, "<span class='warning'>You pull the rod off from the tip of your penis!</span>")
|
||||
removesounding()
|
||||
src.ui_interact(usr) //reopen dialog
|
||||
return
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/solomasturbate()
|
||||
if(restrained(TRUE))
|
||||
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/free_hands = get_num_arms()
|
||||
if(!free_hands)
|
||||
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return
|
||||
for(var/helditem in held_items)
|
||||
if(isobj(helditem))
|
||||
free_hands--
|
||||
if(free_hands <= 0)
|
||||
to_chat(src, "<span class='warning'>You're holding too many things.</span>")
|
||||
return
|
||||
//We got hands, let's pick an organ
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = pick_masturbate_genitals()
|
||||
if(picked_organ)
|
||||
src << browse(null, "window=arousal") //closes the window
|
||||
mob_masturbate(picked_organ)
|
||||
return
|
||||
else //They either lack organs that can masturbate, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot climax without choosing genitals.</span>")
|
||||
return
|
||||
|
||||
|
||||
//Kissing target proc
|
||||
/mob/living/carbon/human/proc/kisstarget(mob/living/L)
|
||||
|
||||
src << browse(null, "window=arousal") //closes the arousal window, if its open, mainly to stop spam
|
||||
if(isliving(L)) //is your target living? Living people can resist your advances if they want to via moving.
|
||||
if(iscarbon(L))
|
||||
src.visible_message("<span class='notice'>[src] is about to kiss [L]!</span>", \
|
||||
"<span class='notice'>You're attempting to kiss [L]!</span>", \
|
||||
"<span class='notice'>You're attempting to kiss with something!</span>")
|
||||
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "kissed", /datum/mood_event/kiss) //how cute, affection is nice.
|
||||
//Well done you kissed it/them!
|
||||
src.visible_message("<span class='notice'>[src] kisses [L]!</span>", \
|
||||
"<span class='notice'>You kiss [L]!</span>", \
|
||||
"<span class='notice'>You kiss something!</span>")
|
||||
|
||||
/mob/living/carbon/human/proc/climaxalone()
|
||||
//we dont need hands to climax alone, its hands free!
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = pick_climax_genitals()
|
||||
if(picked_organ)
|
||||
src << browse(null, "window=arousal") //closes the window
|
||||
mob_climax_outside(picked_organ)
|
||||
return
|
||||
else //They either lack organs that can masturbate, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot climax without choosing genitals.</span>")
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/climaxwith(mob/living/T)
|
||||
|
||||
var/mob/living/carbon/human/L = pick_partner()
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = pick_climax_genitals()
|
||||
if(picked_organ)
|
||||
var/mob/living/partner = L
|
||||
if(partner)
|
||||
src << browse(null, "window=arousal") //alls fine, we can close the window now.
|
||||
var/obj/item/organ/genital/penis/P = picked_organ
|
||||
var/spillage = "No" //default to no, just incase player has items on to prevent climax
|
||||
if(!P.condom == 1&&!P.sounding == 1) //you cant climax with a condom on or sounding in.
|
||||
spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No")
|
||||
if(spillage == "Yes")
|
||||
mob_climax_partner(picked_organ, partner, TRUE, FALSE, FALSE)
|
||||
else
|
||||
mob_climax_partner(picked_organ, partner, FALSE, FALSE, FALSE)
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You cannot do this alone.</span>")
|
||||
return
|
||||
else //They either lack organs that can masturbate, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot climax without choosing genitals.</span>")
|
||||
return
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/climaxover(mob/living/T)
|
||||
|
||||
var/mob/living/carbon/human/L = T
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = pick_climax_genitals()
|
||||
if(picked_organ)
|
||||
src << browse(null, "window=arousal") //alls fine, we can close the window now.
|
||||
var/mob/living/partner = L
|
||||
if(partner)
|
||||
var/obj/item/organ/genital/penis/P = picked_organ
|
||||
if(P.condom == 1)
|
||||
to_chat(src, "<span class='warning'>You cannot do this action with a condom on.</span>")
|
||||
return
|
||||
if(P.sounding == 1)
|
||||
to_chat(src, "<span class='warning'>You cannot do this action with a sounding in.</span>")
|
||||
return
|
||||
mob_climax_partner(picked_organ, partner, FALSE, FALSE, TRUE)
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You cannot do this alone.</span>")
|
||||
return
|
||||
else //They either lack organs that can masturbate, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot climax without choosing genitals.</span>")
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/clothesplosion()
|
||||
if(usr.restrained(TRUE))
|
||||
to_chat(usr, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = src
|
||||
var/items = H.get_contents()
|
||||
for(var/obj/item/W in items)
|
||||
if(W == H.w_uniform || W == H.wear_suit)
|
||||
H.dropItemToGround(W, TRUE)
|
||||
playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
H.visible_message("<span class='boldnotice'>[H] explodes out of their clothes!'</span>")
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/impregwith(mob/living/T)
|
||||
|
||||
var/mob/living/carbon/human/L = pick_partner()
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = src.getorganslot("penis") //Impregnation must be done with a penis.
|
||||
if(picked_organ)
|
||||
var/mob/living/partner = L
|
||||
if(partner)
|
||||
if(!partner.breedable)//check if impregable.
|
||||
to_chat(src, "<span class='warning'>Your partner cannot be impregnated.</span>")//some fuckary happening, you shouldnt even get to this point tbh.
|
||||
return
|
||||
var/obj/item/organ/genital/penis/P = picked_organ
|
||||
//you cant impreg with a condom on or sounding in.
|
||||
if(P.condom == 1)
|
||||
to_chat(src, "<span class='warning'>You cannot do this action with a condom on.</span>")
|
||||
return
|
||||
if(P.sounding == 1)
|
||||
to_chat(src, "<span class='warning'>You cannot do this action with a sounding in.</span>")
|
||||
return
|
||||
src << browse(null, "window=arousal") //alls fine, we can close the window now.
|
||||
//Keeping this for messy fun
|
||||
var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No")
|
||||
if(spillage == "Yes")
|
||||
mob_climax_partner(picked_organ, partner, TRUE, TRUE, FALSE)
|
||||
else
|
||||
mob_climax_partner(picked_organ, partner, FALSE, TRUE, FALSE)
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You cannot do this alone.</span>")
|
||||
return
|
||||
else //no penis :(
|
||||
to_chat(src, "<span class='warning'>You cannot impregnate without a penis.</span>")
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/cumcontainer(mob/living/T)
|
||||
//We'll need hands and no restraints.
|
||||
if(restrained(TRUE)) //TRUE ignores grabs
|
||||
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/free_hands = get_num_arms()
|
||||
if(!free_hands)
|
||||
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return
|
||||
for(var/helditem in held_items)//how many hands are free
|
||||
if(isobj(helditem))
|
||||
free_hands--
|
||||
if(free_hands <= 0)
|
||||
to_chat(src, "<span class='warning'>You're holding too many things.</span>")
|
||||
return
|
||||
//We got hands, let's pick an organ
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
src << browse(null, "window=arousal")
|
||||
picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids.
|
||||
if(picked_organ)
|
||||
//Good, got an organ, time to pick a container
|
||||
var/obj/item/reagent_containers/fluid_container = pick_climax_container()
|
||||
if(fluid_container)
|
||||
mob_fill_container(picked_organ, fluid_container)
|
||||
return
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You cannot do this without anything to fill.</span>")
|
||||
return
|
||||
else //They either lack organs that can climax, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot fill anything without choosing genitals.</span>")
|
||||
return
|
||||
|
||||
/atom/proc/add_cum_overlay() //This can go in a better spot, for now its here.
|
||||
cum_splatter_icon = icon(initial(icon), initial(icon_state), , 1)
|
||||
cum_splatter_icon.Blend("#fff", ICON_ADD)
|
||||
cum_splatter_icon.Blend(icon('hyperstation/icons/effects/cumoverlay.dmi', "cum_obj"), ICON_MULTIPLY)
|
||||
add_overlay(cum_splatter_icon)
|
||||
|
||||
/atom/proc/wash_cum()
|
||||
cut_overlay(mutable_appearance('hyperstation/icons/effects/cumoverlay.dmi', "cum_normal"))
|
||||
cut_overlay(mutable_appearance('hyperstation/icons/effects/cumoverlay.dmi', "cum_large"))
|
||||
if(cum_splatter_icon)
|
||||
cut_overlay(cum_splatter_icon)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/human/proc/genitalfeed(mob/living/L, mb_time = 30)
|
||||
if(isliving(L)) //is your target living? Living people can resist your advances if they want to via moving.
|
||||
if(iscarbon(L))
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
var/total_fluids = 0
|
||||
var/datum/reagents/fluid_source = null
|
||||
src << browse(null, "window=arousal")
|
||||
picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids.
|
||||
if(picked_organ)
|
||||
//Good, got an organ, time to pick a container
|
||||
if(picked_organ.name == "penis")//if the select organ is a penis
|
||||
var/obj/item/organ/genital/penis/P = src.getorganslot("penis")
|
||||
if(P.condom) //if the penis is condomed
|
||||
to_chat(src, "<span class='warning'>You cannot feed someone when there is a condom over your [picked_organ.name].</span>")
|
||||
return
|
||||
if(P.sounding) //if the penis is sounded
|
||||
to_chat(src, "<span class='warning'>You cannot feed someone when there is a rod inside your [picked_organ.name].</span>")
|
||||
return
|
||||
if(picked_organ.producing) //Can it produce its own fluids, such as breasts?
|
||||
fluid_source = picked_organ.reagents
|
||||
else
|
||||
if(!picked_organ.linked_organ)
|
||||
to_chat(src, "<span class='warning'>Your [picked_organ.name] is unable to produce it's own fluids, it's missing the organs for it.</span>")
|
||||
return
|
||||
fluid_source = picked_organ.linked_organ.reagents
|
||||
total_fluids = fluid_source.total_volume
|
||||
|
||||
src.visible_message("<span class='love'>[src] starts to feed [L.name] with their [picked_organ.name].</span>", \
|
||||
"<span class='userlove'>You feed [L.name] with your [picked_organ.name].</span>")
|
||||
if(do_after(src, mb_time, target = src) && in_range(src, L))
|
||||
fluid_source.trans_to(L, total_fluids)
|
||||
src.visible_message("<span class='love'>[src] uses [p_their()] [picked_organ.name] to feed [L.name]!</span>", \
|
||||
"<span class='userlove'>You used your [picked_organ.name] to feed [L.name] a total of [total_fluids]u's.</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
||||
if(picked_organ.can_climax)
|
||||
setArousalLoss(min_arousal)
|
||||
|
||||
else //They either lack organs that can climax, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot fill anything without choosing exposed genitals.</span>")
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/genitalfeedfrom(mob/living/target, mb_time = 30)
|
||||
var/mob/living/carbon/human/L = target
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
var/total_fluids = 0
|
||||
var/datum/reagents/fluid_source = null
|
||||
src << browse(null, "window=arousal")
|
||||
|
||||
var/list/genitals_list = list()
|
||||
var/list/worn_stuff = L.get_equipped_items()
|
||||
|
||||
for(var/obj/item/organ/genital/G in L.internal_organs)
|
||||
if(G.can_climax) //filter out what you can't masturbate with
|
||||
if(G.is_exposed(worn_stuff)) //Nude or through_clothing
|
||||
if(!G.dontlist)
|
||||
genitals_list += G
|
||||
if(genitals_list.len)
|
||||
picked_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list
|
||||
else
|
||||
return
|
||||
|
||||
if(picked_organ)
|
||||
//Good, got an organ, time to pick a container
|
||||
if(picked_organ.name == "penis")//if the select organ is a penis
|
||||
var/obj/item/organ/genital/penis/P = L.getorganslot("penis")
|
||||
if(P.condom) //if the penis is condomed
|
||||
to_chat(src, "<span class='warning'>You cannot feed from [picked_organ.name] when there is a condom over it.</span>")
|
||||
return
|
||||
if(P.sounding) //if the penis is sounded
|
||||
to_chat(src, "<span class='warning'>You cannot feed from [picked_organ.name] when there is a rod inside it.</span>")
|
||||
return
|
||||
if(picked_organ.producing) //Can it produce its own fluids, such as breasts?
|
||||
fluid_source = picked_organ.reagents
|
||||
else
|
||||
if(!picked_organ.linked_organ)
|
||||
to_chat(src, "<span class='warning'>The [picked_organ.name] is unable to produce it's own fluids, it's missing the organs for it.</span>")
|
||||
return
|
||||
fluid_source = picked_organ.linked_organ.reagents
|
||||
total_fluids = fluid_source.total_volume
|
||||
|
||||
src.visible_message("<span class='love'>[src] starts to feed from [L.name]'s [picked_organ.name].</span>", \
|
||||
"<span class='userlove'>You feed from [L.name]'s '[picked_organ.name].</span>")
|
||||
if(do_after(src, mb_time, target = src) && in_range(src, L))
|
||||
fluid_source.trans_to(src, total_fluids)
|
||||
src.visible_message("<span class='love'>[src] feeds from [L.name]'s [picked_organ.name]!</span>", \
|
||||
"<span class='userlove'>You used [L.name]'s [picked_organ.name] to feed with a total of [total_fluids]u's.</span>")
|
||||
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
||||
if(picked_organ.can_climax)
|
||||
L.setArousalLoss(min_arousal)
|
||||
|
||||
else //They either lack organs that can climax, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot fill anything without choosing exposed genitals.</span>")
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/genitalfeedyourself(mb_time = 30)
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
var/total_fluids = 0
|
||||
var/datum/reagents/fluid_source = null
|
||||
src << browse(null, "window=arousal")
|
||||
picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids.
|
||||
if(picked_organ)
|
||||
//Good, got an organ, time to pick a container
|
||||
if(picked_organ.name == "penis")//if the select organ is a penis
|
||||
var/obj/item/organ/genital/penis/P = src.getorganslot("penis")
|
||||
if(P.condom) //if the penis is condomed
|
||||
to_chat(src, "<span class='warning'>You cannot feed yourself when there is a condom over your [picked_organ.name].</span>")
|
||||
return
|
||||
if(P.sounding) //if the penis is sounded
|
||||
to_chat(src, "<span class='warning'>You cannot feed yourself when there is a rod inside your [picked_organ.name].</span>")
|
||||
return
|
||||
if(picked_organ.producing) //Can it produce its own fluids, such as breasts?
|
||||
fluid_source = picked_organ.reagents
|
||||
else
|
||||
if(!picked_organ.linked_organ)
|
||||
to_chat(src, "<span class='warning'>Your [picked_organ.name] is unable to produce it's own fluids, it's missing the organs for it.</span>")
|
||||
return
|
||||
fluid_source = picked_organ.linked_organ.reagents
|
||||
total_fluids = fluid_source.total_volume
|
||||
|
||||
src.visible_message("<span class='love'>[src] starts to feed themselves with their [picked_organ.name].</span>", \
|
||||
"<span class='userlove'>You feed yourself with your [picked_organ.name].</span>")
|
||||
if(do_after(src, mb_time))
|
||||
fluid_source.trans_to(src, total_fluids)
|
||||
src.visible_message("<span class='love'>[src] uses [p_their()] [picked_organ.name] to feed themselves!</span>", \
|
||||
"<span class='userlove'>You used your [picked_organ.name] to feed yourself a total of [total_fluids]u's.</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
||||
if(picked_organ.can_climax)
|
||||
setArousalLoss(min_arousal)
|
||||
|
||||
else //They either lack organs that can climax, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot fill anything without choosing exposed genitals.</span>")
|
||||
return
|
||||
15
hyperstation/code/modules/arousal/creampie.dm
Normal file
@@ -0,0 +1,15 @@
|
||||
/mob/living/carbon/human/handle_creampie()
|
||||
if(NOBLOOD in dna.species.species_traits)
|
||||
cumdrip_rate = 0
|
||||
return
|
||||
|
||||
if(cumdrip_rate < 0)
|
||||
cumdrip_rate = 0
|
||||
|
||||
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE)))
|
||||
cumdrip_rate = cumdrip_rate - 1
|
||||
cumdrip()
|
||||
|
||||
/mob/living/carbon/human/proc/cumdrip()
|
||||
if(isturf(loc))
|
||||
new/obj/effect/decal/cleanable/semendrip(get_turf(src))
|
||||
4
hyperstation/code/modules/cargo/exports/engineering.dm
Normal file
@@ -0,0 +1,4 @@
|
||||
/datum/export/plutonium_rod
|
||||
cost = 20000
|
||||
unit_name = "Plutonium Rod"
|
||||
export_types = list(/obj/item/twohanded/required/fuel_rod/plutonium)
|
||||
24
hyperstation/code/modules/cargo/exports/sweatshop.dm
Normal file
@@ -0,0 +1,24 @@
|
||||
/datum/export/sweatshop/stool
|
||||
cost = 850
|
||||
unit_name = "custom stool"
|
||||
export_types = list(/obj/item/processed/wood/stool)
|
||||
|
||||
/datum/export/sweatshop/cushion
|
||||
cost = 300
|
||||
unit_name = "cloth cushion"
|
||||
export_types = list(/obj/item/cushion)
|
||||
|
||||
/datum/export/sweatshop/cushionsilk
|
||||
cost = 500
|
||||
unit_name = "silk cushion"
|
||||
export_types = list(/obj/item/cushion)
|
||||
|
||||
/datum/export/sweatshop/stool/cushioncloth
|
||||
cost = 1800
|
||||
unit_name = "cushioned stool (cloth)"
|
||||
export_types = list(/obj/item/processed/wood/stoolcloth)
|
||||
|
||||
/datum/export/sweatshop/stool/cushionsilk
|
||||
cost = 2400
|
||||
unit_name = "cushioned stool (cloth)"
|
||||
export_types = list(/obj/item/processed/wood/stoolsilk)
|
||||
7
hyperstation/code/modules/cargo/packs/misc.dm
Normal file
@@ -0,0 +1,7 @@
|
||||
/datum/supply_pack/service/stripperpole
|
||||
name = "Stripper Pole Crate"
|
||||
desc = "No private bar is complete without a stripper pole, show off the goods! Comes with a ready-to-assemble stripper pole, and a complementary wrench to get things set up!"
|
||||
cost = 3550
|
||||
contains = list(/obj/item/polepack/,
|
||||
/obj/item/wrench/)
|
||||
crate_name = "stripper pole crate"
|
||||
6
hyperstation/code/modules/cargo/sweatshop/metal.dm
Normal file
@@ -0,0 +1,6 @@
|
||||
/obj/item/processed/metal
|
||||
name = "Heated Metal"
|
||||
desc = "A malleable metal, able to be cut into nails."
|
||||
icon = 'hyperstation/icons/obj/cargo/sweatshop/metal.dmi'
|
||||
icon_state = "metal"
|
||||
sharpness = TRUE
|
||||
256
hyperstation/code/modules/cargo/sweatshop/sweatshop.dm
Normal file
@@ -0,0 +1,256 @@
|
||||
//THE TOOLS
|
||||
/obj/item/carpentry
|
||||
name = "carpentry"
|
||||
desc = "You shouldn't be seeing this!"
|
||||
icon = 'hyperstation/icons/obj/cargo/sweatshop/sweatshop.dmi'
|
||||
usesound = list('sound/effects/picaxe1.ogg', 'sound/effects/picaxe2.ogg', 'sound/effects/picaxe3.ogg')
|
||||
|
||||
/obj/item/carpentry/handsaw
|
||||
name = "handsaw"
|
||||
desc = "A shoddy tool used to process wood into smaller segments."
|
||||
icon_state = "handsaw"
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
force = 8
|
||||
sharpness = TRUE
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
materials = list(MAT_METAL=50)
|
||||
attack_verb = list("slashed", "sawed")
|
||||
|
||||
/obj/item/carpentry/hammer
|
||||
name = "hammer"
|
||||
desc = "A tool used to manually bash nails into place."
|
||||
icon_state = "hammer"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
force = 7
|
||||
sharpness = FALSE
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
materials = list(MAT_METAL=100)
|
||||
attack_verb = list("bonked", "nailed")
|
||||
|
||||
/obj/item/carpentry/glue
|
||||
name = "glue"
|
||||
desc = "Used to haphazardly stick things together; secured by the toughest Monkey Glue(TM)."
|
||||
icon_state = "glue"
|
||||
force = 0
|
||||
sharpness = FALSE
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_PLASTIC=25)
|
||||
attack_verb = list("glued", "coughed")
|
||||
|
||||
/obj/item/carpentry/borer
|
||||
name = "manual borer"
|
||||
desc = "An incredibly awful tool used to manually drill holes into something... Surely there's a better option."
|
||||
icon_state = "borer"
|
||||
force = 3
|
||||
sharpness = TRUE
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
materials = list(MAT_METAL=25)
|
||||
attack_verb = list("bored", "drilled")
|
||||
|
||||
/obj/item/carpentry/sandpaper
|
||||
name = "sandpaper strip"
|
||||
desc = "A strip of sandpaper, commonly used for sanding down rough surfaces into a more smooth shape."
|
||||
icon_state = "sandpaper"
|
||||
force = 1
|
||||
sharpness = FALSE
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
materials = list(MAT_GLASS=1) //lmao
|
||||
attack_verb = list("sanded", "licked")
|
||||
|
||||
/obj/item/nails
|
||||
name = "metal nails"
|
||||
desc = "A bunch of nails, used for hammering into things."
|
||||
icon = 'hyperstation/icons/obj/cargo/sweatshop/sweatshop.dmi'
|
||||
icon_state = "nails"
|
||||
force = 0
|
||||
sharpness = TRUE
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
materials = list(MAT_METAL=10)
|
||||
attack_verb = list("nailed", "screwed")
|
||||
|
||||
/obj/item/cushion
|
||||
name = "basic cushion"
|
||||
desc = "Beats sitting on the floor."
|
||||
icon = 'hyperstation/icons/obj/cargo/sweatshop/cloth.dmi'
|
||||
icon_state = "clothcushion"
|
||||
force = 0
|
||||
sharpness = FALSE
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
attack_verb = list("thomped", "thwacked")
|
||||
|
||||
/obj/item/cushion/silk
|
||||
name = "silk cushion"
|
||||
desc = "How'd it turn red?!"
|
||||
icon_state = "silkcushion"
|
||||
|
||||
//BASIC RECIPES - To do, add sound. As well as refactor everything in a more smart way so we can add the possibility of multiple wood types in the future.
|
||||
//saw a plank into two platforms
|
||||
/obj/item/processed/wood/plank/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/handsaw))
|
||||
to_chat(user,"<span class='notice'> You begin to saw [src] in half...</span>")
|
||||
if(do_after(user, 40) && isturf(loc))
|
||||
new src.sawobj(loc)
|
||||
new src.sawobj(loc) //send help i dont know how to make two in the same line lmfao
|
||||
to_chat(user, "<span class='notice'> You saw [src] in half.</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to saw [src]!</span>")
|
||||
else
|
||||
..()
|
||||
//saw a platform into four blocks
|
||||
/obj/item/processed/wood/platform/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/handsaw))
|
||||
to_chat(user,"<span class='notice'> You begin cut [src] into smaller pieces...</span>")
|
||||
if(do_after(user, 20) && isturf(loc))
|
||||
new src.sawobj(loc)
|
||||
new src.sawobj(loc)
|
||||
new src.sawobj(loc)
|
||||
new src.sawobj(loc)
|
||||
to_chat(user, "<span class='notice'> You cut [src] into four pieces.</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to saw [src]!</span>")
|
||||
else
|
||||
..()
|
||||
//sand a block into a peg
|
||||
/obj/item/processed/wood/block/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/sandpaper))
|
||||
to_chat(user,"<span class='notice'> You carefully begin to sand down [src]...</span>")
|
||||
if(do_after(user, 50) && isturf(loc))
|
||||
new src.sandobj(loc)
|
||||
to_chat(user, "<span class='notice'> You smooth [src] into a peg.</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to sand [src]!</span>")
|
||||
else
|
||||
..()
|
||||
//cut heated metal into nails
|
||||
/obj/item/processed/metal/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_WIRECUTTER)
|
||||
to_chat(user,"<span class='notice'> You tediously begin to cut [src] into several nails...</span>")
|
||||
if(do_after(user, 80) && isturf(loc))
|
||||
new /obj/item/nails(loc)
|
||||
new /obj/item/nails(loc)
|
||||
to_chat(user, "<span class='notice'> You make some crude metal nails.</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to process [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
//Covered in glue
|
||||
//cover a wooden block in glue
|
||||
/obj/item/processed/wood/block/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/glue))
|
||||
to_chat(user,"<span class='notice'> You begin to glue down one end of [src]...</span>")
|
||||
if(do_after(user, 10) && isturf(loc))
|
||||
new src.glueobj(loc)
|
||||
to_chat(user, "<span class='notice'> You slap some glue onto [src].</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to glue [src]!</span>")
|
||||
else
|
||||
..()
|
||||
//cover a wooden peg in glue
|
||||
/obj/item/processed/wood/peg/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/glue))
|
||||
to_chat(user,"<span class='notice'> You begin to glue down one end of the [src]...</span>")
|
||||
if(do_after(user, 10) && isturf(loc))
|
||||
new src.glueobj(loc)
|
||||
to_chat(user, "<span class='notice'> You slap some glue onto [src].</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to glue [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
//Seats
|
||||
//bore a platform into a seat
|
||||
/obj/item/processed/wood/platform/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/borer))
|
||||
to_chat(user,"<span class='notice'> You begin to cut four holes into [src]...</span>")
|
||||
if(do_after(user, 40) && isturf(loc))
|
||||
new src.boreobj(loc)
|
||||
to_chat(user, "<span class='notice'> You drill four holes into [src].</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to refine [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
//Stools - Further crafting
|
||||
/obj/item/processed/wood/stool1/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/nails))
|
||||
to_chat(user,"<span class='notice'> You place nails into [src]...</span>")
|
||||
if(do_after(user, 20) && isturf(loc))
|
||||
new /obj/item/processed/wood/stool2(loc)
|
||||
to_chat(user, "<span class='notice'> The nails are ready to be hammered.</span>")
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to refine [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/processed/wood/stool2/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/hammer))
|
||||
to_chat(user,"<span class='notice'> You begin to hammer the [src]...</span>")
|
||||
if(do_after(user, 30) && isturf(loc))
|
||||
new /obj/item/processed/wood/stool3(loc)
|
||||
to_chat(user, "<span class='notice'> The nails are hammered into place.</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to refine [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/processed/wood/stool3/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/carpentry/sandpaper))
|
||||
to_chat(user,"<span class='notice'> You begin to sand the [src]...</span>")
|
||||
if(do_after(user, 30) && isturf(loc))
|
||||
new /obj/item/processed/wood/stool4(loc)
|
||||
to_chat(user, "<span class='notice'> You sand down the [src].</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to refine [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/processed/wood/stool4/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/processed/wood/glueblock))
|
||||
to_chat(user,"<span class='notice'> You add some finishing touches to the [src]...</span>")
|
||||
if(do_after(user, 30) && isturf(loc))
|
||||
new /obj/item/processed/wood/stool(loc)
|
||||
to_chat(user, "<span class='notice'> You complete the [src].</span>")
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to refine [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/processed/wood/stool/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/cushion))
|
||||
to_chat(user,"<span class='notice'> You secure a cloth cushion to [src]...</span>")
|
||||
if(do_after(user, 30) && isturf(loc))
|
||||
new /obj/item/processed/wood/stoolcloth(loc)
|
||||
to_chat(user, "<span class='notice'> You add a cushion to [src].</span>")
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to detail [src]!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/processed/wood/stool/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/cushion/silk))
|
||||
to_chat(user,"<span class='notice'> You secure a silk cushion to [src]...</span>")
|
||||
if(do_after(user, 30) && isturf(loc))
|
||||
new /obj/item/processed/wood/stoolsilk(loc)
|
||||
to_chat(user, "<span class='notice'> You add a cushion to [src].</span>")
|
||||
qdel(src)
|
||||
qdel(I)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to hold still to detail [src]!</span>")
|
||||
else
|
||||
..()
|
||||
128
hyperstation/code/modules/cargo/sweatshop/wooden.dm
Normal file
@@ -0,0 +1,128 @@
|
||||
//WOODEN COMPONENTS. honestly i need to move some shit around to allow for easier material swapping, but that's for a later date.
|
||||
|
||||
/obj/item/processed/wood
|
||||
name = "Wooden Processed Item"
|
||||
desc = "You shouldn't see this!"
|
||||
icon = 'hyperstation/icons/obj/cargo/sweatshop/wooden.dmi'
|
||||
sharpness = FALSE
|
||||
attack_verb = list("slapped", "thunked")
|
||||
var/sawobj = /obj/item/condom
|
||||
var/glueobj = /obj/item/dildo
|
||||
var/sandobj = /obj/item/carpentry/sandpaper
|
||||
var/boreobj = /obj/item/carpentry/borer
|
||||
|
||||
/obj/item/processed/wood/plank
|
||||
name = "processable wooden plank"
|
||||
desc = "A somewhat sturdy refined plank. This can be used in various applications."
|
||||
icon_state = "plank"
|
||||
force = 3
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
sawobj = /obj/item/processed/wood/platform
|
||||
|
||||
/obj/item/processed/wood/platform
|
||||
name = "wood platform"
|
||||
desc = "A somewhat sturdy cropping of a plank. This one is an alright foundation for chairs and stools."
|
||||
icon_state = "platform"
|
||||
force = 3
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
sawobj = /obj/item/processed/wood/block
|
||||
boreobj = /obj/item/processed/wood/seat
|
||||
|
||||
/obj/item/processed/wood/block
|
||||
name = "wood block"
|
||||
desc = "A chopped platform into a wooden block. This one can be used for sanded into pegs, or used as a base on it's own."
|
||||
icon_state = "block"
|
||||
force = 2
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
sandobj = /obj/item/processed/wood/peg
|
||||
glueobj = /obj/item/processed/wood/glueblock
|
||||
|
||||
/obj/item/processed/wood/peg
|
||||
name = "wood peg"
|
||||
desc = "A wooden peg. Useful for fitting into holes."
|
||||
icon_state = "peg"
|
||||
force = 1
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
attack_verb = list("donked", "thunked")
|
||||
glueobj = /obj/item/processed/wood/gluepeg
|
||||
|
||||
//glue
|
||||
|
||||
/obj/item/processed/wood/gluepeg
|
||||
name = "glued wood peg"
|
||||
desc = "A wooden peg. With a bunch of glue used for securing."
|
||||
icon_state = "gluepeg"
|
||||
force = 1
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
attack_verb = list("pegged", "thunked")
|
||||
|
||||
/obj/item/processed/wood/glueblock
|
||||
name = "glued wood block"
|
||||
desc = "A wooden block. With a bunch of glue used for securing."
|
||||
icon_state = "glueblock"
|
||||
force = 2
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb = list("blocked", "thunked")
|
||||
|
||||
//seat
|
||||
/obj/item/processed/wood/seat
|
||||
name = "wood seat"
|
||||
desc = "A baseline for crafting seats. Not exactly that comfortable to sit on..."
|
||||
icon_state = "seat"
|
||||
force = 2
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb = list("slapped", "thunked")
|
||||
|
||||
|
||||
//Stool steps. There's probably an easier way to do this, but I cannot be assed rn, I'll refine after PR
|
||||
/obj/item/processed/wood/stool1
|
||||
name = "stool base"
|
||||
desc = "A haphazardly made base for a stool. It's not even secured with any nails."
|
||||
icon_state = "stool1"
|
||||
force = 4
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/processed/wood/stool2
|
||||
name = "nailed stool base"
|
||||
desc = "Nails are in position"
|
||||
icon_state = "stool2"
|
||||
force = 4
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/processed/wood/stool3
|
||||
name = "hammered stool base"
|
||||
desc = "A vaguely stool-shaped... Thing. Could use some sandpaper."
|
||||
icon_state = "stool3"
|
||||
force = 4
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/processed/wood/stool4
|
||||
name = "bland stool"
|
||||
desc = "A rather bland stool."
|
||||
icon_state = "stool4"
|
||||
force = 4
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
//The finished product
|
||||
/obj/item/processed/wood/stool
|
||||
name = "custom stool"
|
||||
desc = "An intricite, custom stool."
|
||||
icon_state = "stool"
|
||||
force = 10
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
//Let's make it soft and more expensive
|
||||
|
||||
/obj/item/processed/wood/stoolcloth
|
||||
name = "cloth-cushioned stool"
|
||||
desc = "A custom stool with a cloth cushion."
|
||||
icon_state = "stoolcloth"
|
||||
force = 10
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/processed/wood/stoolsilk
|
||||
name = "cloth-cushioned stool"
|
||||
desc = "A custom stool with a silk cushion."
|
||||
icon_state = "stoolsilk"
|
||||
force = 11 //lol
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
11
hyperstation/code/modules/client/loadout/glasses.dm
Normal file
@@ -0,0 +1,11 @@
|
||||
/datum/gear/glasses/garb
|
||||
name = "polychromic gar glasses"
|
||||
category =ITEM_SLOT_GLASSES
|
||||
path = /obj/item/clothing/glasses/polychromic/garpoly
|
||||
cost = 2
|
||||
|
||||
/datum/gear/glasses/gigagarb
|
||||
name = "polychromic giga gar glasses"
|
||||
category =ITEM_SLOT_GLASSES
|
||||
path = /obj/item/clothing/glasses/polychromic/supergarpoly
|
||||
cost = 2
|
||||
11
hyperstation/code/modules/client/loadout/gloves.dm
Normal file
@@ -0,0 +1,11 @@
|
||||
/datum/gear/syntech/ring
|
||||
name = "Normalizer Ring"
|
||||
category =ITEM_SLOT_GLOVES
|
||||
path = /obj/item/clothing/gloves/ring/syntech
|
||||
cost = 6
|
||||
|
||||
/datum/gear/syntech/band
|
||||
name = "Normalizer Band"
|
||||
category =ITEM_SLOT_GLOVES
|
||||
path = /obj/item/clothing/gloves/ring/syntech/band
|
||||
cost = 6
|
||||