Merge branch 'master' of https://github.com/PolarisSS13/Polaris into 2/28/2016_armor
@@ -63,7 +63,6 @@ var/list/be_special_flags = list(
|
||||
|
||||
// Mode/antag template macros.
|
||||
#define MODE_BORER "borer"
|
||||
#define MODE_XENOMORPH "xeno"
|
||||
#define MODE_LOYALIST "loyalist"
|
||||
#define MODE_MUTINEER "mutineer"
|
||||
#define MODE_COMMANDO "commando"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Species flags.
|
||||
#define NO_MINOR_CUT 0x1 // Can step on broken glass with no ill-effects. Either thick skin (diona/vox), cut resistant (slimes) or incorporeal (shadows)
|
||||
#define NO_MINOR_CUT 0x1 // Can step on broken glass with no ill-effects. Either thick skin (diona), cut resistant (slimes) or incorporeal (shadows)
|
||||
#define IS_PLANT 0x2 // Is a treeperson.
|
||||
#define NO_SCAN 0x4 // Cannot be scanned in a DNA machine/genome-stolen.
|
||||
#define NO_PAIN 0x8 // Cannot suffer halloss/recieves deceptive health indicator.
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
/atom/movable/proc/get_mob()
|
||||
return
|
||||
|
||||
/obj/machinery/bot/mulebot/get_mob()
|
||||
if(load && istype(load,/mob/living))
|
||||
return load
|
||||
|
||||
/obj/mecha/get_mob()
|
||||
return occupant
|
||||
|
||||
@@ -14,6 +10,11 @@
|
||||
/mob/get_mob()
|
||||
return src
|
||||
|
||||
/mob/living/bot/mulebot/get_mob()
|
||||
if(load && istype(load, /mob/living))
|
||||
return list(src, load)
|
||||
return src
|
||||
|
||||
/proc/mobs_in_view(var/range, var/source)
|
||||
var/list/mobs = list()
|
||||
for(var/atom/movable/AM in view(range, source))
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
return // seems legit.
|
||||
|
||||
// Things you might plausibly want to follow
|
||||
if((ismob(A) && A != src) || istype(A,/obj/machinery/bot) || istype(A,/obj/singularity))
|
||||
if((ismob(A) && A != src) || istype(A,/obj/singularity))
|
||||
ManualFollow(A)
|
||||
|
||||
// Otherwise jump
|
||||
|
||||
@@ -278,11 +278,11 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
group = "Miscellaneous"
|
||||
|
||||
/datum/supply_packs/mule
|
||||
name = "MULEbot Crate"
|
||||
contains = list(/obj/machinery/bot/mulebot)
|
||||
name = "Mulebot Crate"
|
||||
contains = list()
|
||||
cost = 20
|
||||
containertype = /obj/structure/largecrate/mule
|
||||
containername = "MULEbot Crate"
|
||||
containertype = /obj/structure/largecrate/animal/mulebot
|
||||
containername = "Mulebot Crate"
|
||||
group = "Operations"
|
||||
|
||||
/datum/supply_packs/cargotrain
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/datum/wires/mulebot
|
||||
random = 1
|
||||
holder_type = /obj/machinery/bot/mulebot
|
||||
wire_count = 10
|
||||
|
||||
var/const/WIRE_POWER1 = 1 // power connections
|
||||
var/const/WIRE_POWER2 = 2
|
||||
var/const/WIRE_AVOIDANCE = 4 // mob avoidance
|
||||
var/const/WIRE_LOADCHECK = 8 // load checking (non-crate)
|
||||
var/const/WIRE_MOTOR1 = 16 // motor wires
|
||||
var/const/WIRE_MOTOR2 = 32 //
|
||||
var/const/WIRE_REMOTE_RX = 64 // remote recv functions
|
||||
var/const/WIRE_REMOTE_TX = 128 // remote trans status
|
||||
var/const/WIRE_BEACON_RX = 256 // beacon ping recv
|
||||
|
||||
/datum/wires/mulebot/CanUse(var/mob/living/L)
|
||||
var/obj/machinery/bot/mulebot/M = holder
|
||||
if(M.open)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
// So the wires do not open a new window, handle the interaction ourselves.
|
||||
/datum/wires/mulebot/Interact(var/mob/living/user)
|
||||
if(CanUse(user))
|
||||
var/obj/machinery/bot/mulebot/M = holder
|
||||
M.interact(user)
|
||||
|
||||
/datum/wires/mulebot/UpdatePulsed(var/index)
|
||||
switch(index)
|
||||
if(WIRE_POWER1, WIRE_POWER2)
|
||||
holder.visible_message("<span class='notice'>\icon[holder] The charge light flickers.</span>")
|
||||
if(WIRE_AVOIDANCE)
|
||||
holder.visible_message("<span class='notice'>\icon[holder] The external warning lights flash briefly.</span>")
|
||||
if(WIRE_LOADCHECK)
|
||||
holder.visible_message("<span class='notice'>\icon[holder] The load platform clunks.</span>")
|
||||
if(WIRE_MOTOR1, WIRE_MOTOR2)
|
||||
holder.visible_message("<span class='notice'>\icon[holder] The drive motor whines briefly.</span>")
|
||||
else
|
||||
holder.visible_message("<span class='notice'>\icon[holder] You hear a radio crackle.</span>")
|
||||
|
||||
// HELPER PROCS
|
||||
|
||||
/datum/wires/mulebot/proc/Motor1()
|
||||
return !(wires_status & WIRE_MOTOR1)
|
||||
|
||||
/datum/wires/mulebot/proc/Motor2()
|
||||
return !(wires_status & WIRE_MOTOR2)
|
||||
|
||||
/datum/wires/mulebot/proc/HasPower()
|
||||
return !(wires_status & WIRE_POWER1) && !(wires_status & WIRE_POWER2)
|
||||
|
||||
/datum/wires/mulebot/proc/LoadCheck()
|
||||
return !(wires_status & WIRE_LOADCHECK)
|
||||
|
||||
/datum/wires/mulebot/proc/MobAvoid()
|
||||
return !(wires_status & WIRE_AVOIDANCE)
|
||||
|
||||
/datum/wires/mulebot/proc/RemoteTX()
|
||||
return !(wires_status & WIRE_REMOTE_TX)
|
||||
|
||||
/datum/wires/mulebot/proc/RemoteRX()
|
||||
return !(wires_status & WIRE_REMOTE_RX)
|
||||
|
||||
/datum/wires/mulebot/proc/BeaconRX()
|
||||
return !(wires_status & WIRE_BEACON_RX)
|
||||
@@ -1,7 +1,8 @@
|
||||
var/datum/antagonist/xenos/borer/borers
|
||||
var/datum/antagonist/borer/borers
|
||||
|
||||
/datum/antagonist/xenos/borer
|
||||
/datum/antagonist/borer
|
||||
id = MODE_BORER
|
||||
role_type = BE_ALIEN
|
||||
role_text = "Cortical Borer"
|
||||
role_text_plural = "Cortical Borers"
|
||||
mob_path = /mob/living/simple_animal/borer
|
||||
@@ -10,6 +11,8 @@ var/datum/antagonist/xenos/borer/borers
|
||||
antag_indicator = "brainworm"
|
||||
antaghud_indicator = "hudborer"
|
||||
|
||||
flags = ANTAG_OVERRIDE_MOB | ANTAG_RANDSPAWN | ANTAG_OVERRIDE_JOB | ANTAG_VOTABLE
|
||||
|
||||
faction_role_text = "Borer Thrall"
|
||||
faction_descriptor = "Unity"
|
||||
faction_welcome = "You are now a thrall to a cortical borer. Please listen to what they have to say; they're in your head."
|
||||
@@ -17,21 +20,26 @@ var/datum/antagonist/xenos/borer/borers
|
||||
initial_spawn_req = 3
|
||||
initial_spawn_target = 5
|
||||
|
||||
/datum/antagonist/xenos/borer/New()
|
||||
spawn_announcement = "Unidentified lifesigns detected coming aboard the station. Secure any exterior access, including ducting and ventilation."
|
||||
spawn_announcement_title = "Lifesign Alert"
|
||||
spawn_announcement_sound = 'sound/AI/aliens.ogg'
|
||||
spawn_announcement_delay = 5000
|
||||
|
||||
/datum/antagonist/borer/New()
|
||||
..(1)
|
||||
borers = src
|
||||
|
||||
/datum/antagonist/xenos/borer/get_extra_panel_options(var/datum/mind/player)
|
||||
return "<a href='?src=\ref[src];move_to_spawn=\ref[player.current]'>\[put in host\]</a>"
|
||||
|
||||
/datum/antagonist/xenos/borer/create_objectives(var/datum/mind/player)
|
||||
/datum/antagonist/borer/create_objectives(var/datum/mind/player)
|
||||
if(!..())
|
||||
return
|
||||
player.objectives += new /datum/objective/borer_survive()
|
||||
player.objectives += new /datum/objective/borer_reproduce()
|
||||
player.objectives += new /datum/objective/escape()
|
||||
|
||||
/datum/antagonist/xenos/borer/place_mob(var/mob/living/mob)
|
||||
/datum/antagonist/borer/place_mob(var/mob/living/mob)
|
||||
var/mob/living/simple_animal/borer/borer = mob
|
||||
if(istype(borer))
|
||||
var/mob/living/carbon/human/host
|
||||
@@ -51,4 +59,16 @@ var/datum/antagonist/xenos/borer/borers
|
||||
borer.host_brain.name = host.name
|
||||
borer.host_brain.real_name = host.real_name
|
||||
return
|
||||
..() // Place them at a vent if they can't get a host.
|
||||
// Place them at a vent if they can't get a host.
|
||||
borer.forceMove(get_turf(pick(get_vents())))
|
||||
|
||||
/datum/antagonist/borer/attempt_random_spawn()
|
||||
if(config.aliens_allowed) ..()
|
||||
|
||||
/datum/antagonist/borer/proc/get_vents()
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines)
|
||||
if(!temp_vent.welded && temp_vent.network && temp_vent.loc.z in config.station_levels)
|
||||
if(temp_vent.network.normal_members.len > 50)
|
||||
vents += temp_vent
|
||||
return vents
|
||||
@@ -1,47 +0,0 @@
|
||||
var/datum/antagonist/xenos/xenomorphs
|
||||
|
||||
/datum/antagonist/xenos
|
||||
id = MODE_XENOMORPH
|
||||
role_type = BE_ALIEN
|
||||
role_text = "Xenomorph"
|
||||
role_text_plural = "Xenomorphs"
|
||||
mob_path = /mob/living/carbon/alien/larva
|
||||
bantype = "Xenomorph"
|
||||
flags = ANTAG_OVERRIDE_MOB | ANTAG_RANDSPAWN | ANTAG_OVERRIDE_JOB | ANTAG_VOTABLE
|
||||
welcome_text = "Hiss! You are a larval alien. Hide and bide your time until you are ready to evolve."
|
||||
antaghud_indicator = "hudalien"
|
||||
|
||||
hard_cap = 5
|
||||
hard_cap_round = 8
|
||||
initial_spawn_req = 4
|
||||
initial_spawn_target = 6
|
||||
|
||||
spawn_announcement = "Unidentified lifesigns detected coming aboard the station. Secure any exterior access, including ducting and ventilation."
|
||||
spawn_announcement_title = "Lifesign Alert"
|
||||
spawn_announcement_sound = 'sound/AI/aliens.ogg'
|
||||
spawn_announcement_delay = 5000
|
||||
|
||||
/datum/antagonist/xenos/New(var/no_reference)
|
||||
..()
|
||||
if(!no_reference)
|
||||
xenomorphs = src
|
||||
|
||||
/datum/antagonist/xenos/attempt_random_spawn()
|
||||
if(config.aliens_allowed) ..()
|
||||
|
||||
/datum/antagonist/xenos/proc/get_vents()
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines)
|
||||
if(!temp_vent.welded && temp_vent.network && temp_vent.loc.z in config.station_levels)
|
||||
if(temp_vent.network.normal_members.len > 50)
|
||||
vents += temp_vent
|
||||
return vents
|
||||
|
||||
/datum/antagonist/xenos/create_objectives(var/datum/mind/player)
|
||||
if(!..())
|
||||
return
|
||||
player.objectives += new /datum/objective/survive()
|
||||
player.objectives += new /datum/objective/escape()
|
||||
|
||||
/datum/antagonist/xenos/place_mob(var/mob/living/player)
|
||||
player.forceMove(get_turf(pick(get_vents())))
|
||||
@@ -161,7 +161,7 @@ var/datum/antagonist/raider/raiders
|
||||
else
|
||||
win_type = "Minor"
|
||||
win_group = "Crew"
|
||||
//Now we modify that result by the state of the vox crew.
|
||||
//Now we modify that result by the state of the crew.
|
||||
if(antags_are_dead())
|
||||
win_type = "Major"
|
||||
win_group = "Crew"
|
||||
@@ -198,26 +198,23 @@ var/datum/antagonist/raider/raiders
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(player.species && player.species.get_bodytype() == "Vox")
|
||||
equip_vox(player)
|
||||
else
|
||||
var/new_shoes = pick(raider_shoes)
|
||||
var/new_uniform = pick(raider_uniforms)
|
||||
var/new_glasses = pick(raider_glasses)
|
||||
var/new_helmet = pick(raider_helmets)
|
||||
var/new_suit = pick(raider_suits)
|
||||
var/new_shoes = pick(raider_shoes)
|
||||
var/new_uniform = pick(raider_uniforms)
|
||||
var/new_glasses = pick(raider_glasses)
|
||||
var/new_helmet = pick(raider_helmets)
|
||||
var/new_suit = pick(raider_suits)
|
||||
|
||||
player.equip_to_slot_or_del(new new_shoes(player),slot_shoes)
|
||||
if(!player.shoes)
|
||||
//If equipping shoes failed, fall back to equipping sandals
|
||||
var/fallback_type = pick(/obj/item/clothing/shoes/sandal, /obj/item/clothing/shoes/jackboots/unathi)
|
||||
player.equip_to_slot_or_del(new fallback_type(player), slot_shoes)
|
||||
player.equip_to_slot_or_del(new new_shoes(player),slot_shoes)
|
||||
if(!player.shoes)
|
||||
//If equipping shoes failed, fall back to equipping sandals
|
||||
var/fallback_type = pick(/obj/item/clothing/shoes/sandal, /obj/item/clothing/shoes/jackboots/unathi)
|
||||
player.equip_to_slot_or_del(new fallback_type(player), slot_shoes)
|
||||
|
||||
player.equip_to_slot_or_del(new new_uniform(player),slot_w_uniform)
|
||||
player.equip_to_slot_or_del(new new_glasses(player),slot_glasses)
|
||||
player.equip_to_slot_or_del(new new_helmet(player),slot_head)
|
||||
player.equip_to_slot_or_del(new new_suit(player),slot_wear_suit)
|
||||
equip_weapons(player)
|
||||
player.equip_to_slot_or_del(new new_uniform(player),slot_w_uniform)
|
||||
player.equip_to_slot_or_del(new new_glasses(player),slot_glasses)
|
||||
player.equip_to_slot_or_del(new new_helmet(player),slot_head)
|
||||
player.equip_to_slot_or_del(new new_suit(player),slot_wear_suit)
|
||||
equip_weapons(player)
|
||||
|
||||
var/obj/item/weapon/card/id/id = create_id("Visitor", player, equip = 0)
|
||||
id.name = "[player.real_name]'s Passport"
|
||||
@@ -293,21 +290,3 @@ var/datum/antagonist/raider/raiders
|
||||
var/grenade_type = pick(grenades)
|
||||
new grenade_type(ammobox)
|
||||
player.put_in_any_hand_if_possible(ammobox)
|
||||
|
||||
/datum/antagonist/raider/proc/equip_vox(var/mob/living/carbon/human/player)
|
||||
|
||||
var/uniform_type = pick(list(/obj/item/clothing/under/vox/vox_robes,/obj/item/clothing/under/vox/vox_casual))
|
||||
|
||||
player.equip_to_slot_or_del(new uniform_type(player), slot_w_uniform)
|
||||
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(player), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES.
|
||||
player.equip_to_slot_or_del(new /obj/item/clothing/gloves/yellow/vox(player), slot_gloves) // AS ABOVE.
|
||||
player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat/vox(player), slot_wear_mask)
|
||||
player.equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(player), slot_back)
|
||||
player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_r_store)
|
||||
|
||||
player.internal = locate(/obj/item/weapon/tank) in player.contents
|
||||
if(istype(player.internal,/obj/item/weapon/tank) && player.internals)
|
||||
player.internals.icon_state = "internal1"
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
@@ -350,11 +350,6 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is
|
||||
M << "<br>"
|
||||
M.add_ion_law("THE STATION IS [who2pref] [who2]")
|
||||
|
||||
if(botEmagChance)
|
||||
for(var/obj/machinery/bot/bot in machines)
|
||||
if(prob(botEmagChance))
|
||||
bot.emag_act(1)
|
||||
|
||||
/*
|
||||
|
||||
var/apcnum = 0
|
||||
|
||||
@@ -254,13 +254,13 @@ var/global/list/additional_antag_types = list()
|
||||
"suspected criminal operatives",
|
||||
"malfunctioning von Neumann probe swarms",
|
||||
"shadowy interlopers",
|
||||
"a stranded Vox arkship",
|
||||
"a stranded alien arkship",
|
||||
"haywire IPC constructs",
|
||||
"rogue Unathi exiles",
|
||||
"artifacts of eldritch horror",
|
||||
"a brain slug infestation",
|
||||
"killer bugs that lay eggs in the husks of the living",
|
||||
"a deserted transport carrying xenomorph specimens",
|
||||
"a deserted transport carrying alien specimens",
|
||||
"an emissary for the gestalt requesting a security detail",
|
||||
"a Tajaran slave rebellion",
|
||||
"radical Skrellian transevolutionaries",
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/datum/game_mode/bughunt
|
||||
name = "Bughunt"
|
||||
round_description = "A mercenary strike force is approaching the station to eradicate a xenomorph infestation!"
|
||||
extended_round_description = "Mercenaries and xenomorphs spawn in this game mode."
|
||||
config_tag = "bughunt"
|
||||
required_players = 15
|
||||
required_players_secret = 25
|
||||
required_enemies = 1
|
||||
end_on_antag_death = 1
|
||||
antag_tags = list(MODE_XENOMORPH, MODE_DEATHSQUAD)
|
||||
auto_recall_shuttle = 1
|
||||
ert_disabled = 1
|
||||
require_all_templates = 1
|
||||
votable = 0
|
||||
@@ -1,12 +1,12 @@
|
||||
/datum/game_mode/infestation
|
||||
name = "infestation"
|
||||
round_description = "There's something in the walls!"
|
||||
extended_round_description = "Two alien antagonists (Xenomorphs, Cortical Borers or Changelings) may spawn during this round."
|
||||
extended_round_description = "Two alien antagonists (Cortical Borers or Changelings) spawn during this round."
|
||||
config_tag = "infestation"
|
||||
required_players = 15
|
||||
required_enemies = 5
|
||||
end_on_antag_death = 1
|
||||
antag_tags = list(MODE_BORER, MODE_XENOMORPH, MODE_CHANGELING)
|
||||
antag_tags = list(MODE_BORER, MODE_CHANGELING)
|
||||
require_all_templates = 1
|
||||
votable = 0
|
||||
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
// AI (i.e. game AI, not the AI player) controlled bots
|
||||
|
||||
/obj/machinery/bot
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
layer = MOB_LAYER
|
||||
light_range = 3
|
||||
use_power = 0
|
||||
var/obj/item/weapon/card/id/botcard // the ID card that the bot "holds"
|
||||
var/on = 1
|
||||
var/health = 0 //do not forget to set health for your bot!
|
||||
var/maxhealth = 0
|
||||
var/fire_dam_coeff = 1.0
|
||||
var/brute_dam_coeff = 1.0
|
||||
var/open = 0//Maint panel
|
||||
var/locked = 1
|
||||
//var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots
|
||||
|
||||
/obj/machinery/bot/proc/turn_on()
|
||||
if(stat) return 0
|
||||
on = 1
|
||||
set_light(initial(light_range))
|
||||
return 1
|
||||
|
||||
/obj/machinery/bot/proc/turn_off()
|
||||
on = 0
|
||||
set_light(0)
|
||||
|
||||
/obj/machinery/bot/proc/explode()
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/bot/proc/healthcheck()
|
||||
if (src.health <= 0)
|
||||
src.explode()
|
||||
|
||||
/obj/machinery/bot/emag_act(var/remaining_charges, var/user)
|
||||
if(locked && !emagged)
|
||||
locked = 0
|
||||
emagged = 1
|
||||
user << "<span class='warning'>You short out [src]'s maintenance hatch lock.</span>"
|
||||
log_and_message_admins("emagged [src]'s maintenance hatch lock")
|
||||
return 1
|
||||
|
||||
if(!locked && open && emagged == 1)
|
||||
emagged = 2
|
||||
log_and_message_admins("emagged [src]'s inner circuits")
|
||||
return 1
|
||||
|
||||
/obj/machinery/bot/examine(mob/user)
|
||||
..(user)
|
||||
if (src.health < maxhealth)
|
||||
if (src.health > maxhealth/3)
|
||||
user << "<span class='warning'>[src]'s parts look loose.</span>"
|
||||
else
|
||||
user << "<span class='danger'>[src]'s parts look very loose!</span>"
|
||||
return
|
||||
|
||||
/obj/machinery/bot/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/screwdriver))
|
||||
if(!locked)
|
||||
open = !open
|
||||
user << "<span class='notice'>Maintenance panel is now [src.open ? "opened" : "closed"].</span>"
|
||||
else if(istype(W, /obj/item/weapon/weldingtool))
|
||||
if(health < maxhealth)
|
||||
if(open)
|
||||
health = min(maxhealth, health+10)
|
||||
user.visible_message("<span class='warning'>[user] repairs [src]!</span>","<span class='notice'>You repair [src]!</span>")
|
||||
else
|
||||
user << "<span class='notice'>Unable to repair with the maintenance panel closed.</span>"
|
||||
else
|
||||
user << "<span class='notice'>[src] does not need a repair.</span>"
|
||||
else
|
||||
if(hasvar(W,"force") && hasvar(W,"damtype"))
|
||||
switch(W.damtype)
|
||||
if("fire")
|
||||
src.health -= W.force * fire_dam_coeff
|
||||
if("brute")
|
||||
src.health -= W.force * brute_dam_coeff
|
||||
..()
|
||||
healthcheck()
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/bot/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
|
||||
return
|
||||
health -= Proj.damage
|
||||
..()
|
||||
healthcheck()
|
||||
|
||||
/obj/machinery/bot/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
src.explode()
|
||||
return
|
||||
if(2.0)
|
||||
src.health -= rand(5,10)*fire_dam_coeff
|
||||
src.health -= rand(10,20)*brute_dam_coeff
|
||||
healthcheck()
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(50))
|
||||
src.health -= rand(1,5)*fire_dam_coeff
|
||||
src.health -= rand(1,5)*brute_dam_coeff
|
||||
healthcheck()
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/bot/emp_act(severity)
|
||||
var/was_on = on
|
||||
stat |= EMPED
|
||||
var/obj/effect/overlay/pulse2 = PoolOrNew(/obj/effect/overlay, src.loc )
|
||||
pulse2.icon = 'icons/effects/effects.dmi'
|
||||
pulse2.icon_state = "empdisable"
|
||||
pulse2.name = "emp sparks"
|
||||
pulse2.anchored = 1
|
||||
pulse2.set_dir(pick(cardinal))
|
||||
|
||||
spawn(10)
|
||||
qdel(pulse2)
|
||||
if (on)
|
||||
turn_off()
|
||||
spawn(severity*300)
|
||||
stat &= ~EMPED
|
||||
if (was_on)
|
||||
turn_on()
|
||||
|
||||
|
||||
/obj/machinery/bot/attack_ai(mob/user as mob)
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/machinery/bot/attack_hand(var/mob/living/carbon/human/user)
|
||||
|
||||
if(!istype(user))
|
||||
return ..()
|
||||
|
||||
if(user.species.can_shred(user))
|
||||
src.health -= rand(15,30)*brute_dam_coeff
|
||||
src.visible_message("<span class='danger'>[user] has slashed [src]!</span>")
|
||||
playsound(src.loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
if(prob(10))
|
||||
new /obj/effect/decal/cleanable/blood/oil(src.loc)
|
||||
healthcheck()
|
||||
|
||||
/******************************************************************/
|
||||
// Navigation procs
|
||||
// Used for A-star pathfinding
|
||||
|
||||
|
||||
// Returns the surrounding cardinal turfs with open links
|
||||
// Including through doors openable with the ID
|
||||
/turf/proc/CardinalTurfsWithAccess(var/obj/item/weapon/card/id/ID)
|
||||
var/L[] = new()
|
||||
|
||||
// for(var/turf/simulated/t in oview(src,1))
|
||||
|
||||
for(var/d in cardinal)
|
||||
var/turf/simulated/T = get_step(src, d)
|
||||
if(istype(T) && !T.density)
|
||||
if(!LinkBlockedWithAccess(src, T, ID))
|
||||
L.Add(T)
|
||||
return L
|
||||
|
||||
|
||||
// Returns true if a link between A and B is blocked
|
||||
// Movement through doors allowed if ID has access
|
||||
/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID)
|
||||
|
||||
if(A == null || B == null) return 1
|
||||
var/adir = get_dir(A,B)
|
||||
var/rdir = get_dir(B,A)
|
||||
if((adir & (NORTH|SOUTH)) && (adir & (EAST|WEST))) // diagonal
|
||||
var/iStep = get_step(A,adir&(NORTH|SOUTH))
|
||||
if(!LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID))
|
||||
return 0
|
||||
|
||||
var/pStep = get_step(A,adir&(EAST|WEST))
|
||||
if(!LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
if(DirBlockedWithAccess(A,adir, ID))
|
||||
return 1
|
||||
|
||||
if(DirBlockedWithAccess(B,rdir, ID))
|
||||
return 1
|
||||
|
||||
for(var/obj/O in B)
|
||||
if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
// Returns true if direction is blocked from loc
|
||||
// Checks doors against access with given ID
|
||||
/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID)
|
||||
for(var/obj/structure/window/D in loc)
|
||||
if(!D.density) continue
|
||||
if(D.dir == SOUTHWEST) return 1
|
||||
if(D.dir == dir) return 1
|
||||
|
||||
for(var/obj/machinery/door/D in loc)
|
||||
if(!D.density) continue
|
||||
if(istype(D, /obj/machinery/door/window))
|
||||
if( dir & D.dir ) return !D.check_access(ID)
|
||||
|
||||
//if((dir & SOUTH) && (D.dir & (EAST|WEST))) return !D.check_access(ID)
|
||||
//if((dir & EAST ) && (D.dir & (NORTH|SOUTH))) return !D.check_access(ID)
|
||||
else return !D.check_access(ID) // it's a real, air blocking door
|
||||
return 0
|
||||
@@ -1,887 +0,0 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
|
||||
|
||||
// Mulebot - carries crates around for Quartermaster
|
||||
// Navigates via floor navbeacons
|
||||
// Remote Controlled from QM's PDA
|
||||
|
||||
|
||||
/obj/machinery/bot/mulebot
|
||||
name = "Mulebot"
|
||||
desc = "A Multiple Utility Load Effector bot."
|
||||
icon_state = "mulebot0"
|
||||
layer = MOB_LAYER
|
||||
density = 1
|
||||
anchored = 1
|
||||
animate_movement=1
|
||||
health = 150 //yeah, it's tougher than ed209 because it is a big metal box with wheels --rastaf0
|
||||
maxhealth = 150
|
||||
fire_dam_coeff = 0.7
|
||||
brute_dam_coeff = 0.5
|
||||
var/atom/movable/load = null // the loaded crate (usually)
|
||||
var/beacon_freq = 1400
|
||||
var/control_freq = BOT_FREQ
|
||||
|
||||
suffix = ""
|
||||
|
||||
var/turf/target // this is turf to navigate to (location of beacon)
|
||||
var/loaddir = 0 // this the direction to unload onto/load from
|
||||
var/new_destination = "" // pending new destination (waiting for beacon response)
|
||||
var/destination = "" // destination description
|
||||
var/home_destination = "" // tag of home beacon
|
||||
req_access = list(access_cargo) // added robotics access so assembly line drop-off works properly -veyveyr //I don't think so, Tim. You need to add it to the MULE's hidden robot ID card. -NEO
|
||||
var/path[] = new()
|
||||
|
||||
var/mode = 0 //0 = idle/ready
|
||||
//1 = loading/unloading
|
||||
//2 = moving to deliver
|
||||
//3 = returning to home
|
||||
//4 = blocked
|
||||
//5 = computing navigation
|
||||
//6 = waiting for nav computation
|
||||
//7 = no destination beacon found (or no route)
|
||||
|
||||
var/blockcount = 0 //number of times retried a blocked path
|
||||
var/reached_target = 1 //true if already reached the target
|
||||
|
||||
var/refresh = 1 // true to refresh dialogue
|
||||
var/auto_return = 1 // true if auto return to home beacon after unload
|
||||
var/auto_pickup = 1 // true if auto-pickup at beacon
|
||||
|
||||
var/obj/item/weapon/cell/cell
|
||||
// the installed power cell
|
||||
|
||||
// constants for internal wiring bitflags
|
||||
var/datum/wires/mulebot/wires = null
|
||||
|
||||
var/bloodiness = 0 // count of bloodiness
|
||||
|
||||
/obj/machinery/bot/mulebot/New()
|
||||
..()
|
||||
wires = new(src)
|
||||
botcard = new(src)
|
||||
botcard.access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
|
||||
cell = new(src)
|
||||
cell.charge = 2000
|
||||
cell.maxcharge = 2000
|
||||
|
||||
spawn(5) // must wait for map loading to finish
|
||||
if(radio_controller)
|
||||
radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT)
|
||||
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
|
||||
|
||||
var/count = 0
|
||||
for(var/obj/machinery/bot/mulebot/other in world)
|
||||
count++
|
||||
if(!suffix)
|
||||
suffix = "#[count]"
|
||||
name = "Mulebot ([suffix])"
|
||||
|
||||
/obj/machinery/bot/mulebot/Destroy()
|
||||
unload(0)
|
||||
qdel(wires)
|
||||
wires = null
|
||||
if(radio_controller)
|
||||
radio_controller.remove_object(src,beacon_freq)
|
||||
radio_controller.remove_object(src,control_freq)
|
||||
return ..()
|
||||
|
||||
// attack by item
|
||||
// emag : lock/unlock,
|
||||
// screwdriver: open/close hatch
|
||||
// cell: insert it
|
||||
// other: chance to knock rider off bot
|
||||
/obj/machinery/bot/mulebot/attackby(var/obj/item/I, var/mob/user)
|
||||
if(istype(I,/obj/item/weapon/cell) && open && !cell)
|
||||
var/obj/item/weapon/cell/C = I
|
||||
user.drop_item()
|
||||
C.loc = src
|
||||
cell = C
|
||||
updateDialog()
|
||||
else if(istype(I,/obj/item/weapon/screwdriver))
|
||||
if(locked)
|
||||
user << "<span class='notice'>The maintenance hatch cannot be opened or closed while the controls are locked.</span>"
|
||||
return
|
||||
|
||||
open = !open
|
||||
if(open)
|
||||
src.visible_message("[user] opens the maintenance hatch of [src]", "<span class='notice'>You open [src]'s maintenance hatch.</span>")
|
||||
on = 0
|
||||
icon_state="mulebot-hatch"
|
||||
else
|
||||
src.visible_message("[user] closes the maintenance hatch of [src]", "<span class='notice'>You close [src]'s maintenance hatch.</span>")
|
||||
icon_state = "mulebot0"
|
||||
|
||||
updateDialog()
|
||||
else if (istype(I, /obj/item/weapon/wrench))
|
||||
if (src.health < maxhealth)
|
||||
src.health = min(maxhealth, src.health+25)
|
||||
user.visible_message(
|
||||
"<span class='notice'>\The [user] repairs \the [src]!</span>",
|
||||
"<span class='notice'>You repair \the [src]!</span>"
|
||||
)
|
||||
else
|
||||
user << "<span class='notice'>[src] does not need a repair!</span>"
|
||||
else if(load && ismob(load)) // chance to knock off rider
|
||||
if(prob(1+I.force * 2))
|
||||
unload(0)
|
||||
user.visible_message("<span class='warning'>[user] knocks [load] off [src] with \the [I]!</span>", "<span class='warning'>You knock [load] off [src] with \the [I]!</span>")
|
||||
else
|
||||
user << "You hit [src] with \the [I] but to no effect."
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/machinery/bot/mulebot/emag_act(var/remaining_charges, var/user)
|
||||
locked = !locked
|
||||
user << "<span class='notice'>You [locked ? "lock" : "unlock"] the mulebot's controls!</span>"
|
||||
flick("mulebot-emagged", src)
|
||||
playsound(src.loc, 'sound/effects/sparks1.ogg', 100, 0)
|
||||
return 1
|
||||
|
||||
/obj/machinery/bot/mulebot/ex_act(var/severity)
|
||||
unload(0)
|
||||
switch(severity)
|
||||
if(2)
|
||||
BITRESET(wires, rand(0,9))
|
||||
BITRESET(wires, rand(0,9))
|
||||
BITRESET(wires, rand(0,9))
|
||||
if(3)
|
||||
BITRESET(wires, rand(0,9))
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/machinery/bot/mulebot/bullet_act()
|
||||
if(prob(50) && !isnull(load))
|
||||
unload(0)
|
||||
if(prob(25))
|
||||
src.visible_message("<span class='warning'>Something shorts out inside [src]!</span>")
|
||||
var/index = 1<< (rand(0,9))
|
||||
if(wires & index)
|
||||
wires &= ~index
|
||||
else
|
||||
wires |= index
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/bot/mulebot/attack_ai(var/mob/user)
|
||||
user.set_machine(src)
|
||||
interact(user, 1)
|
||||
|
||||
/obj/machinery/bot/mulebot/attack_hand(var/mob/user)
|
||||
. = ..()
|
||||
if (.)
|
||||
return
|
||||
user.set_machine(src)
|
||||
interact(user, 0)
|
||||
|
||||
/obj/machinery/bot/mulebot/interact(var/mob/user, var/ai=0)
|
||||
var/dat
|
||||
dat += "<TT><B>Multiple Utility Load Effector Mk. III</B></TT><BR><BR>"
|
||||
dat += "ID: [suffix]<BR>"
|
||||
dat += "Power: [on ? "On" : "Off"]<BR>"
|
||||
|
||||
if(!open)
|
||||
|
||||
dat += "Status: "
|
||||
switch(mode)
|
||||
if(0)
|
||||
dat += "Ready"
|
||||
if(1)
|
||||
dat += "Loading/Unloading"
|
||||
if(2)
|
||||
dat += "Navigating to Delivery Location"
|
||||
if(3)
|
||||
dat += "Navigating to Home"
|
||||
if(4)
|
||||
dat += "Waiting for clear path"
|
||||
if(5,6)
|
||||
dat += "Calculating navigation path"
|
||||
if(7)
|
||||
dat += "Unable to locate destination"
|
||||
|
||||
|
||||
dat += "<BR>Current Load: [load ? load.name : "<i>none</i>"]<BR>"
|
||||
dat += "Destination: [!destination ? "<i>none</i>" : destination]<BR>"
|
||||
dat += "Power level: [cell ? cell.percent() : 0]%<BR>"
|
||||
|
||||
if(locked && !ai)
|
||||
dat += "<HR>Controls are locked <A href='byond://?src=\ref[src];op=unlock'><I>(unlock)</I></A>"
|
||||
else
|
||||
dat += "<HR>Controls are unlocked <A href='byond://?src=\ref[src];op=lock'><I>(lock)</I></A><BR><BR>"
|
||||
|
||||
dat += "<A href='byond://?src=\ref[src];op=power'>Toggle Power</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=stop'>Stop</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=go'>Proceed</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=home'>Return to Home</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=destination'>Set Destination</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=setid'>Set Bot ID</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=sethome'>Set Home</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=autoret'>Toggle Auto Return Home</A> ([auto_return ? "On":"Off"])<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=autopick'>Toggle Auto Pickup Crate</A> ([auto_pickup ? "On":"Off"])<BR>"
|
||||
|
||||
if(load)
|
||||
dat += "<A href='byond://?src=\ref[src];op=unload'>Unload Now</A><BR>"
|
||||
dat += "<HR>The maintenance hatch is closed.<BR>"
|
||||
|
||||
else
|
||||
if(!ai)
|
||||
dat += "The maintenance hatch is open.<BR><BR>"
|
||||
dat += "Power cell: "
|
||||
if(cell)
|
||||
dat += "<A href='byond://?src=\ref[src];op=cellremove'>Installed</A><BR>"
|
||||
else
|
||||
dat += "<A href='byond://?src=\ref[src];op=cellinsert'>Removed</A><BR>"
|
||||
|
||||
dat += wires.GetInteractWindow()
|
||||
else
|
||||
dat += "The bot is in maintenance mode and cannot be controlled.<BR>"
|
||||
|
||||
user << browse("<HEAD><TITLE>Mulebot [suffix ? "([suffix])" : ""]</TITLE></HEAD>[dat]", "window=mulebot;size=350x500")
|
||||
onclose(user, "mulebot")
|
||||
return
|
||||
|
||||
/obj/machinery/bot/mulebot/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if (usr.stat)
|
||||
return
|
||||
if ((in_range(src, usr) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
|
||||
switch(href_list["op"])
|
||||
if("lock", "unlock")
|
||||
if(src.allowed(usr))
|
||||
locked = !locked
|
||||
updateDialog()
|
||||
else
|
||||
usr << "<span class='warning'>Access denied.</span>"
|
||||
return
|
||||
if("power")
|
||||
if (src.on)
|
||||
turn_off()
|
||||
else if (cell && !open)
|
||||
if (!turn_on())
|
||||
usr << "<span class='warning'>You can't switch on [src].</span>"
|
||||
return
|
||||
else
|
||||
return
|
||||
visible_message("[usr] switches [on ? "on" : "off"] [src].")
|
||||
updateDialog()
|
||||
|
||||
|
||||
if("cellremove")
|
||||
if(open && cell && !usr.get_active_hand())
|
||||
cell.update_icon()
|
||||
usr.put_in_active_hand(cell)
|
||||
cell.add_fingerprint(usr)
|
||||
cell = null
|
||||
|
||||
usr.visible_message("<span class='notice'>[usr] removes the power cell from [src].</span>", "<span class='notice'>You remove the power cell from [src].</span>")
|
||||
updateDialog()
|
||||
|
||||
if("cellinsert")
|
||||
if(open && !cell)
|
||||
var/obj/item/weapon/cell/C = usr.get_active_hand()
|
||||
if(istype(C))
|
||||
usr.drop_item()
|
||||
cell = C
|
||||
C.loc = src
|
||||
C.add_fingerprint(usr)
|
||||
|
||||
usr.visible_message("<span class='notice'>[usr] inserts a power cell into [src].</span>", "<span class='notice'>You insert the power cell into [src].</span>")
|
||||
updateDialog()
|
||||
|
||||
|
||||
if("stop")
|
||||
if(mode >=2)
|
||||
mode = 0
|
||||
updateDialog()
|
||||
|
||||
if("go")
|
||||
if(mode == 0)
|
||||
start()
|
||||
updateDialog()
|
||||
|
||||
if("home")
|
||||
if(mode == 0 || mode == 2)
|
||||
start_home()
|
||||
updateDialog()
|
||||
|
||||
if("destination")
|
||||
refresh=0
|
||||
var/new_dest
|
||||
var/list/beaconlist = new()
|
||||
for(var/obj/machinery/navbeacon/N in navbeacons)
|
||||
beaconlist.Add(N.location)
|
||||
if(beaconlist.len)
|
||||
new_dest = input("Select new destination tag", "Mulebot [suffix ? "([suffix])" : ""]", destination) in beaconlist
|
||||
else
|
||||
alert("No destination beacons available.")
|
||||
refresh=1
|
||||
if(new_dest)
|
||||
set_destination(new_dest)
|
||||
|
||||
|
||||
if("setid")
|
||||
refresh=0
|
||||
var/new_id = sanitize(input("Enter new bot ID", "Mulebot [suffix ? "([suffix])" : ""]", suffix) as text|null, MAX_NAME_LEN)
|
||||
refresh=1
|
||||
if(new_id)
|
||||
suffix = new_id
|
||||
name = "Mulebot ([suffix])"
|
||||
updateDialog()
|
||||
|
||||
if("sethome")
|
||||
refresh=0
|
||||
var/new_home = input("Enter new home tag", "Mulebot [suffix ? "([suffix])" : ""]", home_destination) as text|null
|
||||
refresh=1
|
||||
if(new_home)
|
||||
home_destination = new_home
|
||||
updateDialog()
|
||||
|
||||
if("unload")
|
||||
if(load && mode !=1)
|
||||
if(loc == target)
|
||||
unload(loaddir)
|
||||
else
|
||||
unload(0)
|
||||
|
||||
if("autoret")
|
||||
auto_return = !auto_return
|
||||
|
||||
if("autopick")
|
||||
auto_pickup = !auto_pickup
|
||||
|
||||
if("close")
|
||||
usr.unset_machine()
|
||||
usr << browse(null,"window=mulebot")
|
||||
|
||||
updateDialog()
|
||||
//src.updateUsrDialog()
|
||||
else
|
||||
usr << browse(null, "window=mulebot")
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
|
||||
|
||||
// returns true if the bot has power
|
||||
/obj/machinery/bot/mulebot/proc/has_power()
|
||||
return !open && cell && cell.charge>0 && wires.HasPower()
|
||||
|
||||
// mousedrop a crate to load the bot
|
||||
// can load anything if emagged
|
||||
|
||||
/obj/machinery/bot/mulebot/MouseDrop_T(var/atom/movable/C, mob/user)
|
||||
|
||||
if(user.stat)
|
||||
return
|
||||
|
||||
if (!on || !istype(C)|| C.anchored || get_dist(user, src) > 1 || get_dist(src,C) > 1 )
|
||||
return
|
||||
|
||||
if(load)
|
||||
return
|
||||
|
||||
load(C)
|
||||
|
||||
|
||||
// called to load a crate
|
||||
/obj/machinery/bot/mulebot/proc/load(var/atom/movable/C)
|
||||
if(wires.LoadCheck() && !istype(C,/obj/structure/closet/crate))
|
||||
src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
|
||||
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
return // if not emagged, only allow crates to be loaded
|
||||
|
||||
//I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool.
|
||||
//So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below.
|
||||
if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C))
|
||||
return
|
||||
if(!isturf(C.loc)) //To prevent the loading from stuff from someone's inventory, which wouldn't get handled properly.
|
||||
return
|
||||
|
||||
if(get_dist(C, src) > 1 || load || !on)
|
||||
return
|
||||
for(var/obj/structure/plasticflaps/P in src.loc)//Takes flaps into account
|
||||
if(!CanPass(C,P))
|
||||
return
|
||||
mode = 1
|
||||
|
||||
// if a create, close before loading
|
||||
var/obj/structure/closet/crate/crate = C
|
||||
if(istype(crate))
|
||||
crate.close()
|
||||
|
||||
C.loc = src.loc
|
||||
sleep(2)
|
||||
if(C.loc != src.loc) //To prevent you from going onto more thano ne bot.
|
||||
return
|
||||
C.loc = src
|
||||
load = C
|
||||
|
||||
C.pixel_y += 9
|
||||
if(C.layer < layer)
|
||||
C.layer = layer + 0.1
|
||||
overlays += C
|
||||
|
||||
if(ismob(C))
|
||||
var/mob/M = C
|
||||
if(M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
|
||||
mode = 0
|
||||
send_status()
|
||||
|
||||
// called to unload the bot
|
||||
// argument is optional direction to unload
|
||||
// if zero, unload at bot's location
|
||||
/obj/machinery/bot/mulebot/proc/unload(var/dirn = 0)
|
||||
if(!load)
|
||||
return
|
||||
|
||||
mode = 1
|
||||
overlays.Cut()
|
||||
|
||||
load.loc = src.loc
|
||||
load.pixel_y -= 9
|
||||
load.layer = initial(load.layer)
|
||||
if(ismob(load))
|
||||
var/mob/M = load
|
||||
if(M.client)
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
|
||||
|
||||
if(dirn)
|
||||
var/turf/T = src.loc
|
||||
T = get_step(T,dirn)
|
||||
if(CanPass(load,T))//Can't get off onto anything that wouldn't let you pass normally
|
||||
step(load, dirn)
|
||||
else
|
||||
load.loc = src.loc//Drops you right there, so you shouldn't be able to get yourself stuck
|
||||
|
||||
load = null
|
||||
|
||||
// in case non-load items end up in contents, dump every else too
|
||||
// this seems to happen sometimes due to race conditions
|
||||
// with items dropping as mobs are loaded
|
||||
|
||||
for(var/atom/movable/AM in src)
|
||||
if(AM == cell || AM == botcard) continue
|
||||
|
||||
AM.loc = src.loc
|
||||
AM.layer = initial(AM.layer)
|
||||
AM.pixel_y = initial(AM.pixel_y)
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
if(M.client)
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
mode = 0
|
||||
|
||||
|
||||
/obj/machinery/bot/mulebot/process()
|
||||
if(!has_power())
|
||||
on = 0
|
||||
return
|
||||
if(on)
|
||||
var/speed = (wires.Motor1() ? 1:0) + (wires.Motor2() ? 2:0)
|
||||
//world << "speed: [speed]"
|
||||
switch(speed)
|
||||
if(0)
|
||||
// do nothing
|
||||
if(1)
|
||||
process_bot()
|
||||
spawn(2)
|
||||
process_bot()
|
||||
sleep(2)
|
||||
process_bot()
|
||||
sleep(2)
|
||||
process_bot()
|
||||
sleep(2)
|
||||
process_bot()
|
||||
if(2)
|
||||
process_bot()
|
||||
spawn(4)
|
||||
process_bot()
|
||||
if(3)
|
||||
process_bot()
|
||||
|
||||
if(refresh) updateDialog()
|
||||
|
||||
/obj/machinery/bot/mulebot/proc/process_bot()
|
||||
//if(mode) world << "Mode: [mode]"
|
||||
switch(mode)
|
||||
if(0) // idle
|
||||
icon_state = "mulebot0"
|
||||
return
|
||||
if(1) // loading/unloading
|
||||
return
|
||||
if(2,3,4) // navigating to deliver,home, or blocked
|
||||
|
||||
if(loc == target) // reached target
|
||||
at_target()
|
||||
return
|
||||
|
||||
else if(path.len > 0 && target) // valid path
|
||||
|
||||
var/turf/next = path[1]
|
||||
reached_target = 0
|
||||
if(next == loc)
|
||||
path -= next
|
||||
return
|
||||
|
||||
|
||||
if(istype( next, /turf/simulated))
|
||||
//world << "at ([x],[y]) moving to ([next.x],[next.y])"
|
||||
|
||||
|
||||
if(bloodiness)
|
||||
var/obj/effect/decal/cleanable/blood/tracks/B = new(loc)
|
||||
var/newdir = get_dir(next, loc)
|
||||
if(newdir == dir)
|
||||
B.set_dir(newdir)
|
||||
else
|
||||
newdir = newdir | dir
|
||||
if(newdir == 3)
|
||||
newdir = 1
|
||||
else if(newdir == 12)
|
||||
newdir = 4
|
||||
B.set_dir(newdir)
|
||||
bloodiness--
|
||||
|
||||
|
||||
|
||||
var/moved = step_towards(src, next) // attempt to move
|
||||
if(cell) cell.use(1)
|
||||
if(moved) // successful move
|
||||
//world << "Successful move."
|
||||
blockcount = 0
|
||||
path -= loc
|
||||
|
||||
|
||||
if(mode==4)
|
||||
spawn(1)
|
||||
send_status()
|
||||
|
||||
if(destination == home_destination)
|
||||
mode = 3
|
||||
else
|
||||
mode = 2
|
||||
|
||||
else // failed to move
|
||||
|
||||
//world << "Unable to move."
|
||||
|
||||
|
||||
|
||||
blockcount++
|
||||
mode = 4
|
||||
if(blockcount == 3)
|
||||
src.visible_message("[src] makes an annoyed buzzing sound", "You hear an electronic buzzing sound.")
|
||||
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
|
||||
if(blockcount > 5) // attempt 5 times before recomputing
|
||||
// find new path excluding blocked turf
|
||||
src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
|
||||
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
|
||||
spawn(2)
|
||||
calc_path(next)
|
||||
if(path.len > 0)
|
||||
src.visible_message("[src] makes a delighted ping!", "You hear a ping.")
|
||||
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
|
||||
mode = 4
|
||||
mode =6
|
||||
return
|
||||
return
|
||||
else
|
||||
src.visible_message("[src] makes an annoyed buzzing sound", "You hear an electronic buzzing sound.")
|
||||
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
//world << "Bad turf."
|
||||
mode = 5
|
||||
return
|
||||
else
|
||||
//world << "No path."
|
||||
mode = 5
|
||||
return
|
||||
|
||||
if(5) // calculate new path
|
||||
//world << "Calc new path."
|
||||
mode = 6
|
||||
spawn(0)
|
||||
|
||||
calc_path()
|
||||
|
||||
if(path.len > 0)
|
||||
blockcount = 0
|
||||
mode = 4
|
||||
src.visible_message("[src] makes a delighted ping!", "You hear a ping.")
|
||||
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
|
||||
|
||||
else
|
||||
src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
|
||||
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
|
||||
mode = 7
|
||||
//if(6)
|
||||
//world << "Pending path calc."
|
||||
//if(7)
|
||||
//world << "No dest / no route."
|
||||
return
|
||||
|
||||
|
||||
// calculates a path to the current destination
|
||||
// given an optional turf to avoid
|
||||
/obj/machinery/bot/mulebot/proc/calc_path(var/turf/avoid = null)
|
||||
src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 250, id=botcard, exclude=avoid)
|
||||
if(!src.path)
|
||||
src.path = list()
|
||||
|
||||
|
||||
// sets the current destination
|
||||
// signals all beacons matching the delivery code
|
||||
// beacons will return a signal giving their locations
|
||||
/obj/machinery/bot/mulebot/proc/set_destination(var/new_dest)
|
||||
spawn(0)
|
||||
new_destination = new_dest
|
||||
post_signal(beacon_freq, "findbeacon", "delivery")
|
||||
updateDialog()
|
||||
|
||||
// starts bot moving to current destination
|
||||
/obj/machinery/bot/mulebot/proc/start()
|
||||
if(destination == home_destination)
|
||||
mode = 3
|
||||
else
|
||||
mode = 2
|
||||
icon_state = "mulebot[wires.MobAvoid()]"
|
||||
|
||||
// starts bot moving to home
|
||||
// sends a beacon query to find
|
||||
/obj/machinery/bot/mulebot/proc/start_home()
|
||||
spawn(0)
|
||||
set_destination(home_destination)
|
||||
mode = 4
|
||||
icon_state = "mulebot[wires.MobAvoid()]"
|
||||
|
||||
// called when bot reaches current target
|
||||
/obj/machinery/bot/mulebot/proc/at_target()
|
||||
if(!reached_target)
|
||||
src.visible_message("[src] makes a chiming sound!", "You hear a chime.")
|
||||
playsound(src.loc, 'sound/machines/chime.ogg', 50, 0)
|
||||
reached_target = 1
|
||||
|
||||
if(load) // if loaded, unload at target
|
||||
unload(loaddir)
|
||||
else
|
||||
// not loaded
|
||||
if(auto_pickup) // find a crate
|
||||
var/atom/movable/AM
|
||||
if(!wires.LoadCheck()) // if emagged, load first unanchored thing we find
|
||||
for(var/atom/movable/A in get_step(loc, loaddir))
|
||||
if(!A.anchored)
|
||||
AM = A
|
||||
break
|
||||
else // otherwise, look for crates only
|
||||
AM = locate(/obj/structure/closet/crate) in get_step(loc,loaddir)
|
||||
if(AM)
|
||||
load(AM)
|
||||
// whatever happened, check to see if we return home
|
||||
|
||||
if(auto_return && destination != home_destination)
|
||||
// auto return set and not at home already
|
||||
start_home()
|
||||
mode = 4
|
||||
else
|
||||
mode = 0 // otherwise go idle
|
||||
|
||||
send_status() // report status to anyone listening
|
||||
|
||||
return
|
||||
|
||||
// called when bot bumps into anything
|
||||
/obj/machinery/bot/mulebot/Bump(var/atom/obs)
|
||||
if(!wires.MobAvoid()) //usually just bumps, but if avoidance disabled knock over mobs
|
||||
var/mob/M = obs
|
||||
if(ismob(M))
|
||||
if(istype(M,/mob/living/silicon/robot))
|
||||
src.visible_message("<span class='warning'>[src] bumps into [M]!</span>")
|
||||
else
|
||||
src.visible_message("<span class='warning'>[src] knocks over [M]!</span>")
|
||||
M.stop_pulling()
|
||||
M.Stun(8)
|
||||
M.Weaken(5)
|
||||
M.lying = 1
|
||||
..()
|
||||
|
||||
// called from mob/living/carbon/human/Crossed()
|
||||
// when mulebot is in the same loc
|
||||
/obj/machinery/bot/mulebot/proc/RunOver(var/mob/living/carbon/human/H)
|
||||
src.visible_message("<span class='warning'>[src] drives over [H]!</span>")
|
||||
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
|
||||
var/damage = rand(5,15)
|
||||
H.apply_damage(2*damage, BRUTE, BP_HEAD)
|
||||
H.apply_damage(2*damage, BRUTE, BP_TORSO)
|
||||
H.apply_damage(0.5*damage, BRUTE, BP_L_LEG)
|
||||
H.apply_damage(0.5*damage, BRUTE, BP_R_LEG)
|
||||
H.apply_damage(0.5*damage, BRUTE, BP_L_ARM)
|
||||
H.apply_damage(0.5*damage, BRUTE, BP_R_ARM)
|
||||
|
||||
blood_splatter(src,H,1)
|
||||
bloodiness += 4
|
||||
|
||||
// player on mulebot attempted to move
|
||||
/obj/machinery/bot/mulebot/relaymove(var/mob/user)
|
||||
if(user.stat)
|
||||
return
|
||||
if(load == user)
|
||||
unload(0)
|
||||
return
|
||||
|
||||
// receive a radio signal
|
||||
// used for control and beacon reception
|
||||
|
||||
/obj/machinery/bot/mulebot/receive_signal(datum/signal/signal)
|
||||
|
||||
if(!on)
|
||||
return
|
||||
|
||||
var/recv = signal.data["command"]
|
||||
// process all-bot input
|
||||
if(recv=="bot_status" && wires.RemoteRX())
|
||||
send_status()
|
||||
|
||||
|
||||
recv = signal.data["command [suffix]"]
|
||||
if(wires.RemoteRX())
|
||||
// process control input
|
||||
switch(recv)
|
||||
if("stop")
|
||||
mode = 0
|
||||
return
|
||||
|
||||
if("go")
|
||||
start()
|
||||
return
|
||||
|
||||
if("target")
|
||||
set_destination(signal.data["destination"] )
|
||||
return
|
||||
|
||||
if("unload")
|
||||
if(loc == target)
|
||||
unload(loaddir)
|
||||
else
|
||||
unload(0)
|
||||
return
|
||||
|
||||
if("home")
|
||||
start_home()
|
||||
return
|
||||
|
||||
if("bot_status")
|
||||
send_status()
|
||||
return
|
||||
|
||||
if("autoret")
|
||||
auto_return = text2num(signal.data["value"])
|
||||
return
|
||||
|
||||
if("autopick")
|
||||
auto_pickup = text2num(signal.data["value"])
|
||||
return
|
||||
|
||||
// receive response from beacon
|
||||
recv = signal.data["beacon"]
|
||||
if(wires.BeaconRX())
|
||||
if(recv == new_destination) // if the recvd beacon location matches the set destination
|
||||
// the we will navigate there
|
||||
destination = new_destination
|
||||
target = signal.source.loc
|
||||
var/direction = signal.data["dir"] // this will be the load/unload dir
|
||||
if(direction)
|
||||
loaddir = text2num(direction)
|
||||
else
|
||||
loaddir = 0
|
||||
icon_state = "mulebot[wires.MobAvoid()]"
|
||||
calc_path()
|
||||
updateDialog()
|
||||
|
||||
// send a radio signal with a single data key/value pair
|
||||
/obj/machinery/bot/mulebot/proc/post_signal(var/freq, var/key, var/value)
|
||||
post_signal_multiple(freq, list("[key]" = value) )
|
||||
|
||||
// send a radio signal with multiple data key/values
|
||||
/obj/machinery/bot/mulebot/proc/post_signal_multiple(var/freq, var/list/keyval)
|
||||
|
||||
if(freq == beacon_freq && !wires.BeaconRX())
|
||||
return
|
||||
if(freq == control_freq && !wires.RemoteTX())
|
||||
return
|
||||
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
|
||||
|
||||
if(!frequency) return
|
||||
|
||||
|
||||
|
||||
var/datum/signal/signal = new()
|
||||
signal.source = src
|
||||
signal.transmission_method = 1
|
||||
//for(var/key in keyval)
|
||||
// signal.data[key] = keyval[key]
|
||||
signal.data = keyval
|
||||
//world << "sent [key],[keyval[key]] on [freq]"
|
||||
if (signal.data["findbeacon"])
|
||||
frequency.post_signal(src, signal, filter = RADIO_NAVBEACONS)
|
||||
else if (signal.data["type"] == "mulebot")
|
||||
frequency.post_signal(src, signal, filter = RADIO_MULEBOT)
|
||||
else
|
||||
frequency.post_signal(src, signal)
|
||||
|
||||
// signals bot status etc. to controller
|
||||
/obj/machinery/bot/mulebot/proc/send_status()
|
||||
var/list/kv = list(
|
||||
"type" = "mulebot",
|
||||
"name" = suffix,
|
||||
"loca" = (loc ? loc.loc : "Unknown"), // somehow loc can be null and cause a runtime - Quarxink
|
||||
"mode" = mode,
|
||||
"powr" = (cell ? cell.percent() : 0),
|
||||
"dest" = destination,
|
||||
"home" = home_destination,
|
||||
"load" = load,
|
||||
"retn" = auto_return,
|
||||
"pick" = auto_pickup,
|
||||
)
|
||||
post_signal_multiple(control_freq, kv)
|
||||
|
||||
/obj/machinery/bot/mulebot/emp_act(severity)
|
||||
if (cell)
|
||||
cell.emp_act(severity)
|
||||
if(load)
|
||||
load.emp_act(severity)
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/bot/mulebot/explode()
|
||||
src.visible_message("<span class='danger'>[src] blows apart!</span>", 1)
|
||||
var/turf/Tsec = get_turf(src)
|
||||
|
||||
new /obj/item/device/assembly/prox_sensor(Tsec)
|
||||
PoolOrNew(/obj/item/stack/rods, Tsec)
|
||||
PoolOrNew(/obj/item/stack/rods, Tsec)
|
||||
new /obj/item/stack/cable_coil/cut(Tsec)
|
||||
if (cell)
|
||||
cell.loc = Tsec
|
||||
cell.update_icon()
|
||||
cell = null
|
||||
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
new /obj/effect/decal/cleanable/blood/oil(src.loc)
|
||||
unload(0)
|
||||
qdel(src)
|
||||
@@ -41,13 +41,13 @@
|
||||
|
||||
if(scan)
|
||||
usr << "You remove \the [scan] from \the [src]."
|
||||
scan.loc = get_turf(src)
|
||||
scan.forceMove(get_turf(src))
|
||||
if(!usr.get_active_hand() && istype(usr,/mob/living/carbon/human))
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
else if(modify)
|
||||
usr << "You remove \the [modify] from \the [src]."
|
||||
modify.loc = get_turf(src)
|
||||
modify.forceMove(get_turf(src))
|
||||
if(!usr.get_active_hand() && istype(usr,/mob/living/carbon/human))
|
||||
usr.put_in_hands(modify)
|
||||
modify = null
|
||||
@@ -60,10 +60,12 @@
|
||||
return ..()
|
||||
|
||||
if(!scan && (access_change_ids in id_card.access) && user.unEquip(id_card))
|
||||
id_card.loc = src
|
||||
user.drop_item()
|
||||
id_card.forceMove(src)
|
||||
scan = id_card
|
||||
else if(!modify)
|
||||
id_card.loc = src
|
||||
user.drop_item()
|
||||
id_card.forceMove(src)
|
||||
modify = id_card
|
||||
|
||||
nanomanager.update_uis(src)
|
||||
@@ -146,34 +148,34 @@
|
||||
data_core.manifest_modify(modify.registered_name, modify.assignment)
|
||||
modify.name = text("[modify.registered_name]'s ID Card ([modify.assignment])")
|
||||
if(ishuman(usr))
|
||||
modify.loc = usr.loc
|
||||
modify.forceMove(get_turf(src))
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_hands(modify)
|
||||
modify = null
|
||||
else
|
||||
modify.loc = loc
|
||||
modify.forceMove(get_turf(src))
|
||||
modify = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
|
||||
I.loc = src
|
||||
I.forceMove(src)
|
||||
modify = I
|
||||
|
||||
if ("scan")
|
||||
if (scan)
|
||||
if(ishuman(usr))
|
||||
scan.loc = usr.loc
|
||||
scan.forceMove(get_turf(src))
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
else
|
||||
scan.loc = src.loc
|
||||
scan.forceMove(get_turf(src))
|
||||
scan = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
I.forceMove(src)
|
||||
scan = I
|
||||
|
||||
if("access")
|
||||
|
||||
@@ -103,13 +103,6 @@
|
||||
bumpopen(M)
|
||||
return
|
||||
|
||||
if(istype(AM, /obj/machinery/bot))
|
||||
var/obj/machinery/bot/bot = AM
|
||||
if(src.check_access(bot.botcard))
|
||||
if(density)
|
||||
open()
|
||||
return
|
||||
|
||||
if(istype(AM, /mob/living/bot))
|
||||
var/mob/living/bot/bot = AM
|
||||
if(src.check_access(bot.botcard))
|
||||
|
||||
@@ -502,7 +502,7 @@ var/list/turret_icons
|
||||
if(isanimal(L) || issmall(L)) // Animals are not so dangerous
|
||||
return check_anomalies ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET
|
||||
|
||||
if(isxenomorph(L) || isalien(L)) // Xenos are dangerous
|
||||
if(isalien(L)) // Xenos are dangerous
|
||||
return check_anomalies ? TURRET_PRIORITY_TARGET : TURRET_NOT_TARGET
|
||||
|
||||
if(ishuman(L)) //if the target is a human, analyze threat level
|
||||
|
||||
@@ -1,440 +0,0 @@
|
||||
/* Alien Effects!
|
||||
* Contains:
|
||||
* effect/alien
|
||||
* Resin
|
||||
* Weeds
|
||||
* Acid
|
||||
* Egg
|
||||
*/
|
||||
|
||||
/*
|
||||
* effect/alien
|
||||
*/
|
||||
/obj/effect/alien
|
||||
name = "alien thing"
|
||||
desc = "theres something alien about this"
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
|
||||
/*
|
||||
* Resin
|
||||
*/
|
||||
/obj/effect/alien/resin
|
||||
name = "resin"
|
||||
desc = "Looks like some kind of slimy growth."
|
||||
icon_state = "resin"
|
||||
|
||||
density = 1
|
||||
opacity = 1
|
||||
anchored = 1
|
||||
var/health = 200
|
||||
//var/mob/living/affecting = null
|
||||
|
||||
/obj/effect/alien/resin/wall
|
||||
name = "resin wall"
|
||||
desc = "Purple slime solidified into a wall."
|
||||
icon_state = "resinwall" //same as resin, but consistency ho!
|
||||
|
||||
/obj/effect/alien/resin/membrane
|
||||
name = "resin membrane"
|
||||
desc = "Purple slime just thin enough to let light pass through."
|
||||
icon_state = "resinmembrane"
|
||||
opacity = 0
|
||||
health = 120
|
||||
|
||||
/obj/effect/alien/resin/New()
|
||||
..()
|
||||
var/turf/T = get_turf(src)
|
||||
T.thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
|
||||
|
||||
/obj/effect/alien/resin/Destroy()
|
||||
var/turf/T = get_turf(src)
|
||||
T.thermal_conductivity = initial(T.thermal_conductivity)
|
||||
..()
|
||||
|
||||
/obj/effect/alien/resin/proc/healthcheck()
|
||||
if(health <=0)
|
||||
density = 0
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/alien/resin/bullet_act(var/obj/item/projectile/Proj)
|
||||
health -= Proj.damage
|
||||
..()
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
/obj/effect/alien/resin/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
health-=50
|
||||
if(2.0)
|
||||
health-=50
|
||||
if(3.0)
|
||||
if (prob(50))
|
||||
health-=50
|
||||
else
|
||||
health-=25
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
/obj/effect/alien/resin/hitby(AM as mob|obj)
|
||||
..()
|
||||
for(var/mob/O in viewers(src, null))
|
||||
O.show_message("<span class='danger'>[src] was hit by [AM].</span>", 1)
|
||||
var/tforce = 0
|
||||
if(ismob(AM))
|
||||
tforce = 10
|
||||
else
|
||||
tforce = AM:throwforce
|
||||
playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
|
||||
health = max(0, health - tforce)
|
||||
healthcheck()
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/effect/alien/resin/attack_hand()
|
||||
usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
if (HULK in usr.mutations)
|
||||
usr << "<span class='notice'>You easily destroy the [name].</span>"
|
||||
for(var/mob/O in oviewers(src))
|
||||
O.show_message("<span class='warning'>[usr] destroys the [name]!</span>", 1)
|
||||
health = 0
|
||||
else
|
||||
|
||||
// Aliens can get straight through these.
|
||||
if(istype(usr,/mob/living/carbon))
|
||||
var/mob/living/carbon/M = usr
|
||||
if(locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
|
||||
for(var/mob/O in oviewers(src))
|
||||
O.show_message("<span class='warning'>[usr] strokes the [name] and it melts away!</span>", 1)
|
||||
health = 0
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
usr << "<span class='notice'>You claw at the [name].</span>"
|
||||
for(var/mob/O in oviewers(src))
|
||||
O.show_message("<span class='warning'>[usr] claws at the [name]!</span>", 1)
|
||||
health -= rand(5,10)
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
/obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
var/aforce = W.force
|
||||
health = max(0, health - aforce)
|
||||
playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
|
||||
healthcheck()
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/effect/alien/resin/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group) return 0
|
||||
if(istype(mover) && mover.checkpass(PASSGLASS))
|
||||
return !opacity
|
||||
return !density
|
||||
|
||||
|
||||
/*
|
||||
* Weeds
|
||||
*/
|
||||
#define NODERANGE 3
|
||||
|
||||
/obj/effect/alien/weeds
|
||||
name = "weeds"
|
||||
desc = "Weird purple weeds."
|
||||
icon_state = "weeds"
|
||||
|
||||
anchored = 1
|
||||
density = 0
|
||||
layer = 2
|
||||
var/health = 15
|
||||
var/obj/effect/alien/weeds/node/linked_node = null
|
||||
|
||||
/obj/effect/alien/weeds/node
|
||||
icon_state = "weednode"
|
||||
name = "purple sac"
|
||||
desc = "Weird purple octopus-like thing."
|
||||
layer = 3
|
||||
light_range = NODERANGE
|
||||
var/node_range = NODERANGE
|
||||
|
||||
/obj/effect/alien/weeds/node/New()
|
||||
..(src.loc, src)
|
||||
|
||||
|
||||
/obj/effect/alien/weeds/New(pos, node)
|
||||
..()
|
||||
if(istype(loc, /turf/space))
|
||||
qdel(src)
|
||||
return
|
||||
linked_node = node
|
||||
if(icon_state == "weeds")icon_state = pick("weeds", "weeds1", "weeds2")
|
||||
spawn(rand(150, 200))
|
||||
if(src)
|
||||
Life()
|
||||
return
|
||||
|
||||
/obj/effect/alien/weeds/proc/Life()
|
||||
set background = 1
|
||||
var/turf/U = get_turf(src)
|
||||
/*
|
||||
if (locate(/obj/movable, U))
|
||||
U = locate(/obj/movable, U)
|
||||
if(U.density == 1)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
Alien plants should do something if theres a lot of poison
|
||||
if(U.poison> 200000)
|
||||
health -= round(U.poison/200000)
|
||||
update()
|
||||
return
|
||||
*/
|
||||
if (istype(U, /turf/space))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(!linked_node || (get_dist(linked_node, src) > linked_node.node_range) )
|
||||
return
|
||||
|
||||
direction_loop:
|
||||
for(var/dirn in cardinal)
|
||||
var/turf/T = get_step(src, dirn)
|
||||
|
||||
if (!istype(T) || T.density || locate(/obj/effect/alien/weeds) in T || istype(T.loc, /area/arrival) || istype(T, /turf/space))
|
||||
continue
|
||||
|
||||
// if (locate(/obj/movable, T)) // don't propogate into movables
|
||||
// continue
|
||||
|
||||
for(var/obj/O in T)
|
||||
if(O.density)
|
||||
continue direction_loop
|
||||
|
||||
PoolOrNew(/obj/effect/alien/weeds, T, linked_node)
|
||||
|
||||
|
||||
/obj/effect/alien/weeds/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
qdel(src)
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
qdel(src)
|
||||
if(3.0)
|
||||
if (prob(5))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
if(W.attack_verb.len)
|
||||
visible_message("<span class='danger'>\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>\The [src] have been attacked with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
|
||||
var/damage = W.force / 4.0
|
||||
|
||||
if(istype(W, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
|
||||
if(WT.remove_fuel(0, user))
|
||||
damage = 15
|
||||
playsound(loc, 'sound/items/Welder.ogg', 100, 1)
|
||||
|
||||
health -= damage
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/alien/weeds/proc/healthcheck()
|
||||
if(health <= 0)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/effect/alien/weeds/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > 300 + T0C)
|
||||
health -= 5
|
||||
healthcheck()
|
||||
|
||||
#undef NODERANGE
|
||||
|
||||
|
||||
/*
|
||||
* Acid
|
||||
*/
|
||||
/obj/effect/alien/acid
|
||||
name = "acid"
|
||||
desc = "Burbling corrossive stuff. I wouldn't want to touch it."
|
||||
icon_state = "acid"
|
||||
|
||||
density = 0
|
||||
opacity = 0
|
||||
anchored = 1
|
||||
|
||||
var/atom/target
|
||||
var/ticks = 0
|
||||
var/target_strength = 0
|
||||
|
||||
/obj/effect/alien/acid/New(loc, target)
|
||||
..(loc)
|
||||
src.target = target
|
||||
|
||||
if(isturf(target)) // Turf take twice as long to take down.
|
||||
target_strength = 8
|
||||
else
|
||||
target_strength = 4
|
||||
tick()
|
||||
|
||||
/obj/effect/alien/acid/proc/tick()
|
||||
if(!target)
|
||||
qdel(src)
|
||||
|
||||
ticks += 1
|
||||
|
||||
if(ticks >= target_strength)
|
||||
|
||||
for(var/mob/O in hearers(src, null))
|
||||
O.show_message("<span class='alium'>[src.target] collapses under its own weight into a puddle of goop and undigested debris!</span>", 1)
|
||||
|
||||
if(istype(target, /turf/simulated/wall)) // I hate turf code.
|
||||
var/turf/simulated/wall/W = target
|
||||
W.dismantle_wall(1)
|
||||
else
|
||||
qdel(target)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
switch(target_strength - ticks)
|
||||
if(6)
|
||||
visible_message("<span class='alium'>[src.target] is holding up against the acid!</span>")
|
||||
if(4)
|
||||
visible_message("<span class='alium'>[src.target]\s structure is being melted by the acid!</span>")
|
||||
if(2)
|
||||
visible_message("<span class='alium'>[src.target] is struggling to withstand the acid!</span>")
|
||||
if(0 to 1)
|
||||
visible_message("<span class='alium'>[src.target] begins to crumble under the acid!</span>")
|
||||
spawn(rand(150, 200)) tick()
|
||||
|
||||
/*
|
||||
* Egg
|
||||
*/
|
||||
/var/const //for the status var
|
||||
BURST = 0
|
||||
BURSTING = 1
|
||||
GROWING = 2
|
||||
GROWN = 3
|
||||
|
||||
MIN_GROWTH_TIME = 1800 //time it takes to grow a hugger
|
||||
MAX_GROWTH_TIME = 3000
|
||||
|
||||
/obj/effect/alien/egg
|
||||
desc = "It looks like a weird egg"
|
||||
name = "egg"
|
||||
icon_state = "egg_growing"
|
||||
density = 0
|
||||
anchored = 1
|
||||
|
||||
var/health = 100
|
||||
var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive
|
||||
flags = PROXMOVE
|
||||
|
||||
/obj/effect/alien/egg/New()
|
||||
if(config.aliens_allowed)
|
||||
..()
|
||||
spawn(rand(MIN_GROWTH_TIME,MAX_GROWTH_TIME))
|
||||
Grow()
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/alien/egg/attack_hand(user as mob)
|
||||
|
||||
var/mob/living/carbon/M = user
|
||||
if(!istype(M) || !(locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs))
|
||||
return attack_hand(user)
|
||||
|
||||
switch(status)
|
||||
if(BURST)
|
||||
user << "<span class='warning'>You clear the hatched egg.</span>"
|
||||
qdel(src)
|
||||
return
|
||||
if(GROWING)
|
||||
user << "<span class='warning'>The child is not developed yet.</span>"
|
||||
return
|
||||
if(GROWN)
|
||||
user << "<span class='warning'>You retrieve the child.</span>"
|
||||
Burst(0)
|
||||
return
|
||||
|
||||
/obj/effect/alien/egg/proc/GetFacehugger()
|
||||
return locate(/obj/item/clothing/mask/facehugger) in contents
|
||||
|
||||
/obj/effect/alien/egg/proc/Grow()
|
||||
icon_state = "egg"
|
||||
status = GROWN
|
||||
new /obj/item/clothing/mask/facehugger(src)
|
||||
return
|
||||
|
||||
/obj/effect/alien/egg/proc/Burst(var/kill = 1) //drops and kills the hugger if any is remaining
|
||||
if(status == GROWN || status == GROWING)
|
||||
var/obj/item/clothing/mask/facehugger/child = GetFacehugger()
|
||||
icon_state = "egg_hatched"
|
||||
flick("egg_opening", src)
|
||||
status = BURSTING
|
||||
spawn(15)
|
||||
status = BURST
|
||||
child.loc = get_turf(src)
|
||||
|
||||
if(kill && istype(child))
|
||||
child.Die()
|
||||
else
|
||||
for(var/mob/M in range(1,src))
|
||||
if(CanHug(M))
|
||||
child.Attach(M)
|
||||
break
|
||||
|
||||
/obj/effect/alien/egg/bullet_act(var/obj/item/projectile/Proj)
|
||||
health -= Proj.damage
|
||||
..()
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
|
||||
/obj/effect/alien/egg/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
if(health <= 0)
|
||||
return
|
||||
if(W.attack_verb.len)
|
||||
src.visible_message("<span class='danger'>\The [src] has been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
else
|
||||
src.visible_message("<span class='danger'>\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
var/damage = W.force / 4.0
|
||||
|
||||
if(istype(W, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
|
||||
if(WT.remove_fuel(0, user))
|
||||
damage = 15
|
||||
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
|
||||
|
||||
src.health -= damage
|
||||
src.healthcheck()
|
||||
|
||||
|
||||
/obj/effect/alien/egg/proc/healthcheck()
|
||||
if(health <= 0)
|
||||
Burst()
|
||||
|
||||
/obj/effect/alien/egg/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > 500 + T0C)
|
||||
health -= 5
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/alien/egg/HasProximity(atom/movable/AM as mob|obj)
|
||||
if(status == GROWN)
|
||||
if(!CanHug(AM))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = AM
|
||||
if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST)
|
||||
return
|
||||
|
||||
Burst(0)
|
||||
@@ -424,8 +424,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
cartdata["radio"] = 1
|
||||
if(istype(cartridge.radio, /obj/item/radio/integrated/signal))
|
||||
cartdata["radio"] = 2
|
||||
if(istype(cartridge.radio, /obj/item/radio/integrated/mule))
|
||||
cartdata["radio"] = 3
|
||||
//if(istype(cartridge.radio, /obj/item/radio/integrated/mule))
|
||||
// cartdata["radio"] = 3
|
||||
|
||||
if(mode == 2)
|
||||
cartdata["charges"] = cartridge.charges ? cartridge.charges : 0
|
||||
|
||||
@@ -124,10 +124,6 @@
|
||||
icon_state = "cart-q"
|
||||
access_quartermaster = 1
|
||||
|
||||
/obj/item/weapon/cartridge/quartermaster/initialize()
|
||||
radio = new /obj/item/radio/integrated/mule(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/head
|
||||
name = "\improper Easy-Record DELUXE"
|
||||
icon_state = "cart-h"
|
||||
@@ -141,9 +137,6 @@
|
||||
access_janitor = 1
|
||||
access_security = 1
|
||||
|
||||
/obj/item/weapon/cartridge/hop/initialize()
|
||||
radio = new /obj/item/radio/integrated/mule(src)
|
||||
|
||||
/obj/item/weapon/cartridge/hos
|
||||
name = "\improper R.O.B.U.S.T. DELUXE"
|
||||
icon_state = "cart-hos"
|
||||
@@ -351,40 +344,26 @@
|
||||
/* MULEBOT Control (Mode: 48) */
|
||||
|
||||
if(mode==48)
|
||||
var/muleData[0]
|
||||
var/mulebotsData[0]
|
||||
if(istype(radio,/obj/item/radio/integrated/mule))
|
||||
var/obj/item/radio/integrated/mule/QC = radio
|
||||
muleData["active"] = QC.active
|
||||
if(QC.active && !isnull(QC.botstatus))
|
||||
var/area/loca = QC.botstatus["loca"]
|
||||
var/loca_name = sanitize(loca.name)
|
||||
muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"]))
|
||||
var/count = 0
|
||||
|
||||
else
|
||||
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
|
||||
for(var/mob/living/bot/mulebot/M in living_mob_list)
|
||||
if(!M.on)
|
||||
continue
|
||||
++count
|
||||
var/muleData[0]
|
||||
muleData["name"] = M.suffix
|
||||
muleData["location"] = get_area(M)
|
||||
muleData["mode"] = M.mode
|
||||
muleData["home"] = M.homeName
|
||||
muleData["target"] = M.targetName
|
||||
muleData["ref"] = "\ref[M]"
|
||||
muleData["load"] = M.load ? M.load.name : "Nothing"
|
||||
|
||||
mulebotsData[++mulebotsData.len] = muleData.Copy()
|
||||
|
||||
|
||||
var/mulebotsCount=0
|
||||
for(var/obj/machinery/bot/B in QC.botlist)
|
||||
mulebotsCount++
|
||||
if(B.loc)
|
||||
mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
|
||||
|
||||
if(!mulebotsData.len)
|
||||
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
|
||||
|
||||
muleData["bots"] = mulebotsData
|
||||
muleData["count"] = mulebotsCount
|
||||
|
||||
else
|
||||
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
|
||||
muleData["active"] = 0
|
||||
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
|
||||
muleData["bots"] = mulebotsData
|
||||
muleData["count"] = 0
|
||||
|
||||
values["mulebot"] = muleData
|
||||
values["mulebotcount"] = count
|
||||
values["mulebots"] = mulebotsData
|
||||
|
||||
|
||||
|
||||
@@ -575,5 +554,9 @@
|
||||
loc:mode = 43
|
||||
mode = 43
|
||||
|
||||
if("MULEbot")
|
||||
var/mob/living/bot/mulebot/M = locate(href_list["ref"])
|
||||
if(istype(M))
|
||||
M.obeyCommand(href_list["command"])
|
||||
|
||||
return 1
|
||||
|
||||
@@ -105,107 +105,6 @@
|
||||
radio_controller.remove_object(src, control_freq)
|
||||
..()
|
||||
|
||||
/obj/item/radio/integrated/mule
|
||||
var/list/botlist = null // list of bots
|
||||
var/obj/machinery/bot/mulebot/active // the active bot; if null, show bot list
|
||||
var/list/botstatus // the status signal sent by the bot
|
||||
var/list/beacons
|
||||
|
||||
var/beacon_freq = 1400
|
||||
var/control_freq = BOT_FREQ
|
||||
|
||||
// create a new QM cartridge, and register to receive bot control & beacon message
|
||||
New()
|
||||
..()
|
||||
spawn(5)
|
||||
if(radio_controller)
|
||||
radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT)
|
||||
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
|
||||
spawn(10)
|
||||
post_signal(beacon_freq, "findbeacon", "delivery", s_filter = RADIO_NAVBEACONS)
|
||||
|
||||
// receive radio signals
|
||||
// can detect bot status signals
|
||||
// and beacon locations
|
||||
// create/populate lists as they are recvd
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
// var/obj/item/device/pda/P = src.loc
|
||||
|
||||
/*
|
||||
world << "recvd:[P] : [signal.source]"
|
||||
for(var/d in signal.data)
|
||||
world << "- [d] = [signal.data[d]]"
|
||||
*/
|
||||
if(signal.data["type"] == "mulebot")
|
||||
if(!botlist)
|
||||
botlist = new()
|
||||
|
||||
if(!(signal.source in botlist))
|
||||
botlist += signal.source
|
||||
|
||||
if(active == signal.source)
|
||||
var/list/b = signal.data
|
||||
botstatus = b.Copy()
|
||||
|
||||
else if(signal.data["beacon"])
|
||||
if(!beacons)
|
||||
beacons = new()
|
||||
|
||||
beacons[signal.data["beacon"] ] = signal.source
|
||||
|
||||
|
||||
// if(istype(P)) P.updateSelfDialog()
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
var/cmd = "command"
|
||||
if(active) cmd = "command [active.suffix]"
|
||||
|
||||
switch(href_list["op"])
|
||||
|
||||
if("control")
|
||||
active = locate(href_list["bot"])
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("scanbots") // find all bots
|
||||
botlist = null
|
||||
post_signal(control_freq, "command", "bot_status", s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("botlist")
|
||||
active = null
|
||||
|
||||
|
||||
if("unload")
|
||||
post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
if("setdest")
|
||||
if(beacons)
|
||||
var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons
|
||||
if(dest)
|
||||
post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("retoff")
|
||||
post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
if("reton")
|
||||
post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("pickoff")
|
||||
post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
if("pickon")
|
||||
post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("stop", "go", "home")
|
||||
post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Radio Cartridge, essentially a signaler.
|
||||
*/
|
||||
|
||||
@@ -56,12 +56,6 @@
|
||||
new /obj/item/clothing/mask/breath( src )
|
||||
new /obj/item/weapon/tank/emergency_oxygen( src )
|
||||
|
||||
/obj/item/weapon/storage/box/vox/
|
||||
New()
|
||||
..()
|
||||
new /obj/item/clothing/mask/breath( src )
|
||||
new /obj/item/weapon/tank/emergency_nitrogen( src )
|
||||
|
||||
/obj/item/weapon/storage/box/engineer/
|
||||
New()
|
||||
..()
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
name = "surgery kit"
|
||||
desc = "Contains tools for surgery."
|
||||
storage_slots = 10
|
||||
max_storage_space = 23
|
||||
|
||||
/obj/item/weapon/storage/firstaid/surgery/New()
|
||||
..()
|
||||
@@ -302,4 +303,4 @@
|
||||
new /obj/item/weapon/reagent_containers/pill/citalopram( src )
|
||||
new /obj/item/weapon/reagent_containers/pill/citalopram( src )
|
||||
new /obj/item/weapon/reagent_containers/pill/citalopram( src )
|
||||
new /obj/item/weapon/reagent_containers/pill/citalopram( src )
|
||||
new /obj/item/weapon/reagent_containers/pill/citalopram( src )
|
||||
|
||||
@@ -148,31 +148,6 @@
|
||||
gauge_icon = "indicator_emergency_double"
|
||||
volume = 10
|
||||
|
||||
/obj/item/weapon/tank/emergency_nitrogen
|
||||
name = "emergency nitrogen tank"
|
||||
desc = "An emergency air tank hastily painted red and issued to Vox crewmembers."
|
||||
icon_state = "emergency_nitro"
|
||||
gauge_icon = "indicator_emergency"
|
||||
gauge_cap = 4
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = 2.0
|
||||
force = 4.0
|
||||
distribute_pressure = ONE_ATMOSPHERE*O2STANDARD
|
||||
volume = 2
|
||||
|
||||
New()
|
||||
..()
|
||||
src.air_contents.adjust_gas("nitrogen", (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
|
||||
|
||||
return
|
||||
|
||||
|
||||
examine(mob/user)
|
||||
if(..(user, 0) && air_contents.gas["nitrogen"] < 0.2 && loc==user)
|
||||
user << text("<span class='danger'>The meter on \the [src] indicates you are almost out of air!</span>")
|
||||
user << sound('sound/effects/alert.ogg')
|
||||
|
||||
/*
|
||||
* Nitrogen
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
for(var/i = 1;i<=held_count;i++)
|
||||
new held_type(src)
|
||||
|
||||
/obj/structure/largecrate/animal/mulebot
|
||||
name = "Mulebot crate"
|
||||
held_type = /mob/living/bot/mulebot
|
||||
|
||||
/obj/structure/largecrate/animal/corgi
|
||||
name = "corgi carrier"
|
||||
held_type = /mob/living/simple_animal/corgi
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/obj/structure/lamarr
|
||||
name = "lab cage"
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "labcage1"
|
||||
desc = "A glass lab container for storing interesting creatures."
|
||||
density = 1
|
||||
anchored = 1
|
||||
unacidable = 1//Dissolving the case would also delete Lamarr
|
||||
var/health = 30
|
||||
var/occupied = 1
|
||||
var/destroyed = 0
|
||||
|
||||
/obj/structure/lamarr/ex_act(severity)
|
||||
switch(severity)
|
||||
if (1)
|
||||
new /obj/item/weapon/material/shard( src.loc )
|
||||
Break()
|
||||
qdel(src)
|
||||
if (2)
|
||||
if (prob(50))
|
||||
src.health -= 15
|
||||
src.healthcheck()
|
||||
if (3)
|
||||
if (prob(50))
|
||||
src.health -= 5
|
||||
src.healthcheck()
|
||||
|
||||
|
||||
/obj/structure/lamarr/bullet_act(var/obj/item/projectile/Proj)
|
||||
health -= Proj.damage
|
||||
..()
|
||||
src.healthcheck()
|
||||
return
|
||||
|
||||
/obj/structure/lamarr/proc/healthcheck()
|
||||
if (src.health <= 0)
|
||||
if (!( src.destroyed ))
|
||||
src.density = 0
|
||||
src.destroyed = 1
|
||||
new /obj/item/weapon/material/shard( src.loc )
|
||||
playsound(src, "shatter", 70, 1)
|
||||
Break()
|
||||
else
|
||||
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
|
||||
return
|
||||
|
||||
/obj/structure/lamarr/update_icon()
|
||||
if(src.destroyed)
|
||||
src.icon_state = "labcageb[src.occupied]"
|
||||
else
|
||||
src.icon_state = "labcage[src.occupied]"
|
||||
return
|
||||
|
||||
|
||||
/obj/structure/lamarr/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
src.health -= W.force
|
||||
src.healthcheck()
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/structure/lamarr/attack_hand(mob/user as mob)
|
||||
if (src.destroyed)
|
||||
return
|
||||
else
|
||||
usr << "<span class='notice'>You kick the lab cage.</span>"
|
||||
for(var/mob/O in oviewers())
|
||||
if ((O.client && !( O.blinded )))
|
||||
O << "<span class='warning'>[usr] kicks the lab cage.</span>"
|
||||
src.health -= 2
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
/obj/structure/lamarr/proc/Break()
|
||||
if(occupied)
|
||||
new /obj/item/clothing/mask/facehugger/lamarr(src.loc)
|
||||
occupied = 0
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/lamarr
|
||||
name = "Lamarr"
|
||||
desc = "The worst she might do is attempt to... couple with your head."//hope we don't get sued over a harmless reference, rite?
|
||||
sterile = 1
|
||||
gender = FEMALE
|
||||
|
||||
/obj/item/clothing/mask/facehugger/lamarr/New()//to prevent deleting it if aliums are disabled
|
||||
return
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
|
||||
/obj/structure/mirror/bullet_act(var/obj/item/projectile/Proj)
|
||||
|
||||
|
||||
if(prob(Proj.get_structure_damage() * 2))
|
||||
if(!shattered)
|
||||
shatter()
|
||||
@@ -63,31 +63,3 @@
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user] hits [src] and bounces off!</span>")
|
||||
return 1
|
||||
|
||||
// The following mirror is ~special~.
|
||||
/obj/structure/mirror/raider
|
||||
name = "cracked mirror"
|
||||
desc = "Something seems strange about this old, dirty mirror. Your reflection doesn't look like you remember it."
|
||||
icon_state = "mirror_broke"
|
||||
shattered = 1
|
||||
|
||||
/obj/structure/mirror/raider/attack_hand(var/mob/living/carbon/human/user)
|
||||
if(istype(get_area(src),/area/syndicate_mothership))
|
||||
if(istype(user) && user.mind && user.mind.special_role == "Raider" && user.species.name != "Vox" && is_alien_whitelisted(user, "Vox"))
|
||||
var/choice = input("Do you wish to become a true Vox of the Shoal? This is not reversible.") as null|anything in list("No","Yes")
|
||||
if(choice && choice == "Yes")
|
||||
var/mob/living/carbon/human/vox/vox = new(get_turf(src),"Vox")
|
||||
vox.gender = user.gender
|
||||
raiders.equip(vox)
|
||||
if(user.mind)
|
||||
user.mind.transfer_to(vox)
|
||||
spawn(1)
|
||||
var/newname = sanitizeSafe(input(vox,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN)
|
||||
if(!newname || newname == "")
|
||||
var/datum/language/L = all_languages[vox.species.default_language]
|
||||
newname = L.get_random_name()
|
||||
vox.real_name = newname
|
||||
vox.name = vox.real_name
|
||||
raiders.update_access(vox)
|
||||
qdel(user)
|
||||
..()
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
//Alium nests. Essentially beds with an unbuckle delay that only aliums can buckle mobs to.
|
||||
#define NEST_RESIST_TIME 1200
|
||||
|
||||
/obj/structure/bed/nest
|
||||
name = "alien nest"
|
||||
desc = "It's a gruesome pile of thick, sticky resin shaped like a nest."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "nest"
|
||||
var/health = 100
|
||||
|
||||
/obj/structure/bed/nest/update_icon()
|
||||
return
|
||||
|
||||
/obj/structure/bed/nest/user_unbuckle_mob(mob/user as mob)
|
||||
if(buckled_mob)
|
||||
if(buckled_mob.buckled == src)
|
||||
if(buckled_mob != user)
|
||||
buckled_mob.visible_message(\
|
||||
"<span class='notice'>[user.name] pulls [buckled_mob.name] free from the sticky nest!</span>",\
|
||||
"<span class='notice'>[user.name] pulls you free from the gelatinous resin.</span>",\
|
||||
"<span class='notice'>You hear squelching...</span>")
|
||||
buckled_mob.pixel_y = 0
|
||||
buckled_mob.old_y = 0
|
||||
unbuckle_mob()
|
||||
else
|
||||
if(world.time <= buckled_mob.last_special+NEST_RESIST_TIME)
|
||||
return
|
||||
buckled_mob.last_special = world.time
|
||||
buckled_mob.visible_message(\
|
||||
"<span class='warning'>[buckled_mob.name] struggles to break free of the gelatinous resin...</span>",\
|
||||
"<span class='warning'>You struggle to break free from the gelatinous resin...</span>",\
|
||||
"<span class='notice'>You hear squelching...</span>")
|
||||
spawn(NEST_RESIST_TIME)
|
||||
if(user && buckled_mob && user.buckled == src)
|
||||
buckled_mob.last_special = world.time
|
||||
buckled_mob.pixel_y = 0
|
||||
buckled_mob.old_y = 0
|
||||
unbuckle_mob()
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/structure/bed/nest/user_buckle_mob(mob/M as mob, mob/user as mob)
|
||||
if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || usr.stat || M.buckled || istype(user, /mob/living/silicon/pai) )
|
||||
return
|
||||
|
||||
unbuckle_mob()
|
||||
|
||||
var/mob/living/carbon/xenos = user
|
||||
var/mob/living/carbon/victim = M
|
||||
|
||||
if(istype(victim) && locate(/obj/item/organ/internal/xenos/hivenode) in victim.internal_organs)
|
||||
return
|
||||
|
||||
if(istype(xenos) && !(locate(/obj/item/organ/internal/xenos/hivenode) in xenos.internal_organs))
|
||||
return
|
||||
|
||||
if(M == usr)
|
||||
return
|
||||
else
|
||||
M.visible_message(\
|
||||
"<span class='notice'>[user.name] secretes a thick vile goo, securing [M.name] into [src]!</span>",\
|
||||
"<span class='warning'>[user.name] drenches you in a foul-smelling resin, trapping you in the [src]!</span>",\
|
||||
"<span class='notice'>You hear squelching...</span>")
|
||||
M.buckled = src
|
||||
M.loc = src.loc
|
||||
M.set_dir(src.dir)
|
||||
M.update_canmove()
|
||||
M.pixel_y = 6
|
||||
M.old_y = 6
|
||||
src.buckled_mob = M
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/structure/bed/nest/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
var/aforce = W.force
|
||||
health = max(0, health - aforce)
|
||||
playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
|
||||
for(var/mob/M in viewers(src, 7))
|
||||
M.show_message("<span class='warning'>[user] hits [src] with [W]!</span>", 1)
|
||||
healthcheck()
|
||||
|
||||
/obj/structure/bed/nest/proc/healthcheck()
|
||||
if(health <=0)
|
||||
density = 0
|
||||
qdel(src)
|
||||
return
|
||||
@@ -49,6 +49,7 @@ var/list/mechtoys = list(
|
||||
layer = 4
|
||||
explosion_resistance = 5
|
||||
var/list/mobs_can_pass = list(
|
||||
/mob/living/bot,
|
||||
/mob/living/carbon/slime,
|
||||
/mob/living/simple_animal/mouse,
|
||||
/mob/living/silicon/robot/drone
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "plating"
|
||||
|
||||
/turf/simulated/shuttle/plating/vox //Skipjack plating
|
||||
/turf/simulated/shuttle/plating/skipjack //Skipjack plating
|
||||
oxygen = 0
|
||||
nitrogen = MOLES_N2STANDARD + MOLES_O2STANDARD
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
name = "Brig floor" // Also added it into the 2x3 brig area of the shuttle.
|
||||
icon_state = "floor4"
|
||||
|
||||
/turf/simulated/shuttle/floor4/vox //skipjack floors
|
||||
/turf/simulated/shuttle/floor4/skipjack //skipjack floors
|
||||
name = "skipjack floor"
|
||||
oxygen = 0
|
||||
nitrogen = MOLES_N2STANDARD + MOLES_O2STANDARD
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
..(newloc,"sandstone","diamond")
|
||||
|
||||
// Kind of wondering if this is going to bite me in the butt.
|
||||
/turf/simulated/wall/voxshuttle/New(var/newloc)
|
||||
..(newloc,"voxalloy")
|
||||
/turf/simulated/wall/voxshuttle/attackby()
|
||||
/turf/simulated/wall/skipjack/New(var/newloc)
|
||||
..(newloc,"alienalloy")
|
||||
/turf/simulated/wall/skipjack/attackby()
|
||||
return
|
||||
/turf/simulated/wall/titanium/New(var/newloc)
|
||||
..(newloc,"titanium")
|
||||
|
||||
@@ -86,7 +86,10 @@
|
||||
msg += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
msg += " (AFK)"
|
||||
var/seconds = C.last_activity_seconds()
|
||||
msg += " (AFK - "
|
||||
msg += "[round(seconds / 60)] minutes, "
|
||||
msg += "[seconds % 60] seconds)"
|
||||
msg += "\n"
|
||||
|
||||
num_admins_online++
|
||||
@@ -101,7 +104,10 @@
|
||||
modmsg += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
modmsg += " (AFK)"
|
||||
var/seconds = C.last_activity_seconds()
|
||||
modmsg += " (AFK - "
|
||||
modmsg += "[round(seconds / 60)] minutes, "
|
||||
modmsg += "[seconds % 60] seconds)"
|
||||
modmsg += "\n"
|
||||
num_mods_online++
|
||||
|
||||
@@ -115,7 +121,10 @@
|
||||
mentmsg += " - Playing"
|
||||
|
||||
if(C.is_afk())
|
||||
mentmsg += " (AFK)"
|
||||
var/seconds = C.last_activity_seconds()
|
||||
mentmsg += " (AFK - "
|
||||
mentmsg += "[round(seconds / 60)] minutes, "
|
||||
mentmsg += "[seconds % 60] seconds)"
|
||||
mentmsg += "\n"
|
||||
num_mentors_online++
|
||||
|
||||
|
||||
@@ -145,16 +145,10 @@ proc/admin_notice(var/message, var/rights)
|
||||
body += {"<br><br>
|
||||
<b>Rudimentary transformation:</b><font size=2><br>These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.</font><br>
|
||||
<A href='?src=\ref[src];simplemake=observer;mob=\ref[M]'>Observer</A> |
|
||||
\[ Xenos: <A href='?src=\ref[src];simplemake=larva;mob=\ref[M]'>Larva</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Drone;mob=\ref[M]'>Drone</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Hunter;mob=\ref[M]'>Hunter</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Sentinel;mob=\ref[M]'>Sentinel</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Xenomorph Queen;mob=\ref[M]'>Queen</A> \] |
|
||||
\[ Crew: <A href='?src=\ref[src];simplemake=human;mob=\ref[M]'>Human</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Unathi;mob=\ref[M]'>Unathi</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Tajaran;mob=\ref[M]'>Tajaran</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Skrell;mob=\ref[M]'>Skrell</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species=Vox;mob=\ref[M]'>Vox</A> \] | \[
|
||||
<A href='?src=\ref[src];simplemake=human;species=Skrell;mob=\ref[M]'>Skrell</A> \] | \[
|
||||
<A href='?src=\ref[src];simplemake=nymph;mob=\ref[M]'>Nymph</A>
|
||||
<A href='?src=\ref[src];simplemake=human;species='Diona';mob=\ref[M]'>Diona</A> \] |
|
||||
\[ slime: <A href='?src=\ref[src];simplemake=slime;mob=\ref[M]'>Baby</A>,
|
||||
@@ -1356,7 +1350,7 @@ proc/admin_notice(var/message, var/rights)
|
||||
message_admins(msg)
|
||||
else
|
||||
usr << "You do not have access to this command."
|
||||
|
||||
|
||||
/datum/admins/proc/add_tcrystals(mob/living/carbon/human/H as mob)
|
||||
set category = "Debug"
|
||||
set name = "Add Telecrystals"
|
||||
|
||||
@@ -822,7 +822,7 @@ var/list/admin_verbs_mentor = list(
|
||||
if(!istype(M, /mob/living/carbon/human))
|
||||
usr << "\red You can only do this to humans!"
|
||||
return
|
||||
switch(alert("Are you sure you wish to edit this mob's appearance? Skrell, Unathi, Vox and Tajaran can result in unintended consequences.",,"Yes","No"))
|
||||
switch(alert("Are you sure you wish to edit this mob's appearance? Skrell, Unathi, Tajaran can result in unintended consequences.",,"Yes","No"))
|
||||
if("No")
|
||||
return
|
||||
var/new_facial = input("Please select facial hair color.", "Character Generation") as color
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/datum/admin_secret_item/random_event/trigger_xenomorph_infestation
|
||||
name = "Trigger a Xenomorph Infestation"
|
||||
|
||||
/datum/admin_secret_item/random_event/trigger_xenomorph_infestation/execute(var/mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return xenomorphs.attempt_random_spawn()
|
||||
@@ -1119,16 +1119,6 @@
|
||||
log_admin("[key_name(usr)] AIized [key_name(H)]")
|
||||
H.AIize()
|
||||
|
||||
else if(href_list["makealien"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["makealien"])
|
||||
if(!istype(H))
|
||||
usr << "This can only be used on instances of type /mob/living/carbon/human"
|
||||
return
|
||||
|
||||
usr.client.cmd_admin_alienize(H)
|
||||
|
||||
else if(href_list["makeslime"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
|
||||
@@ -100,23 +100,6 @@
|
||||
paiController.pai_candidates.Remove(candidate)
|
||||
feedback_add_details("admin_verb","MPAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_alienize(var/mob/M in mob_list)
|
||||
set category = "Fun"
|
||||
set name = "Make Alien"
|
||||
|
||||
if(!ticker)
|
||||
alert("Wait until the game starts")
|
||||
return
|
||||
if(ishuman(M))
|
||||
log_admin("[key_name(src)] has alienized [M.key].")
|
||||
spawn(10)
|
||||
M:Alienize()
|
||||
feedback_add_details("admin_verb","MKAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] made [key_name(M)] into an alien.")
|
||||
message_admins("\blue [key_name_admin(usr)] made [key_name(M)] into an alien.", 1)
|
||||
else
|
||||
alert("Invalid mob")
|
||||
|
||||
/client/proc/cmd_admin_slimeize(var/mob/M in mob_list)
|
||||
set category = "Fun"
|
||||
set name = "Make slime"
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
<option value='?_src_=vars;makeai=\ref[src]'>Make AI</option>
|
||||
<option value='?_src_=vars;makerobot=\ref[src]'>Make cyborg</option>
|
||||
<option value='?_src_=vars;makemonkey=\ref[src]'>Make monkey</option>
|
||||
<option value='?_src_=vars;makealien=\ref[src]'>Make alien</option>
|
||||
<option value='?_src_=vars;makeslime=\ref[src]'>Make slime</option>
|
||||
"}
|
||||
|
||||
|
||||
@@ -90,10 +90,6 @@
|
||||
if(V)
|
||||
V.ex_act(2)
|
||||
return
|
||||
var/obj/machinery/bot/B = locate() in T
|
||||
if(B)
|
||||
B.ex_act(2)
|
||||
return
|
||||
var/obj/mecha/M = locate() in T
|
||||
if(M)
|
||||
M.visible_message("<span class='danger'>The blob attacks \the [M]!</span>")
|
||||
|
||||
@@ -281,6 +281,9 @@
|
||||
if(inactivity > duration) return inactivity
|
||||
return 0
|
||||
|
||||
/client/proc/last_activity_seconds()
|
||||
return inactivity / 10
|
||||
|
||||
//send resources to the client. It's here in its own proc so we can move it around easiliy if need be
|
||||
/client/proc/send_resources()
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
Sprites used when the clothing item is refit. This is done by setting icon_override.
|
||||
For best results, if this is set then sprite_sheets should be null and vice versa, but that is by no means necessary.
|
||||
Ideally, sprite_sheets_refit should be used for "hard" clothing items that can't change shape very well to fit the wearer (e.g. helmets, hardsuits),
|
||||
while sprite_sheets should be used for "flexible" clothing items that do not need to be refitted (e.g. vox wearing jumpsuits).
|
||||
while sprite_sheets should be used for "flexible" clothing items that do not need to be refitted (e.g. aliens wearing jumpsuits).
|
||||
*/
|
||||
var/list/sprite_sheets_refit = null
|
||||
var/ear_protection = 0
|
||||
@@ -204,9 +204,8 @@
|
||||
body_parts_covered = HANDS
|
||||
slot_flags = SLOT_GLOVES
|
||||
attack_verb = list("challenged")
|
||||
species_restricted = list("exclude","Unathi","Tajara", "Vox")
|
||||
species_restricted = list("exclude","Unathi","Tajara")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/gloves.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/gloves.dmi',
|
||||
)
|
||||
|
||||
@@ -264,7 +263,6 @@
|
||||
var/on = 0
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/head.dmi'
|
||||
)
|
||||
|
||||
@@ -363,7 +361,6 @@
|
||||
slot_flags = SLOT_MASK
|
||||
body_parts_covered = FACE|EYES
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/masks.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/masks.dmi',
|
||||
)
|
||||
|
||||
@@ -397,9 +394,8 @@
|
||||
slowdown = SHOES_SLOWDOWN
|
||||
force = 2
|
||||
var/overshoes = 0
|
||||
species_restricted = list("exclude","Teshari", "Unathi","Tajara","Vox")
|
||||
species_restricted = list("exclude","Teshari", "Unathi","Tajara")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/shoes.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/shoes.dmi',
|
||||
)
|
||||
|
||||
@@ -474,7 +470,6 @@
|
||||
w_class = 3
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/suit.dmi'
|
||||
)
|
||||
|
||||
@@ -511,7 +506,6 @@
|
||||
var/rolled_down = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled
|
||||
var/rolled_sleeves = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/uniform.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/uniform.dmi'
|
||||
)
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ BLIND // can't see anything
|
||||
var/obj/screen/overlay = null
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/eyes.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/eyes.dmi'
|
||||
)
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
desc = "an ultra rare hat. It commands a certain respect."
|
||||
icon_state = "petehat"
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/head.dmi'
|
||||
)
|
||||
|
||||
|
||||
@@ -43,12 +43,6 @@
|
||||
siemens_coefficient = 0.7
|
||||
body_parts_covered = FACE|EYES
|
||||
|
||||
/obj/item/clothing/mask/gas/swat/vox
|
||||
name = "\improper alien mask"
|
||||
desc = "Clearly not designed for a human face."
|
||||
body_parts_covered = 0 //Hack to allow vox to eat while wearing this mask.
|
||||
species_restricted = list("Vox")
|
||||
|
||||
/obj/item/clothing/mask/gas/syndicate
|
||||
name = "tactical mask"
|
||||
desc = "A close-fitting tactical mask that can be connected to an air supply."
|
||||
|
||||
@@ -28,141 +28,3 @@
|
||||
/obj/item/clothing/suit/space/skrell/black
|
||||
icon_state = "skrell_suit_black"
|
||||
item_state = "skrell_suit_black"
|
||||
|
||||
// Vox space gear (vaccuum suit, low pressure armour)
|
||||
// Can't be equipped by any other species due to bone structure and vox cybernetics.
|
||||
/obj/item/clothing/suit/space/vox
|
||||
w_class = 3
|
||||
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank)
|
||||
slowdown = 2
|
||||
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
|
||||
siemens_coefficient = 0.6
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
|
||||
species_restricted = list("Vox")
|
||||
|
||||
/obj/item/clothing/head/helmet/space/vox
|
||||
armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30)
|
||||
siemens_coefficient = 0.6
|
||||
item_flags = STOPPRESSUREDAMAGE
|
||||
species_restricted = list("Vox")
|
||||
|
||||
/obj/item/clothing/head/helmet/space/vox/pressure
|
||||
name = "alien helmet"
|
||||
icon_state = "vox-pressure"
|
||||
item_state = "vox-pressure"
|
||||
desc = "Hey, wasn't this a prop in \'The Abyss\'?"
|
||||
|
||||
/obj/item/clothing/suit/space/vox/pressure
|
||||
name = "alien pressure suit"
|
||||
icon_state = "vox-pressure"
|
||||
item_state = "vox-pressure"
|
||||
desc = "A huge, armoured, pressurized suit, designed for distinctly nonhuman proportions."
|
||||
|
||||
/obj/item/clothing/head/helmet/space/vox/carapace
|
||||
name = "alien visor"
|
||||
icon_state = "vox-carapace"
|
||||
item_state = "vox-carapace"
|
||||
desc = "A glowing visor, perhaps stolen from a depressed Cylon."
|
||||
|
||||
/obj/item/clothing/suit/space/vox/carapace
|
||||
name = "alien carapace armour"
|
||||
icon_state = "vox-carapace"
|
||||
item_state = "vox-carapace"
|
||||
desc = "An armoured, segmented carapace with glowing purple lights. It looks pretty run-down."
|
||||
|
||||
/obj/item/clothing/head/helmet/space/vox/stealth
|
||||
name = "alien stealth helmet"
|
||||
icon_state = "vox-stealth"
|
||||
item_state = "vox-stealth"
|
||||
desc = "A smoothly contoured, matte-black alien helmet."
|
||||
|
||||
/obj/item/clothing/suit/space/vox/stealth
|
||||
name = "alien stealth suit"
|
||||
icon_state = "vox-stealth"
|
||||
item_state = "vox-stealth"
|
||||
desc = "A sleek black suit. It seems to have a tail, and is very heavy."
|
||||
|
||||
/obj/item/clothing/head/helmet/space/vox/medic
|
||||
name = "alien goggled helmet"
|
||||
icon_state = "vox-medic"
|
||||
item_state = "vox-medic"
|
||||
desc = "An alien helmet with enormous goggled lenses."
|
||||
|
||||
/obj/item/clothing/suit/space/vox/medic
|
||||
name = "alien armour"
|
||||
icon_state = "vox-medic"
|
||||
item_state = "vox-medic"
|
||||
desc = "An almost organic looking nonhuman pressure suit."
|
||||
|
||||
/obj/item/clothing/under/vox
|
||||
has_sensor = 0
|
||||
species_restricted = list("Vox")
|
||||
|
||||
/obj/item/clothing/under/vox/vox_casual
|
||||
name = "alien clothing"
|
||||
desc = "This doesn't look very comfortable."
|
||||
icon_state = "vox-casual-1"
|
||||
item_state = "vox-casual-1"
|
||||
body_parts_covered = LEGS
|
||||
|
||||
/obj/item/clothing/under/vox/vox_robes
|
||||
name = "alien robes"
|
||||
desc = "Weird and flowing!"
|
||||
icon_state = "vox-casual-2"
|
||||
item_state = "vox-casual-2"
|
||||
|
||||
/obj/item/clothing/gloves/yellow/vox
|
||||
desc = "These bizarre gauntlets seem to be fitted for... bird claws?"
|
||||
name = "insulated gauntlets"
|
||||
icon_state = "gloves-vox"
|
||||
item_state = "gloves-vox"
|
||||
siemens_coefficient = 0
|
||||
permeability_coefficient = 0.05
|
||||
species_restricted = list("Vox")
|
||||
|
||||
/obj/item/clothing/shoes/magboots/vox
|
||||
|
||||
desc = "A pair of heavy, jagged armoured foot pieces, seemingly suitable for a velociraptor."
|
||||
name = "vox magclaws"
|
||||
item_state = "boots-vox"
|
||||
icon_state = "boots-vox"
|
||||
species_restricted = list("Vox")
|
||||
|
||||
action_button_name = "Toggle the magclaws"
|
||||
|
||||
/obj/item/clothing/shoes/magboots/vox/attack_self(mob/user)
|
||||
if(src.magpulse)
|
||||
item_flags &= ~NOSLIP
|
||||
magpulse = 0
|
||||
canremove = 1
|
||||
user << "You relax your deathgrip on the flooring."
|
||||
else
|
||||
//make sure these can only be used when equipped.
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if (H.shoes != src)
|
||||
user << "You will have to put on the [src] before you can do that."
|
||||
return
|
||||
|
||||
item_flags |= NOSLIP
|
||||
magpulse = 1
|
||||
canremove = 0 //kinda hard to take off magclaws when you are gripping them tightly.
|
||||
user << "You dig your claws deeply into the flooring, bracing yourself."
|
||||
user << "It would be hard to take off the [src] without relaxing your grip first."
|
||||
user.update_action_buttons()
|
||||
|
||||
//In case they somehow come off while enabled.
|
||||
/obj/item/clothing/shoes/magboots/vox/dropped(mob/user as mob)
|
||||
..()
|
||||
if(src.magpulse)
|
||||
user.visible_message("The [src] go limp as they are removed from [usr]'s feet.", "The [src] go limp as they are removed from your feet.")
|
||||
item_flags &= ~NOSLIP
|
||||
magpulse = 0
|
||||
canremove = 1
|
||||
|
||||
/obj/item/clothing/shoes/magboots/vox/examine(mob/user)
|
||||
..(user)
|
||||
if (magpulse)
|
||||
user << "It would be hard to take these off without relaxing your grip first." //theoretically this message should only be seen by the wearer when the claws are equipped.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE
|
||||
siemens_coefficient = 0.9
|
||||
species_restricted = list("exclude","Diona", "Xenomorph")
|
||||
species_restricted = list("exclude","Diona")
|
||||
|
||||
var/obj/machinery/camera/camera
|
||||
var/list/camera_networks
|
||||
@@ -63,7 +63,7 @@
|
||||
cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
|
||||
min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE
|
||||
siemens_coefficient = 0.9
|
||||
species_restricted = list("exclude","Diona", "Xenomorph")
|
||||
species_restricted = list("exclude","Diona")
|
||||
|
||||
var/list/supporting_limbs //If not-null, automatically splints breaks. Checked when removing the suit.
|
||||
|
||||
|
||||
@@ -21,12 +21,14 @@
|
||||
var/cash_stored = 0
|
||||
var/obj/item/confirm_item
|
||||
var/datum/money_account/linked_account
|
||||
var/account_to_connect = null
|
||||
|
||||
|
||||
// Claim machine ID
|
||||
/obj/machinery/cash_register/New()
|
||||
machine_id = "[station_name()] RETAIL #[num_financial_terminals++]"
|
||||
cash_stored = rand(10, 70)*10
|
||||
transaction_devices += src // Global reference list to be properly set up by /proc/setup_economy()
|
||||
|
||||
|
||||
/obj/machinery/cash_register/examine(mob/user as mob)
|
||||
@@ -39,6 +41,9 @@
|
||||
|
||||
|
||||
/obj/machinery/cash_register/attack_hand(mob/user as mob)
|
||||
// Don't be accessible from the wrong side of the machine
|
||||
if(get_dir(src, user) & reverse_dir[src.dir]) return
|
||||
|
||||
if(cash_open)
|
||||
if(cash_stored)
|
||||
spawn_money(cash_stored, loc, user)
|
||||
@@ -278,26 +283,24 @@
|
||||
usr << "\icon[src]<span class='warning'>The cash box is open.</span>"
|
||||
return
|
||||
|
||||
// Access account for transaction
|
||||
if(check_account())
|
||||
if(transaction_amount > SC.worth)
|
||||
src.visible_message("\icon[src]<span class='warning'>Not enough money.</span>")
|
||||
else
|
||||
// Insert cash into magical slot
|
||||
SC.worth -= transaction_amount
|
||||
SC.update_icon()
|
||||
if(!SC.worth)
|
||||
if(ishuman(SC.loc))
|
||||
var/mob/living/carbon/human/H = SC.loc
|
||||
H.drop_from_inventory(SC)
|
||||
qdel(SC)
|
||||
cash_stored += transaction_amount
|
||||
if(transaction_amount > SC.worth)
|
||||
src.visible_message("\icon[src]<span class='warning'>Not enough money.</span>")
|
||||
else
|
||||
// Insert cash into magical slot
|
||||
SC.worth -= transaction_amount
|
||||
SC.update_icon()
|
||||
if(!SC.worth)
|
||||
if(ishuman(SC.loc))
|
||||
var/mob/living/carbon/human/H = SC.loc
|
||||
H.drop_from_inventory(SC)
|
||||
qdel(SC)
|
||||
cash_stored += transaction_amount
|
||||
|
||||
// Save log
|
||||
add_transaction_log("n/A", "Cash", transaction_amount)
|
||||
// Save log
|
||||
add_transaction_log("n/A", "Cash", transaction_amount)
|
||||
|
||||
// Confirm and reset
|
||||
transaction_complete()
|
||||
// Confirm and reset
|
||||
transaction_complete()
|
||||
|
||||
|
||||
/obj/machinery/cash_register/proc/scan_item_price(obj/O)
|
||||
@@ -436,39 +439,33 @@
|
||||
cash_locked = 0
|
||||
open_cash_box()
|
||||
|
||||
|
||||
//--Premades--//
|
||||
|
||||
/obj/machinery/cash_register/command
|
||||
New()
|
||||
linked_account = department_accounts["Command"]
|
||||
..()
|
||||
/obj/machinery/cash_register/medical
|
||||
account_to_connect = "Command"
|
||||
..()
|
||||
|
||||
New()
|
||||
linked_account = department_accounts["Medical"]
|
||||
..()
|
||||
/obj/machinery/cash_register/medical
|
||||
account_to_connect = "Medical"
|
||||
..()
|
||||
|
||||
/obj/machinery/cash_register/engineering
|
||||
New()
|
||||
linked_account = department_accounts["Engineering"]
|
||||
..()
|
||||
account_to_connect = "Engineering"
|
||||
..()
|
||||
|
||||
/obj/machinery/cash_register/science
|
||||
New()
|
||||
linked_account = department_accounts["Science"]
|
||||
..()
|
||||
account_to_connect = "Science"
|
||||
..()
|
||||
|
||||
/obj/machinery/cash_register/security
|
||||
New()
|
||||
linked_account = department_accounts["Security"]
|
||||
..()
|
||||
account_to_connect = "Security"
|
||||
..()
|
||||
|
||||
/obj/machinery/cash_register/cargo
|
||||
New()
|
||||
linked_account = department_accounts["Cargo"]
|
||||
..()
|
||||
account_to_connect = "Cargo"
|
||||
..()
|
||||
|
||||
/obj/machinery/cash_register/civilian
|
||||
New()
|
||||
linked_account = department_accounts["Civilian"]
|
||||
..()
|
||||
account_to_connect = "Civilian"
|
||||
..()
|
||||
@@ -52,8 +52,7 @@
|
||||
/datum/species/skrell = 12,
|
||||
/datum/species/teshari = 9, // Skrell sponsored!
|
||||
/datum/species/tajaran = 7,
|
||||
/datum/species/unathi = 7,
|
||||
/datum/species/vox = 1
|
||||
/datum/species/unathi = 7
|
||||
)
|
||||
|
||||
//---- The following corporations are friendly with NanoTrasen and loosely enable trade and travel:
|
||||
@@ -81,6 +80,7 @@ var/global/list/datum/money_account/department_accounts = list()
|
||||
var/global/num_financial_terminals = 1
|
||||
var/global/next_account_number = 0
|
||||
var/global/list/all_money_accounts = list()
|
||||
var/global/list/transaction_devices = list()
|
||||
var/global/economy_init = 0
|
||||
|
||||
/proc/setup_economy()
|
||||
@@ -102,6 +102,13 @@ var/global/economy_init = 0
|
||||
create_department_account("Vendor")
|
||||
vendor_account = department_accounts["Vendor"]
|
||||
|
||||
for(var/obj/item/device/retail_scanner/RS in transaction_devices)
|
||||
if(RS.account_to_connect)
|
||||
RS.linked_account = department_accounts[RS.account_to_connect]
|
||||
for(var/obj/machinery/cash_register/CR in transaction_devices)
|
||||
if(CR.account_to_connect)
|
||||
CR.linked_account = department_accounts[CR.account_to_connect]
|
||||
|
||||
current_date_string = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], [game_year]"
|
||||
|
||||
economy_init = 1
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
var/obj/item/confirm_item
|
||||
var/datum/money_account/linked_account
|
||||
var/account_to_connect = null
|
||||
|
||||
|
||||
// Claim machine ID
|
||||
@@ -24,6 +25,7 @@
|
||||
machine_id = "[station_name()] RETAIL #[num_financial_terminals++]"
|
||||
if(locate(/obj/structure/table) in loc)
|
||||
pixel_y = 3
|
||||
transaction_devices += src // Global reference list to be properly set up by /proc/setup_economy()
|
||||
|
||||
|
||||
// Always face the user when put on a table
|
||||
@@ -315,36 +317,29 @@
|
||||
//--Premades--//
|
||||
|
||||
/obj/item/device/retail_scanner/command
|
||||
New()
|
||||
linked_account = department_accounts["Command"]
|
||||
..()
|
||||
/obj/item/device/retail_scanner/medical
|
||||
account_to_connect = "Command"
|
||||
..()
|
||||
|
||||
New()
|
||||
linked_account = department_accounts["Medical"]
|
||||
..()
|
||||
/obj/item/device/retail_scanner/medical
|
||||
account_to_connect = "Medical"
|
||||
..()
|
||||
|
||||
/obj/item/device/retail_scanner/engineering
|
||||
New()
|
||||
linked_account = department_accounts["Engineering"]
|
||||
..()
|
||||
account_to_connect = "Engineering"
|
||||
..()
|
||||
|
||||
/obj/item/device/retail_scanner/science
|
||||
New()
|
||||
linked_account = department_accounts["Science"]
|
||||
..()
|
||||
account_to_connect = "Science"
|
||||
..()
|
||||
|
||||
/obj/item/device/retail_scanner/security
|
||||
New()
|
||||
linked_account = department_accounts["Security"]
|
||||
..()
|
||||
account_to_connect = "Security"
|
||||
..()
|
||||
|
||||
/obj/item/device/retail_scanner/cargo
|
||||
New()
|
||||
linked_account = department_accounts["Cargo"]
|
||||
..()
|
||||
account_to_connect = "Cargo"
|
||||
..()
|
||||
|
||||
/obj/item/device/retail_scanner/civilian
|
||||
New()
|
||||
linked_account = department_accounts["Civilian"]
|
||||
..()
|
||||
account_to_connect = "Civilian"
|
||||
..()
|
||||
@@ -86,12 +86,6 @@
|
||||
"admin","ponies","heresy","meow","Pun Pun","monkey","Ian","moron","pizza","message","spam",\
|
||||
"director", "Hello", "Hi!"," ","nuke","crate","dwarf","xeno")
|
||||
|
||||
/datum/event/ionstorm/tick()
|
||||
if(botEmagChance)
|
||||
for(var/obj/machinery/bot/bot in world)
|
||||
if(prob(botEmagChance))
|
||||
bot.emag_act(1)
|
||||
|
||||
/datum/event/ionstorm/end()
|
||||
spawn(rand(5000,8000))
|
||||
if(prob(50))
|
||||
|
||||
@@ -1151,23 +1151,3 @@
|
||||
set_trait(TRAIT_PRODUCTION,7)
|
||||
set_trait(TRAIT_YIELD,3)
|
||||
set_trait(TRAIT_POTENCY,3)
|
||||
|
||||
// Alien weeds.
|
||||
/datum/seed/xenomorph
|
||||
name = "xenomorph"
|
||||
seed_name = "alien weed"
|
||||
display_name = "alien weeds"
|
||||
force_layer = 3
|
||||
chems = list("phoron" = list(1,3))
|
||||
|
||||
/datum/seed/xenomorph/New()
|
||||
..()
|
||||
set_trait(TRAIT_PLANT_ICON,"vine2")
|
||||
set_trait(TRAIT_IMMUTABLE,1)
|
||||
set_trait(TRAIT_PRODUCT_COLOUR,"#3D1934")
|
||||
set_trait(TRAIT_FLESH_COLOUR,"#3D1934")
|
||||
set_trait(TRAIT_PLANT_COLOUR,"#3D1934")
|
||||
set_trait(TRAIT_PRODUCTION,1)
|
||||
set_trait(TRAIT_YIELD,-1)
|
||||
set_trait(TRAIT_SPREAD,2)
|
||||
set_trait(TRAIT_POTENCY,50)
|
||||
@@ -556,8 +556,8 @@ var/list/name_to_material
|
||||
sheet_plural_name = "ingots"
|
||||
|
||||
// Adminspawn only, do not let anyone get this.
|
||||
/material/voxalloy
|
||||
name = "voxalloy"
|
||||
/material/alienalloy
|
||||
name = "alienalloy"
|
||||
display_name = "durable alloy"
|
||||
stack_type = null
|
||||
icon_colour = "#6C7364"
|
||||
@@ -640,21 +640,6 @@ var/list/name_to_material
|
||||
/material/cult/reinf/place_dismantled_product(var/turf/target)
|
||||
new /obj/effect/decal/remains/human(target)
|
||||
|
||||
/material/resin
|
||||
name = "resin"
|
||||
icon_colour = "#E85DD8"
|
||||
dooropen_noise = 'sound/effects/attackblob.ogg'
|
||||
door_icon_base = "resin"
|
||||
melting_point = T0C+300
|
||||
sheet_singular_name = "blob"
|
||||
sheet_plural_name = "blobs"
|
||||
|
||||
/material/resin/can_open_material_door(var/mob/living/user)
|
||||
var/mob/living/carbon/M = user
|
||||
if(istype(M) && locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//TODO PLACEHOLDERS:
|
||||
/material/leather
|
||||
name = "leather"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
generate_loot()
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/proc/generate_loot()
|
||||
var/loot = rand(1, 100)
|
||||
var/loot = rand(1, 99)
|
||||
switch(loot)
|
||||
if(1 to 5) // Common things go, 5%
|
||||
new/obj/item/weapon/reagent_containers/food/drinks/bottle/rum(src)
|
||||
@@ -104,7 +104,7 @@
|
||||
if(88)
|
||||
new/obj/item/xenos_claw(src)
|
||||
if(89)
|
||||
new/obj/item/organ/internal/xenos/plasmavessel(src)
|
||||
new/obj/item/clothing/head/bearpelt(src)
|
||||
if(90)
|
||||
new/obj/item/organ/internal/heart(src)
|
||||
if(91)
|
||||
@@ -142,8 +142,6 @@
|
||||
if(99)
|
||||
new/obj/item/weapon/storage/belt/champion(src)
|
||||
new/obj/item/clothing/mask/luchador(src)
|
||||
if(100)
|
||||
new/obj/item/clothing/head/bearpelt(src)
|
||||
|
||||
/obj/structure/closet/crate/secure/loot/togglelock(mob/user as mob)
|
||||
if(!locked)
|
||||
|
||||
@@ -9,7 +9,6 @@ var/list/holder_mob_icon_cache = list()
|
||||
show_messages = 1
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi',
|
||||
"Teshari" = 'icons/mob/species/seromi/head.dmi'
|
||||
)
|
||||
|
||||
|
||||
@@ -1,34 +1,3 @@
|
||||
/datum/language/xenocommon
|
||||
name = "Xenomorph"
|
||||
colour = "alien"
|
||||
desc = "The common tongue of the xenomorphs."
|
||||
speech_verb = "hisses"
|
||||
ask_verb = "hisses"
|
||||
exclaim_verb = "hisses"
|
||||
key = "4"
|
||||
flags = RESTRICTED
|
||||
syllables = list("sss","sSs","SSS")
|
||||
|
||||
/datum/language/xenos
|
||||
name = "Hivemind"
|
||||
desc = "Xenomorphs have the strange ability to commune over a psychic hivemind."
|
||||
speech_verb = "hisses"
|
||||
ask_verb = "hisses"
|
||||
exclaim_verb = "hisses"
|
||||
colour = "alien"
|
||||
key = "a"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
|
||||
/datum/language/xenos/check_special_condition(var/mob/other)
|
||||
|
||||
var/mob/living/carbon/M = other
|
||||
if(!istype(M))
|
||||
return 1
|
||||
if(locate(/obj/item/organ/internal/xenos/hivenode) in M.internal_organs)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/datum/language/ling
|
||||
name = "Changeling"
|
||||
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
|
||||
@@ -68,21 +37,6 @@
|
||||
speaker_mask = B.truename
|
||||
..(speaker,message,speaker_mask)
|
||||
|
||||
/datum/language/vox
|
||||
name = "Vox-pidgin"
|
||||
desc = "The common tongue of the various Vox ships making up the Shoal. It sounds like chaotic shrieking to everyone else."
|
||||
speech_verb = "shrieks"
|
||||
ask_verb = "creels"
|
||||
exclaim_verb = "SHRIEKS"
|
||||
colour = "vox"
|
||||
key = "5"
|
||||
flags = WHITELISTED
|
||||
syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya","chi","cha","kah", \
|
||||
"SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA")
|
||||
|
||||
/datum/language/vox/get_random_name()
|
||||
return ..(FEMALE,1,6)
|
||||
|
||||
/datum/language/cultcommon
|
||||
name = "Cult"
|
||||
desc = "The chants of the occult, the incomprehensible."
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
access_scanner.req_access = req_access.Copy()
|
||||
access_scanner.req_one_access = req_one_access.Copy()
|
||||
|
||||
turn_on()
|
||||
|
||||
/mob/living/bot/Life()
|
||||
..()
|
||||
if(health <= 0)
|
||||
@@ -125,3 +127,70 @@
|
||||
|
||||
/mob/living/bot/attack_throat()
|
||||
return
|
||||
|
||||
/******************************************************************/
|
||||
// Navigation procs
|
||||
// Used for A-star pathfinding
|
||||
|
||||
|
||||
// Returns the surrounding cardinal turfs with open links
|
||||
// Including through doors openable with the ID
|
||||
/turf/proc/CardinalTurfsWithAccess(var/obj/item/weapon/card/id/ID)
|
||||
var/L[] = new()
|
||||
|
||||
// for(var/turf/simulated/t in oview(src,1))
|
||||
|
||||
for(var/d in cardinal)
|
||||
var/turf/simulated/T = get_step(src, d)
|
||||
if(istype(T) && !T.density)
|
||||
if(!LinkBlockedWithAccess(src, T, ID))
|
||||
L.Add(T)
|
||||
return L
|
||||
|
||||
|
||||
// Returns true if a link between A and B is blocked
|
||||
// Movement through doors allowed if ID has access
|
||||
/proc/LinkBlockedWithAccess(turf/A, turf/B, obj/item/weapon/card/id/ID)
|
||||
|
||||
if(A == null || B == null) return 1
|
||||
var/adir = get_dir(A,B)
|
||||
var/rdir = get_dir(B,A)
|
||||
if((adir & (NORTH|SOUTH)) && (adir & (EAST|WEST))) // diagonal
|
||||
var/iStep = get_step(A,adir&(NORTH|SOUTH))
|
||||
if(!LinkBlockedWithAccess(A,iStep, ID) && !LinkBlockedWithAccess(iStep,B,ID))
|
||||
return 0
|
||||
|
||||
var/pStep = get_step(A,adir&(EAST|WEST))
|
||||
if(!LinkBlockedWithAccess(A,pStep,ID) && !LinkBlockedWithAccess(pStep,B,ID))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
if(DirBlockedWithAccess(A,adir, ID))
|
||||
return 1
|
||||
|
||||
if(DirBlockedWithAccess(B,rdir, ID))
|
||||
return 1
|
||||
|
||||
for(var/obj/O in B)
|
||||
if(O.density && !istype(O, /obj/machinery/door) && !(O.flags & ON_BORDER))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
// Returns true if direction is blocked from loc
|
||||
// Checks doors against access with given ID
|
||||
/proc/DirBlockedWithAccess(turf/loc,var/dir,var/obj/item/weapon/card/id/ID)
|
||||
for(var/obj/structure/window/D in loc)
|
||||
if(!D.density) continue
|
||||
if(D.dir == SOUTHWEST) return 1
|
||||
if(D.dir == dir) return 1
|
||||
|
||||
for(var/obj/machinery/door/D in loc)
|
||||
if(!D.density) continue
|
||||
if(istype(D, /obj/machinery/door/window))
|
||||
if( dir & D.dir ) return !D.check_access(ID)
|
||||
|
||||
//if((dir & SOUTH) && (D.dir & (EAST|WEST))) return !D.check_access(ID)
|
||||
//if((dir & EAST ) && (D.dir & (NORTH|SOUTH))) return !D.check_access(ID)
|
||||
else return !D.check_access(ID) // it's a real, air blocking door
|
||||
return 0
|
||||
|
||||
438
code/modules/mob/living/bot/mulebot.dm
Normal file
@@ -0,0 +1,438 @@
|
||||
#define MULE_IDLE 0
|
||||
#define MULE_MOVING 1
|
||||
#define MULE_UNLOAD 2
|
||||
#define MULE_LOST 3
|
||||
#define MULE_CALC_MIN 4
|
||||
#define MULE_CALC_MAX 10
|
||||
#define MULE_PATH_DONE 11
|
||||
// IF YOU CHANGE THOSE, UPDATE THEM IN pda.tmpl TOO
|
||||
|
||||
/mob/living/bot/mulebot
|
||||
name = "Mulebot"
|
||||
desc = "A Multiple Utility Load Effector bot."
|
||||
icon_state = "mulebot0"
|
||||
anchored = 1
|
||||
density = 1
|
||||
health = 150
|
||||
maxHealth = 150
|
||||
mob_bump_flag = HEAVY
|
||||
|
||||
botcard_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
|
||||
|
||||
var/busy = 0
|
||||
var/mode = MULE_IDLE
|
||||
var/atom/movable/load
|
||||
|
||||
var/crates_only = 1
|
||||
var/auto_return = 1
|
||||
var/safety = 1
|
||||
|
||||
var/list/path = list()
|
||||
var/frustration = 0
|
||||
var/turf/target
|
||||
var/targetName
|
||||
var/turf/home
|
||||
var/homeName
|
||||
var/turf/obstacle
|
||||
|
||||
var/global/amount = 0
|
||||
|
||||
/mob/living/bot/mulebot/New()
|
||||
..()
|
||||
|
||||
var/turf/T = get_turf(loc)
|
||||
var/obj/machinery/navbeacon/N = locate() in T
|
||||
if(N)
|
||||
home = T
|
||||
homeName = N.location
|
||||
else
|
||||
homeName = "Unset"
|
||||
|
||||
suffix = num2text(++amount) // Starts from 1
|
||||
|
||||
name = "Mulebot #[suffix]"
|
||||
|
||||
/mob/living/bot/mulebot/MouseDrop_T(var/atom/movable/C, var/mob/user)
|
||||
if(user.stat)
|
||||
return
|
||||
|
||||
if(!istype(C) || C.anchored || get_dist(user, src) > 1 || get_dist(src, C) > 1 )
|
||||
return
|
||||
|
||||
load(C)
|
||||
|
||||
/mob/living/bot/mulebot/attack_hand(var/mob/user)
|
||||
interact(user)
|
||||
|
||||
/mob/living/bot/mulebot/proc/interact(var/mob/user)
|
||||
var/dat
|
||||
dat += "<TT><B>Multiple Utility Load Effector Mk. III</B></TT><BR><BR>"
|
||||
dat += "ID: [suffix]<BR>"
|
||||
dat += "Power: [on ? "On" : "Off"]<BR>"
|
||||
|
||||
if(!open)
|
||||
dat += "Status: "
|
||||
switch(mode)
|
||||
if(MULE_IDLE)
|
||||
dat += "Ready"
|
||||
if(MULE_MOVING, MULE_UNLOAD, MULE_PATH_DONE)
|
||||
dat += "Navigating"
|
||||
if(MULE_UNLOAD)
|
||||
dat += "Unloading"
|
||||
if(MULE_LOST)
|
||||
dat += "Processing commands"
|
||||
if(MULE_CALC_MIN to MULE_CALC_MAX)
|
||||
dat += "Calculating navigation path"
|
||||
|
||||
dat += "<BR>Current Load: [load ? load.name : "<i>none</i>"]<BR>"
|
||||
|
||||
if(locked)
|
||||
dat += "<HR>Controls are locked"
|
||||
else
|
||||
dat += "<HR>Controls are unlocked<BR><BR>"
|
||||
|
||||
if(!locked || issilicon(user))
|
||||
dat += "<A href='byond://?src=\ref[src];op=power'>Toggle power</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=stop'>Stop</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=go'>Proceed</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=home'>Return to home</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=destination'>Set destination</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=sethome'>Set home</A><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=autoret'>Toggle auto return home</A> ([auto_return ? "On" : "Off"])<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];op=cargotypes'>Toggle non-standard cargo</A> ([crates_only ? "Off" : "On"])<BR>"
|
||||
|
||||
if(load)
|
||||
dat += "<A href='byond://?src=\ref[src];op=unload'>Unload now</A><BR>"
|
||||
dat += "<HR>The maintenance hatch is closed.<BR>"
|
||||
|
||||
else
|
||||
if(!issilicon(user))
|
||||
dat += "The maintenance hatch is open.<BR><BR>"
|
||||
|
||||
dat += "<A href='byond://?src=\ref[src];op=safety'>Toggle safety</A> ([safety ? "On" : "Off - DANGER"])<BR>"
|
||||
else
|
||||
dat += "The bot is in maintenance mode and cannot be controlled.<BR>"
|
||||
|
||||
user << browse("<HEAD><TITLE>Mulebot [suffix ? "([suffix])" : ""]</TITLE></HEAD>[dat]", "window=mulebot;size=350x500")
|
||||
onclose(user, "mulebot")
|
||||
return
|
||||
|
||||
/mob/living/bot/mulebot/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
switch(href_list["op"])
|
||||
if("power")
|
||||
if(on)
|
||||
turn_off()
|
||||
else
|
||||
turn_on()
|
||||
visible_message("[usr] switches [on ? "on" : "off"] [src].")
|
||||
|
||||
if("stop")
|
||||
obeyCommand("Stop")
|
||||
|
||||
if("go")
|
||||
obeyCommand("GoTD")
|
||||
|
||||
if("home")
|
||||
obeyCommand("Home")
|
||||
|
||||
if("destination")
|
||||
obeyCommand("SetD")
|
||||
|
||||
if("sethome")
|
||||
var/new_dest
|
||||
var/list/beaconlist = new()
|
||||
for(var/obj/machinery/navbeacon/N in navbeacons)
|
||||
beaconlist.Add(N.location)
|
||||
beaconlist[N.location] = N
|
||||
if(beaconlist.len)
|
||||
new_dest = input("Select new home tag", "Mulebot [suffix ? "([suffix])" : ""]", null) in null|beaconlist
|
||||
else
|
||||
alert("No destination beacons available.")
|
||||
if(new_dest)
|
||||
home = get_turf(beaconlist[new_dest])
|
||||
homeName = new_dest
|
||||
|
||||
if("unload")
|
||||
unload()
|
||||
|
||||
if("autoret")
|
||||
auto_return = !auto_return
|
||||
|
||||
if("cargotypes")
|
||||
crates_only = !crates_only
|
||||
|
||||
if("safety")
|
||||
safety = !safety
|
||||
|
||||
interact(usr)
|
||||
|
||||
/mob/living/bot/mulebot/attackby(var/obj/item/O, var/mob/user)
|
||||
..()
|
||||
update_icons()
|
||||
|
||||
/mob/living/bot/mulebot/proc/obeyCommand(var/command)
|
||||
switch(command)
|
||||
if("Home")
|
||||
mode = MULE_IDLE
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
if("SetD")
|
||||
var/new_dest
|
||||
var/list/beaconlist = new()
|
||||
for(var/obj/machinery/navbeacon/N in navbeacons)
|
||||
beaconlist.Add(N.location)
|
||||
beaconlist[N.location] = N
|
||||
if(beaconlist.len)
|
||||
new_dest = input("Select new destination tag", "Mulebot [suffix ? "([suffix])" : ""]") in null|beaconlist
|
||||
else
|
||||
alert("No destination beacons available.")
|
||||
if(new_dest)
|
||||
target = get_turf(beaconlist[new_dest])
|
||||
targetName = new_dest
|
||||
if("GoTD")
|
||||
if(mode == MULE_IDLE)
|
||||
mode = MULE_LOST
|
||||
if("Stop")
|
||||
mode = MULE_IDLE
|
||||
|
||||
/mob/living/bot/mulebot/emag_act(var/remaining_charges, var/user)
|
||||
locked = !locked
|
||||
user << "<span class='notice'>You [locked ? "lock" : "unlock"] the mulebot's controls!</span>"
|
||||
flick("mulebot-emagged", src)
|
||||
playsound(loc, 'sound/effects/sparks1.ogg', 100, 0)
|
||||
return 1
|
||||
|
||||
/mob/living/bot/mulebot/update_icons()
|
||||
if(open)
|
||||
icon_state = "mulebot-hatch"
|
||||
return
|
||||
if(mode == MULE_MOVING || mode == MULE_UNLOAD)
|
||||
icon_state = "mulebot1"
|
||||
return
|
||||
icon_state = "mulebot0"
|
||||
|
||||
/mob/living/bot/mulebot/Life()
|
||||
..()
|
||||
|
||||
if(busy)
|
||||
return
|
||||
|
||||
if(!safety && prob(1))
|
||||
flick("mulebot-emagged", src)
|
||||
|
||||
switch(mode)
|
||||
if(MULE_IDLE) // Idle
|
||||
return
|
||||
if(MULE_MOVING) // Moving to target
|
||||
if(!target) // Return home
|
||||
if(auto_return && home)
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
return
|
||||
if(loc == target) // Unload or stop
|
||||
custom_emote(2, "makes a chiming sound.")
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
|
||||
mode = MULE_UNLOAD
|
||||
update_icons()
|
||||
return
|
||||
if(path.len) // Move
|
||||
makeStep()
|
||||
sleep(10)
|
||||
if(path.len)
|
||||
makeStep()
|
||||
else
|
||||
mode = MULE_LOST
|
||||
|
||||
update_icons()
|
||||
return
|
||||
if(MULE_UNLOAD)
|
||||
unload(dir)
|
||||
|
||||
if(auto_return && home && (loc != home))
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
return
|
||||
if(MULE_LOST) // Lost my way
|
||||
if(target)
|
||||
spawn(0)
|
||||
calc_path(obstacle)
|
||||
mode = MULE_CALC_MIN
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
return
|
||||
if(MULE_CALC_MIN to MULE_CALC_MAX) // Calcing path
|
||||
if(path.len)
|
||||
mode = MULE_PATH_DONE
|
||||
update_icons()
|
||||
else
|
||||
++mode
|
||||
return
|
||||
if(MULE_PATH_DONE) // Done with path
|
||||
obstacle = null
|
||||
if(path.len)
|
||||
frustration = 0
|
||||
mode = MULE_MOVING
|
||||
else
|
||||
if(home)
|
||||
target = home
|
||||
targetName = "Home"
|
||||
mode = MULE_LOST
|
||||
else
|
||||
mode = MULE_IDLE
|
||||
update_icons()
|
||||
|
||||
/mob/living/bot/mulebot/Bump(var/mob/living/M)
|
||||
if(!safety && istype(M))
|
||||
visible_message("<span class='warning'>[src] knocks over [M]!</span>")
|
||||
M.Stun(8)
|
||||
M.Weaken(5)
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/proc/makeStep()
|
||||
var/turf/next = path[1]
|
||||
if(next == loc)
|
||||
path -= next
|
||||
return
|
||||
|
||||
var/moved = step_towards(src, next)
|
||||
if(moved)
|
||||
frustration = 0
|
||||
path -= next
|
||||
else if(frustration < 6)
|
||||
if(frustration == 3)
|
||||
custom_emote(2, "makes an annoyed buzzing sound")
|
||||
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
++frustration
|
||||
else
|
||||
custom_emote(2, "makes a sighing buzz.")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
obstacle = next
|
||||
|
||||
mode = MULE_LOST
|
||||
|
||||
/mob/living/bot/mulebot/proc/runOver(var/mob/living/carbon/human/H)
|
||||
if(istype(H)) // No safety checks - WILL run over lying humans. Stop ERPing in the maint!
|
||||
visible_message("<span class='warning'>[src] drives over [H]!</span>")
|
||||
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
|
||||
var/damage = rand(5, 7)
|
||||
H.apply_damage(2 * damage, BRUTE, BP_HEAD)
|
||||
H.apply_damage(2 * damage, BRUTE, BP_TORSO)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_L_LEG)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_R_LEG)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_L_ARM)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_R_ARM)
|
||||
|
||||
blood_splatter(src, H, 1)
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/relaymove(var/mob/user, var/direction)
|
||||
if(load == user)
|
||||
unload(direction)
|
||||
|
||||
/mob/living/bot/mulebot/explode()
|
||||
unload(pick(0, 1, 2, 4, 8))
|
||||
|
||||
visible_message("<span class='danger'>[src] blows apart!</span>")
|
||||
|
||||
var/turf/Tsec = get_turf(src)
|
||||
new /obj/item/device/assembly/prox_sensor(Tsec)
|
||||
PoolOrNew(/obj/item/stack/rods, Tsec)
|
||||
PoolOrNew(/obj/item/stack/rods, Tsec)
|
||||
new /obj/item/stack/cable_coil/cut(Tsec)
|
||||
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
new /obj/effect/decal/cleanable/blood/oil(Tsec)
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/proc/calc_path(var/turf/avoid = null)
|
||||
path = AStar(loc, target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 250, id = botcard, exclude = avoid)
|
||||
if(!path)
|
||||
path = list()
|
||||
|
||||
/mob/living/bot/mulebot/proc/load(var/atom/movable/C)
|
||||
if(busy || load || get_dist(C, src) > 1 || !isturf(C.loc))
|
||||
return
|
||||
|
||||
for(var/obj/structure/plasticflaps/P in src.loc)//Takes flaps into account
|
||||
if(!CanPass(C,P))
|
||||
return
|
||||
|
||||
if(crates_only && !istype(C,/obj/structure/closet/crate))
|
||||
custom_emote(2, "makes a sighing buzz.")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
return
|
||||
|
||||
var/obj/structure/closet/crate/crate = C
|
||||
if(istype(crate))
|
||||
crate.close()
|
||||
|
||||
//I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool.
|
||||
//So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below.
|
||||
//if(!istype(C,/obj/item) && !istype(C,/obj/machinery) && !istype(C,/obj/structure) && !ismob(C))
|
||||
// return
|
||||
busy = 1
|
||||
|
||||
C.loc = loc
|
||||
sleep(2)
|
||||
if(C.loc != loc) //To prevent you from going onto more than one bot.
|
||||
return
|
||||
C.loc = src
|
||||
load = C
|
||||
|
||||
C.pixel_y += 9
|
||||
if(C.layer < layer)
|
||||
C.layer = layer + 0.1
|
||||
overlays += C
|
||||
|
||||
busy = 0
|
||||
|
||||
/mob/living/bot/mulebot/proc/unload(var/dirn = 0)
|
||||
if(!load || busy)
|
||||
return
|
||||
|
||||
busy = 1
|
||||
overlays.Cut()
|
||||
|
||||
load.loc = loc
|
||||
load.pixel_y -= 9
|
||||
load.layer = initial(load.layer)
|
||||
|
||||
if(dirn)
|
||||
step(load, dirn)
|
||||
|
||||
load = null
|
||||
|
||||
for(var/atom/movable/AM in src)
|
||||
if(AM == botcard || AM == access_scanner)
|
||||
continue
|
||||
|
||||
AM.loc = loc
|
||||
AM.layer = initial(AM.layer)
|
||||
AM.pixel_y = initial(AM.pixel_y)
|
||||
busy = 0
|
||||
|
||||
#undef MULE_IDLE
|
||||
#undef MULE_MOVING
|
||||
#undef MULE_UNLOAD
|
||||
#undef MULE_LOST
|
||||
#undef MULE_CALC_MIN
|
||||
#undef MULE_CALC_MAX
|
||||
#undef MULE_PATH_DONE
|
||||
@@ -1,14 +0,0 @@
|
||||
/mob/living/carbon/alien/larva
|
||||
name = "alien larva"
|
||||
real_name = "alien larva"
|
||||
adult_form = /mob/living/carbon/human
|
||||
speak_emote = list("hisses")
|
||||
icon_state = "larva"
|
||||
language = "Hivemind"
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
|
||||
/mob/living/carbon/alien/larva/New()
|
||||
..()
|
||||
add_language("Xenomorph") //Bonus language.
|
||||
internal_organs |= new /obj/item/organ/internal/xenos/hivenode(src)
|
||||
@@ -1,12 +0,0 @@
|
||||
//Larvae regenerate health and nutrition from plasma and alien weeds.
|
||||
/mob/living/carbon/alien/larva/handle_environment(var/datum/gas_mixture/environment)
|
||||
|
||||
if(!environment) return
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(environment.gas["phoron"] > 0 || (T && locate(/obj/effect/alien/weeds) in T.contents))
|
||||
update_progression()
|
||||
adjustBruteLoss(-1)
|
||||
adjustFireLoss(-1)
|
||||
adjustToxLoss(-1)
|
||||
adjustOxyLoss(-1)
|
||||
@@ -1,12 +0,0 @@
|
||||
/mob/living/carbon/alien/larva/confirm_evolution()
|
||||
|
||||
src << "\blue <b>You are growing into a beautiful alien! It is time to choose a caste.</b>"
|
||||
src << "\blue There are three to choose from:"
|
||||
src << "<B>Hunters</B> \blue are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves."
|
||||
src << "<B>Sentinels</B> \blue are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters."
|
||||
src << "<B>Drones</B> \blue are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen."
|
||||
var/alien_caste = alert(src, "Please choose which alien caste you shall belong to.",,"Hunter","Sentinel","Drone")
|
||||
return alien_caste ? "Xenomorph [alien_caste]" : null
|
||||
|
||||
/mob/living/carbon/alien/larva/show_evolution_blurb()
|
||||
return
|
||||
@@ -71,10 +71,6 @@
|
||||
stat("Tank Pressure", internal.air_contents.return_pressure())
|
||||
stat("Distribution Pressure", internal.distribute_pressure)
|
||||
|
||||
var/obj/item/organ/internal/xenos/plasmavessel/P = internal_organs_by_name[O_PLASMA]
|
||||
if(P)
|
||||
stat(null, "Phoron Stored: [P.stored_plasma]/[P.max_plasma]")
|
||||
|
||||
if(back && istype(back,/obj/item/weapon/rig))
|
||||
var/obj/item/weapon/rig/suit = back
|
||||
var/cell_status = "ERROR"
|
||||
@@ -235,9 +231,9 @@
|
||||
// called when something steps onto a human
|
||||
// this handles mulebots and vehicles
|
||||
/mob/living/carbon/human/Crossed(var/atom/movable/AM)
|
||||
if(istype(AM, /obj/machinery/bot/mulebot))
|
||||
var/obj/machinery/bot/mulebot/MB = AM
|
||||
MB.RunOver(src)
|
||||
if(istype(AM, /mob/living/bot/mulebot))
|
||||
var/mob/living/bot/mulebot/MB = AM
|
||||
MB.runOver(src)
|
||||
|
||||
if(istype(AM, /obj/vehicle))
|
||||
var/obj/vehicle/V = AM
|
||||
|
||||
@@ -49,116 +49,6 @@
|
||||
if ((O.client && !( O.blinded )))
|
||||
O.show_message(text("\red <B>[] [failed ? "tried to tackle" : "has tackled"] down []!</B>", src, T), 1)
|
||||
|
||||
/mob/living/carbon/human/proc/leap()
|
||||
set category = "Abilities"
|
||||
set name = "Leap"
|
||||
set desc = "Leap at a target and grab them aggressively."
|
||||
|
||||
if(last_special > world.time)
|
||||
return
|
||||
|
||||
if(stat || paralysis || stunned || weakened || lying || restrained() || buckled)
|
||||
src << "You cannot leap in your current state."
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/M in view(6,src))
|
||||
if(!istype(M,/mob/living/silicon))
|
||||
choices += M
|
||||
choices -= src
|
||||
|
||||
var/mob/living/T = input(src,"Who do you wish to leap at?") as null|anything in choices
|
||||
|
||||
if(!T || !src || src.stat) return
|
||||
|
||||
if(get_dist(get_turf(T), get_turf(src)) > 4) return
|
||||
|
||||
if(last_special > world.time)
|
||||
return
|
||||
|
||||
if(stat || paralysis || stunned || weakened || lying || restrained() || buckled)
|
||||
src << "You cannot leap in your current state."
|
||||
return
|
||||
|
||||
last_special = world.time + 75
|
||||
status_flags |= LEAPING
|
||||
|
||||
src.visible_message("<span class='danger'>\The [src] leaps at [T]!</span>")
|
||||
src.throw_at(get_step(get_turf(T),get_turf(src)), 4, 1, src)
|
||||
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
|
||||
|
||||
sleep(5)
|
||||
|
||||
if(status_flags & LEAPING) status_flags &= ~LEAPING
|
||||
|
||||
if(!src.Adjacent(T))
|
||||
src << "<span class='warning'>You miss!</span>"
|
||||
return
|
||||
|
||||
T.Weaken(3)
|
||||
|
||||
// Pariahs are not good at leaping. This is snowflakey, pls fix.
|
||||
if(species.name == "Vox Pariah")
|
||||
src.Weaken(5)
|
||||
return
|
||||
|
||||
var/use_hand = "left"
|
||||
if(l_hand)
|
||||
if(r_hand)
|
||||
src << "<span class='danger'>You need to have one hand free to grab someone.</span>"
|
||||
return
|
||||
else
|
||||
use_hand = "right"
|
||||
|
||||
src.visible_message("<span class='warning'><b>\The [src]</b> seizes [T] aggressively!</span>")
|
||||
|
||||
var/obj/item/weapon/grab/G = new(src,T)
|
||||
if(use_hand == "left")
|
||||
l_hand = G
|
||||
else
|
||||
r_hand = G
|
||||
|
||||
G.state = GRAB_PASSIVE
|
||||
G.icon_state = "grabbed1"
|
||||
G.synch()
|
||||
|
||||
/mob/living/carbon/human/proc/gut()
|
||||
set category = "Abilities"
|
||||
set name = "Gut"
|
||||
set desc = "While grabbing someone aggressively, rip their guts out or tear them apart."
|
||||
|
||||
if(last_special > world.time)
|
||||
return
|
||||
|
||||
if(stat || paralysis || stunned || weakened || lying)
|
||||
src << "\red You cannot do that in your current state."
|
||||
return
|
||||
|
||||
var/obj/item/weapon/grab/G = locate() in src
|
||||
if(!G || !istype(G))
|
||||
src << "\red You are not grabbing anyone."
|
||||
return
|
||||
|
||||
if(G.state < GRAB_AGGRESSIVE)
|
||||
src << "\red You must have an aggressive grab to gut your prey!"
|
||||
return
|
||||
|
||||
last_special = world.time + 50
|
||||
|
||||
visible_message("<span class='warning'><b>\The [src]</b> rips viciously at \the [G.affecting]'s body with its claws!</span>")
|
||||
|
||||
if(istype(G.affecting,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = G.affecting
|
||||
H.apply_damage(50,BRUTE)
|
||||
if(H.stat == 2)
|
||||
H.gib()
|
||||
else
|
||||
var/mob/living/M = G.affecting
|
||||
if(!istype(M)) return //wut
|
||||
M.apply_damage(50,BRUTE)
|
||||
if(M.stat == 2)
|
||||
M.gib()
|
||||
|
||||
/mob/living/carbon/human/proc/commune()
|
||||
set category = "Abilities"
|
||||
set name = "Commune with creature"
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
h_style = "Unathi Horns"
|
||||
..(new_loc, "Unathi")
|
||||
|
||||
/mob/living/carbon/human/vox/New(var/new_loc)
|
||||
h_style = "Short Vox Quills"
|
||||
..(new_loc, "Vox")
|
||||
|
||||
/mob/living/carbon/human/diona/New(var/new_loc)
|
||||
..(new_loc, "Diona")
|
||||
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/datum/species/vox
|
||||
name = "Vox"
|
||||
name_plural = "Vox"
|
||||
icobase = 'icons/mob/human_races/r_vox.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_vox.dmi'
|
||||
default_language = "Vox-pidgin"
|
||||
language = "Galactic Common"
|
||||
num_alternate_languages = 1
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong)
|
||||
rarity_value = 4
|
||||
blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \
|
||||
scavenging vermin who prey on isolated stations, ships or planets to keep their own ancient arkships \
|
||||
alive. They are four to five feet tall, reptillian, beaked, tailed and quilled; human crews often \
|
||||
refer to them as 'shitbirds' for their violent and offensive nature, as well as their horrible \
|
||||
smell.<br/><br/>Most humans will never meet a Vox raider, instead learning of this insular species through \
|
||||
dealing with their traders and merchants; those that do rarely enjoy the experience."
|
||||
|
||||
speech_sounds = list('sound/voice/shriek1.ogg')
|
||||
speech_chance = 20
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = 0
|
||||
|
||||
cold_level_1 = 80
|
||||
cold_level_2 = 50
|
||||
cold_level_3 = 0
|
||||
|
||||
gluttonous = 2
|
||||
|
||||
breath_type = "nitrogen"
|
||||
poison_type = "oxygen"
|
||||
siemens_coefficient = 0.2
|
||||
|
||||
flags = NO_SCAN | NO_MINOR_CUT
|
||||
spawn_flags = CAN_JOIN | IS_WHITELISTED
|
||||
appearance_flags = HAS_EYE_COLOR
|
||||
|
||||
blood_color = "#2299FC"
|
||||
flesh_color = "#808D11"
|
||||
|
||||
reagent_tag = IS_VOX
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/leap
|
||||
)
|
||||
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest),
|
||||
BP_GROIN = list("path" = /obj/item/organ/external/groin),
|
||||
BP_HEAD = list("path" = /obj/item/organ/external/head/vox),
|
||||
BP_L_ARM = list("path" = /obj/item/organ/external/arm),
|
||||
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
|
||||
BP_L_LEG = list("path" = /obj/item/organ/external/leg),
|
||||
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
|
||||
BP_L_HAND = list("path" = /obj/item/organ/external/hand),
|
||||
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
|
||||
BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
|
||||
)
|
||||
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_LUNGS = /obj/item/organ/internal/lungs,
|
||||
O_LIVER = /obj/item/organ/internal/liver,
|
||||
O_KIDNEYS = /obj/item/organ/internal/kidneys,
|
||||
O_BRAIN = /obj/item/organ/internal/brain,
|
||||
O_EYES = /obj/item/organ/internal/eyes,
|
||||
"stack" = /obj/item/organ/internal/stack/vox
|
||||
)
|
||||
|
||||
/datum/species/vox/get_random_name(var/gender)
|
||||
var/datum/language/species_language = all_languages[default_language]
|
||||
return species_language.get_random_name(gender)
|
||||
|
||||
/datum/species/vox/equip_survival_gear(var/mob/living/carbon/human/H)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), slot_wear_mask)
|
||||
if(H.backbag == 1)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(H), slot_back)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H), slot_r_hand)
|
||||
H.internal = H.back
|
||||
else
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(H), slot_r_hand)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H.back), slot_in_backpack)
|
||||
H.internal = H.r_hand
|
||||
H.internals.icon_state = "internal1"
|
||||
|
||||
|
||||
/datum/species/vox/get_station_variant()
|
||||
return "Vox Pariah"
|
||||
|
||||
// Joining as a station vox will give you this template, hence IS_RESTRICTED flag.
|
||||
/datum/species/vox/pariah
|
||||
name = "Vox Pariah"
|
||||
rarity_value = 0.1
|
||||
speech_chance = 60 // No volume control.
|
||||
siemens_coefficient = 0.5 // Ragged scaleless patches.
|
||||
|
||||
warning_low_pressure = (WARNING_LOW_PRESSURE-20)
|
||||
hazard_low_pressure = (HAZARD_LOW_PRESSURE-10)
|
||||
total_health = 80
|
||||
|
||||
cold_level_1 = 130
|
||||
cold_level_2 = 100
|
||||
cold_level_3 = 60
|
||||
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite)
|
||||
|
||||
// Pariahs have no stack.
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_LUNGS = /obj/item/organ/internal/lungs,
|
||||
O_LIVER = /obj/item/organ/internal/liver,
|
||||
O_KIDNEYS = /obj/item/organ/internal/kidneys,
|
||||
O_BRAIN = /obj/item/organ/internal/pariah_brain,
|
||||
O_EYES = /obj/item/organ/internal/eyes
|
||||
)
|
||||
flags = IS_RESTRICTED | NO_SCAN | HAS_EYE_COLOR
|
||||
|
||||
// No combat skills for you.
|
||||
/datum/species/vox/pariah/can_shred(var/mob/living/carbon/human/H, var/ignore_intent)
|
||||
return 0
|
||||
|
||||
// Pariahs are really gross.
|
||||
/datum/species/vox/pariah/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
if(prob(5))
|
||||
var/stink_range = rand(3,5)
|
||||
for(var/mob/living/M in range(H,stink_range))
|
||||
if(M.stat || M == H)
|
||||
continue
|
||||
var/mob/living/carbon/human/target = M
|
||||
if(istype(target))
|
||||
if(target.internals)
|
||||
continue
|
||||
if(target.head && (target.head.body_parts_covered & FACE) && (target.head.flags & AIRTIGHT))
|
||||
continue
|
||||
if(target.wear_mask && (target.wear_mask.body_parts_covered & FACE) && (target.wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT))
|
||||
continue
|
||||
M << "<span class='danger'>A terrible stench emanates from \the [H].</span>"
|
||||
|
||||
/datum/species/vox/pariah/get_bodytype()
|
||||
return "Vox"
|
||||
@@ -1,159 +0,0 @@
|
||||
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
|
||||
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
|
||||
|
||||
/obj/item/alien_embryo
|
||||
name = "alien embryo"
|
||||
desc = "All slimy and yuck."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "larva0_dead"
|
||||
var/mob/living/affected_mob
|
||||
var/stage = 0
|
||||
|
||||
/obj/item/alien_embryo/New()
|
||||
if(istype(loc, /mob/living))
|
||||
affected_mob = loc
|
||||
processing_objects.Add(src)
|
||||
spawn(0)
|
||||
AddInfectionImages(affected_mob)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/item/alien_embryo/Destroy()
|
||||
if(affected_mob)
|
||||
affected_mob.status_flags &= ~(XENO_HOST)
|
||||
spawn(0)
|
||||
RemoveInfectionImages(affected_mob)
|
||||
..()
|
||||
|
||||
/obj/item/alien_embryo/process()
|
||||
if(!affected_mob) return
|
||||
if(loc != affected_mob)
|
||||
affected_mob.status_flags &= ~(XENO_HOST)
|
||||
processing_objects.Remove(src)
|
||||
spawn(0)
|
||||
RemoveInfectionImages(affected_mob)
|
||||
affected_mob = null
|
||||
return
|
||||
|
||||
if(stage < 5 && prob(3))
|
||||
stage++
|
||||
spawn(0)
|
||||
RefreshInfectionImage(affected_mob)
|
||||
|
||||
switch(stage)
|
||||
if(2, 3)
|
||||
if(prob(1))
|
||||
affected_mob.emote("sneeze")
|
||||
if(prob(1))
|
||||
affected_mob.emote("cough")
|
||||
if(prob(1))
|
||||
affected_mob << "\red Your throat feels sore."
|
||||
if(prob(1))
|
||||
affected_mob << "\red Mucous runs down the back of your throat."
|
||||
if(4)
|
||||
if(prob(1))
|
||||
affected_mob.emote("sneeze")
|
||||
if(prob(1))
|
||||
affected_mob.emote("cough")
|
||||
if(prob(2))
|
||||
affected_mob << "\red Your muscles ache."
|
||||
if(prob(20))
|
||||
affected_mob.take_organ_damage(1)
|
||||
if(prob(2))
|
||||
affected_mob << "\red Your stomach hurts."
|
||||
if(prob(20))
|
||||
affected_mob.adjustToxLoss(1)
|
||||
affected_mob.updatehealth()
|
||||
if(5)
|
||||
affected_mob << "\red You feel something tearing its way out of your stomach..."
|
||||
affected_mob.adjustToxLoss(10)
|
||||
affected_mob.updatehealth()
|
||||
if(prob(50))
|
||||
AttemptGrow()
|
||||
|
||||
/obj/item/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1)
|
||||
var/list/candidates = get_alien_candidates()
|
||||
var/picked = null
|
||||
|
||||
// To stop clientless larva, we will check that our host has a client
|
||||
// if we find no ghosts to become the alien. If the host has a client
|
||||
// he will become the alien but if he doesn't then we will set the stage
|
||||
// to 2, so we don't do a process heavy check everytime.
|
||||
|
||||
if(candidates.len)
|
||||
picked = pick(candidates)
|
||||
else if(affected_mob.client)
|
||||
picked = affected_mob.key
|
||||
else
|
||||
stage = 4 // Let's try again later.
|
||||
return
|
||||
|
||||
if(affected_mob.lying)
|
||||
affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_lie")
|
||||
else
|
||||
affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand")
|
||||
spawn(6)
|
||||
var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc)
|
||||
new_xeno.key = picked
|
||||
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
|
||||
if(gib_on_success)
|
||||
affected_mob.gib()
|
||||
qdel(src)
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: RefreshInfectionImage()
|
||||
Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens.
|
||||
----------------------------------------*/
|
||||
/obj/item/alien_embryo/proc/RefreshInfectionImage()
|
||||
|
||||
for(var/mob/living/carbon/alien in player_list)
|
||||
|
||||
if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs)
|
||||
continue
|
||||
|
||||
if(alien.client)
|
||||
for(var/image/I in alien.client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
qdel(I)
|
||||
for(var/mob/living/L in mob_list)
|
||||
if(iscorgi(L) || iscarbon(L))
|
||||
if(L.status_flags & XENO_HOST)
|
||||
var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]")
|
||||
alien.client.images += I
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: AddInfectionImages(C)
|
||||
Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C.
|
||||
----------------------------------------*/
|
||||
/obj/item/alien_embryo/proc/AddInfectionImages(var/mob/living/C)
|
||||
if(C)
|
||||
|
||||
for(var/mob/living/carbon/alien in player_list)
|
||||
|
||||
if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs)
|
||||
continue
|
||||
|
||||
if(alien.client)
|
||||
if(C.status_flags & XENO_HOST)
|
||||
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]")
|
||||
alien.client.images += I
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: RemoveInfectionImage(C)
|
||||
Des: Removes the alien infection image from all aliens in the world located in passed mob (C).
|
||||
----------------------------------------*/
|
||||
|
||||
/obj/item/alien_embryo/proc/RemoveInfectionImages(var/mob/living/C)
|
||||
|
||||
if(C)
|
||||
|
||||
for(var/mob/living/carbon/alien in player_list)
|
||||
|
||||
if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs)
|
||||
continue
|
||||
|
||||
if(alien.client)
|
||||
for(var/image/I in alien.client.images)
|
||||
if(I.loc == C)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
qdel(I)
|
||||
@@ -1,231 +0,0 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
//TODO: Make these simple_animals
|
||||
|
||||
var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone
|
||||
var/const/MAX_IMPREGNATION_TIME = 150
|
||||
|
||||
var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle
|
||||
var/const/MAX_ACTIVE_TIME = 400
|
||||
|
||||
/obj/item/clothing/mask/facehugger
|
||||
name = "alien"
|
||||
desc = "It has some sort of a tube at the end of its tail."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "facehugger"
|
||||
item_state = "facehugger"
|
||||
w_class = 3 //note: can be picked up by aliens unlike most other items of w_class below 4
|
||||
flags = PROXMOVE
|
||||
body_parts_covered = FACE|EYES
|
||||
throw_range = 5
|
||||
|
||||
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
|
||||
var/sterile = 0
|
||||
var/strength = 5
|
||||
var/attached = 0
|
||||
|
||||
/obj/item/clothing/mask/facehugger/attack_hand(user as mob)
|
||||
|
||||
if((stat == CONSCIOUS && !sterile))
|
||||
if(Attach(user))
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob)
|
||||
..()
|
||||
user.drop_from_inventory(src)
|
||||
Attach(M)
|
||||
|
||||
/obj/item/clothing/mask/facehugger/New()
|
||||
if(config.aliens_allowed)
|
||||
..()
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/item/clothing/mask/facehugger/examine(mob/user)
|
||||
..(user)
|
||||
switch(stat)
|
||||
if(DEAD,UNCONSCIOUS)
|
||||
user << "\red \b [src] is not moving."
|
||||
if(CONSCIOUS)
|
||||
user << "\red \b [src] seems to be active."
|
||||
if (sterile)
|
||||
user << "\red \b It looks like the proboscis has been removed."
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/attackby(obj/item/I, mob/user)
|
||||
if(I.force)
|
||||
user.do_attack_animation(src)
|
||||
Die()
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/bullet_act()
|
||||
Die()
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > T0C+80)
|
||||
Die()
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/equipped(mob/M)
|
||||
..()
|
||||
Attach(M)
|
||||
|
||||
/obj/item/clothing/mask/facehugger/Crossed(atom/target)
|
||||
HasProximity(target)
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/on_found(mob/finder as mob)
|
||||
if(stat == CONSCIOUS)
|
||||
HasProximity(finder)
|
||||
return 1
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj)
|
||||
if(CanHug(AM))
|
||||
Attach(AM)
|
||||
|
||||
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed)
|
||||
..()
|
||||
if(stat == CONSCIOUS)
|
||||
icon_state = "[initial(icon_state)]_thrown"
|
||||
spawn(15)
|
||||
if(icon_state == "[initial(icon_state)]_thrown")
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom)
|
||||
..()
|
||||
if(stat == CONSCIOUS)
|
||||
icon_state = "[initial(icon_state)]"
|
||||
throwing = 0
|
||||
GoIdle(30,100) //stunned for a few seconds - allows throwing them to be useful for positioning but not as an offensive action (unless you're setting up a trap)
|
||||
|
||||
/obj/item/clothing/mask/facehugger/proc/Attach(M as mob)
|
||||
|
||||
if((!iscorgi(M) && !iscarbon(M)))
|
||||
return
|
||||
|
||||
if(attached)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = M
|
||||
if(istype(C) && locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
|
||||
return
|
||||
|
||||
|
||||
attached++
|
||||
spawn(MAX_IMPREGNATION_TIME)
|
||||
attached = 0
|
||||
|
||||
var/mob/living/L = M //just so I don't need to use :
|
||||
|
||||
if(loc == L) return
|
||||
if(stat != CONSCIOUS) return
|
||||
if(!sterile) L.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage
|
||||
|
||||
L.visible_message("\red \b [src] leaps at [L]'s face!")
|
||||
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/target = L
|
||||
|
||||
if(target.wear_mask)
|
||||
if(prob(20)) return
|
||||
var/obj/item/clothing/W = target.wear_mask
|
||||
if(!W.canremove) return
|
||||
target.drop_from_inventory(W)
|
||||
|
||||
target.visible_message("\red \b [src] tears [W] off of [target]'s face!")
|
||||
|
||||
target.equip_to_slot(src, slot_wear_mask)
|
||||
target.contents += src // Monkey sanity check - Snapshot
|
||||
|
||||
if(!sterile) L.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
|
||||
else if (iscorgi(M))
|
||||
var/mob/living/simple_animal/corgi/corgi = M
|
||||
src.loc = corgi
|
||||
corgi.facehugger = src
|
||||
corgi.wear_mask = src
|
||||
//C.regenerate_icons()
|
||||
|
||||
GoIdle() //so it doesn't jump the people that tear it off
|
||||
|
||||
spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME))
|
||||
Impregnate(L)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target as mob)
|
||||
if(!target || target.wear_mask != src || target.stat == DEAD) //was taken off or something
|
||||
return
|
||||
|
||||
if(!sterile)
|
||||
new /obj/item/alien_embryo(target)
|
||||
target.status_flags |= XENO_HOST
|
||||
|
||||
target.visible_message("\red \b [src] falls limp after violating [target]'s face!")
|
||||
|
||||
Die()
|
||||
icon_state = "[initial(icon_state)]_impregnated"
|
||||
|
||||
if(iscorgi(target))
|
||||
var/mob/living/simple_animal/corgi/C = target
|
||||
src.loc = get_turf(C)
|
||||
C.facehugger = null
|
||||
else
|
||||
target.visible_message("\red \b [src] violates [target]'s face!")
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/proc/GoActive()
|
||||
if(stat == DEAD || stat == CONSCIOUS)
|
||||
return
|
||||
|
||||
stat = CONSCIOUS
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/proc/GoIdle(var/min_time=MIN_ACTIVE_TIME, var/max_time=MAX_ACTIVE_TIME)
|
||||
if(stat == DEAD || stat == UNCONSCIOUS)
|
||||
return
|
||||
|
||||
/* RemoveActiveIndicators() */
|
||||
|
||||
stat = UNCONSCIOUS
|
||||
icon_state = "[initial(icon_state)]_inactive"
|
||||
|
||||
spawn(rand(min_time,max_time))
|
||||
GoActive()
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/facehugger/proc/Die()
|
||||
if(stat == DEAD)
|
||||
return
|
||||
|
||||
/* RemoveActiveIndicators() */
|
||||
|
||||
icon_state = "[initial(icon_state)]_dead"
|
||||
stat = DEAD
|
||||
|
||||
src.visible_message("\red \b[src] curls up into a ball!")
|
||||
|
||||
return
|
||||
|
||||
/proc/CanHug(var/mob/M)
|
||||
|
||||
if(iscorgi(M))
|
||||
return 1
|
||||
|
||||
if(!iscarbon(M))
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/C = M
|
||||
if(istype(C) && locate(/obj/item/organ/internal/xenos/hivenode) in C.internal_organs)
|
||||
return 0
|
||||
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(H.head && (H.head.body_parts_covered & FACE) && !(H.head.item_flags & FLEXIBLEMATERIAL))
|
||||
return 0
|
||||
return 1
|
||||
@@ -1,222 +0,0 @@
|
||||
/proc/alien_queen_exists(var/ignore_self,var/mob/living/carbon/human/self)
|
||||
for(var/mob/living/carbon/human/Q in living_mob_list)
|
||||
if(self && ignore_self && self == Q)
|
||||
continue
|
||||
if(Q.species.name != "Xenomorph Queen")
|
||||
continue
|
||||
if(!Q.key || !Q.client || Q.stat)
|
||||
continue
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/gain_plasma(var/amount)
|
||||
|
||||
var/obj/item/organ/internal/xenos/plasmavessel/I = internal_organs_by_name[O_PLASMA]
|
||||
if(!istype(I)) return
|
||||
|
||||
if(amount)
|
||||
I.stored_plasma += amount
|
||||
I.stored_plasma = max(0,min(I.stored_plasma,I.max_plasma))
|
||||
|
||||
/mob/living/carbon/human/proc/check_alien_ability(var/cost,var/needs_foundation,var/needs_organ)
|
||||
|
||||
var/obj/item/organ/internal/xenos/plasmavessel/P = internal_organs_by_name[O_PLASMA]
|
||||
if(!istype(P))
|
||||
src << "<span class='danger'>Your plasma vessel has been removed!</span>"
|
||||
return
|
||||
|
||||
if(needs_organ)
|
||||
var/obj/item/organ/internal/I = internal_organs_by_name[needs_organ]
|
||||
if(!I)
|
||||
src << "<span class='danger'>Your [needs_organ] has been removed!</span>"
|
||||
return
|
||||
else if((I.status & ORGAN_CUT_AWAY) || I.is_broken())
|
||||
src << "<span class='danger'>Your [needs_organ] is too damaged to function!</span>"
|
||||
return
|
||||
|
||||
if(P.stored_plasma < cost)
|
||||
src << "\red You don't have enough phoron stored to do that."
|
||||
return 0
|
||||
|
||||
if(needs_foundation)
|
||||
var/turf/T = get_turf(src)
|
||||
var/has_foundation
|
||||
if(T)
|
||||
//TODO: Work out the actual conditions this needs.
|
||||
if(!(istype(T,/turf/space)))
|
||||
has_foundation = 1
|
||||
if(!has_foundation)
|
||||
src << "\red You need a solid foundation to do that on."
|
||||
return 0
|
||||
|
||||
P.stored_plasma -= cost
|
||||
return 1
|
||||
|
||||
// Free abilities.
|
||||
/mob/living/carbon/human/proc/transfer_plasma(mob/living/carbon/human/M as mob in oview())
|
||||
set name = "Transfer Plasma"
|
||||
set desc = "Transfer Plasma to another alien"
|
||||
set category = "Abilities"
|
||||
|
||||
if (get_dist(src,M) <= 1)
|
||||
src << "<span class='alium'>You need to be closer.</span>"
|
||||
return
|
||||
|
||||
var/obj/item/organ/internal/xenos/plasmavessel/I = M.internal_organs_by_name[O_PLASMA]
|
||||
if(!istype(I))
|
||||
src << "<span class='alium'>Their plasma vessel is missing.</span>"
|
||||
return
|
||||
|
||||
var/amount = input("Amount:", "Transfer Plasma to [M]") as num
|
||||
if (amount)
|
||||
amount = abs(round(amount))
|
||||
if(check_alien_ability(amount,0,O_PLASMA))
|
||||
M.gain_plasma(amount)
|
||||
M << "<span class='alium'>[src] has transfered [amount] plasma to you.</span>"
|
||||
src << "<span class='alium'>You have transferred [amount] plasma to [M].</span>"
|
||||
return
|
||||
|
||||
// Queen verbs.
|
||||
/mob/living/carbon/human/proc/lay_egg()
|
||||
|
||||
set name = "Lay Egg (75)"
|
||||
set desc = "Lay an egg to produce huggers to impregnate prey with."
|
||||
set category = "Abilities"
|
||||
|
||||
if(!config.aliens_allowed)
|
||||
src << "You begin to lay an egg, but hesitate. You suspect it isn't allowed."
|
||||
verbs -= /mob/living/carbon/human/proc/lay_egg
|
||||
return
|
||||
|
||||
if(locate(/obj/effect/alien/egg) in get_turf(src))
|
||||
src << "There's already an egg here."
|
||||
return
|
||||
|
||||
if(check_alien_ability(75,1,O_EGG))
|
||||
visible_message("<span class='alium'><B>[src] has laid an egg!</B></span>")
|
||||
new /obj/effect/alien/egg(loc)
|
||||
|
||||
return
|
||||
|
||||
// Drone verbs.
|
||||
/mob/living/carbon/human/proc/evolve()
|
||||
set name = "Evolve (500)"
|
||||
set desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time."
|
||||
set category = "Abilities"
|
||||
|
||||
if(alien_queen_exists())
|
||||
src << "<span class='notice'>We already have an active queen.</span>"
|
||||
return
|
||||
|
||||
if(check_alien_ability(500))
|
||||
visible_message("<span class='alium'><B>[src] begins to twist and contort!</B></span>", "<span class='alium'>You begin to evolve!</span>")
|
||||
src.set_species("Xenomorph Queen")
|
||||
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/plant()
|
||||
set name = "Plant Weeds (50)"
|
||||
set desc = "Plants some alien weeds"
|
||||
set category = "Abilities"
|
||||
|
||||
if(check_alien_ability(50,1,O_RESIN))
|
||||
visible_message("<span class='alium'><B>[src] has planted some alien weeds!</B></span>")
|
||||
new /obj/effect/alien/weeds/node(loc)
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N
|
||||
set name = "Corrosive Acid (200)"
|
||||
set desc = "Drench an object in acid, destroying it over time."
|
||||
set category = "Abilities"
|
||||
|
||||
if(!O in oview(1))
|
||||
src << "<span class='alium'>[O] is too far away.</span>"
|
||||
return
|
||||
|
||||
// OBJ CHECK
|
||||
var/cannot_melt
|
||||
if(isobj(O))
|
||||
var/obj/I = O
|
||||
if(I.unacidable)
|
||||
cannot_melt = 1
|
||||
else
|
||||
if(istype(O, /turf/simulated/wall))
|
||||
var/turf/simulated/wall/W = O
|
||||
if(W.material.flags & MATERIAL_UNMELTABLE)
|
||||
cannot_melt = 1
|
||||
else if(istype(O, /turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = O
|
||||
if(F.flooring && (F.flooring.flags & TURF_ACID_IMMUNE))
|
||||
cannot_melt = 1
|
||||
|
||||
if(cannot_melt)
|
||||
src << "<span class='alium'>You cannot dissolve this object.</span>"
|
||||
return
|
||||
|
||||
if(check_alien_ability(200,0,O_ACID))
|
||||
new /obj/effect/alien/acid(get_turf(O), O)
|
||||
visible_message("<span class='alium'><B>[src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!</B></span>")
|
||||
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/neurotoxin(mob/target as mob in oview())
|
||||
set name = "Spit Neurotoxin (50)"
|
||||
set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear."
|
||||
set category = "Abilities"
|
||||
|
||||
if(!check_alien_ability(50,0,O_ACID))
|
||||
return
|
||||
|
||||
if(stat || paralysis || stunned || weakened || lying || restrained() || buckled)
|
||||
src << "You cannot spit neurotoxin in your current state."
|
||||
return
|
||||
|
||||
visible_message("<span class='warning'>[src] spits neurotoxin at [target]!</span>", "<span class='alium'>You spit neurotoxin at [target].</span>")
|
||||
|
||||
//I'm not motivated enough to revise this. Prjectile code in general needs update.
|
||||
// Maybe change this to use throw_at? ~ Z
|
||||
var/turf/T = loc
|
||||
var/turf/U = (istype(target, /atom/movable) ? target.loc : target)
|
||||
|
||||
if(!U || !T)
|
||||
return
|
||||
while(U && !istype(U,/turf))
|
||||
U = U.loc
|
||||
if(!istype(T, /turf))
|
||||
return
|
||||
if (U == T)
|
||||
usr.bullet_act(new /obj/item/projectile/energy/neurotoxin(usr.loc), get_organ_target())
|
||||
return
|
||||
if(!istype(U, /turf))
|
||||
return
|
||||
|
||||
var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc)
|
||||
A.current = U
|
||||
A.yo = U.y - T.y
|
||||
A.xo = U.x - T.x
|
||||
A.process()
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/resin() // -- TLE
|
||||
set name = "Secrete Resin (75)"
|
||||
set desc = "Secrete tough malleable resin."
|
||||
set category = "Abilities"
|
||||
|
||||
var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin door","resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
if(!check_alien_ability(75,1,O_RESIN))
|
||||
return
|
||||
|
||||
visible_message("<span class='warning'><B>[src] vomits up a thick purple substance and begins to shape it!</B></span>", "<span class='alium'>You shape a [choice].</span>")
|
||||
switch(choice)
|
||||
if("resin door")
|
||||
new /obj/structure/simple_door/resin(loc)
|
||||
if("resin wall")
|
||||
new /obj/effect/alien/resin/wall(loc)
|
||||
if("resin membrane")
|
||||
new /obj/effect/alien/resin/membrane(loc)
|
||||
if("resin nest")
|
||||
new /obj/structure/bed/nest(loc)
|
||||
return
|
||||
@@ -1,326 +0,0 @@
|
||||
//Stand-in until this is made more lore-friendly.
|
||||
/datum/species/xenos
|
||||
name = "Xenomorph"
|
||||
name_plural = "Xenomorphs"
|
||||
|
||||
default_language = "Xenomorph"
|
||||
language = "Hivemind"
|
||||
unarmed_types = list(/datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong)
|
||||
hud_type = /datum/hud_data/alien
|
||||
rarity_value = 3
|
||||
|
||||
has_fine_manipulation = 0
|
||||
siemens_coefficient = 0
|
||||
gluttonous = 3
|
||||
|
||||
brute_mod = 0.5 // Hardened carapace.
|
||||
burn_mod = 2 // Weak to fire.
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = -1
|
||||
|
||||
cold_level_1 = 50
|
||||
cold_level_2 = -1
|
||||
cold_level_3 = -1
|
||||
|
||||
flags = NO_SCAN | NO_PAIN | NO_SLIP | NO_POISON | NO_MINOR_CUT
|
||||
spawn_flags = IS_RESTRICTED
|
||||
|
||||
reagent_tag = IS_XENOS
|
||||
|
||||
blood_color = "#05EE05"
|
||||
flesh_color = "#282846"
|
||||
gibbed_anim = "gibbed-a"
|
||||
dusted_anim = "dust-a"
|
||||
death_message = "lets out a waning guttural screech, green blood bubbling from its maw."
|
||||
death_sound = 'sound/voice/hiss6.ogg'
|
||||
|
||||
speech_sounds = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg')
|
||||
speech_chance = 100
|
||||
|
||||
breath_type = null
|
||||
poison_type = null
|
||||
|
||||
vision_flags = SEE_SELF|SEE_MOBS
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/xeno,
|
||||
O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel,
|
||||
O_HIVE = /obj/item/organ/internal/xenos/hivenode,
|
||||
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients
|
||||
)
|
||||
|
||||
bump_flag = ALIEN
|
||||
swap_flags = ~HEAVY
|
||||
push_flags = (~HEAVY) ^ ROBOT
|
||||
|
||||
var/alien_number = 0
|
||||
var/caste_name = "creature" // Used to update alien name.
|
||||
var/weeds_heal_rate = 1 // Health regen on weeds.
|
||||
var/weeds_plasma_rate = 5 // Plasma regen on weeds.
|
||||
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest),
|
||||
BP_GROIN = list("path" = /obj/item/organ/external/groin),
|
||||
BP_HEAD = list("path" = /obj/item/organ/external/head/no_eyes),
|
||||
BP_L_ARM = list("path" = /obj/item/organ/external/arm),
|
||||
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
|
||||
BP_L_LEG = list("path" = /obj/item/organ/external/leg),
|
||||
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
|
||||
BP_L_HAND = list("path" = /obj/item/organ/external/hand),
|
||||
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
|
||||
BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
|
||||
)
|
||||
|
||||
/datum/species/xenos/get_bodytype()
|
||||
return "Xenomorph"
|
||||
|
||||
/datum/species/xenos/get_random_name()
|
||||
return "alien [caste_name] ([alien_number])"
|
||||
|
||||
/datum/species/xenos/can_understand(var/mob/other)
|
||||
|
||||
if(istype(other,/mob/living/carbon/alien/larva))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/datum/species/xenos/hug(var/mob/living/carbon/human/H,var/mob/living/target)
|
||||
H.visible_message("<span class='notice'>[H] caresses [target] with its scythe-like arm.</span>", \
|
||||
"<span class='notice'>You caress [target] with your scythe-like arm.</span>")
|
||||
|
||||
/datum/species/xenos/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
|
||||
if(H.mind)
|
||||
H.mind.assigned_role = "Alien"
|
||||
H.mind.special_role = "Alien"
|
||||
|
||||
alien_number++ //Keep track of how many aliens we've had so far.
|
||||
H.real_name = "alien [caste_name] ([alien_number])"
|
||||
H.name = H.real_name
|
||||
|
||||
..()
|
||||
|
||||
/datum/species/xenos/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
|
||||
var/turf/T = H.loc
|
||||
if(!T) return
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
if(!environment) return
|
||||
|
||||
if(environment.gas["phoron"] > 0 || locate(/obj/effect/alien/weeds) in T)
|
||||
if(!regenerate(H))
|
||||
var/obj/item/organ/internal/xenos/plasmavessel/P = H.internal_organs_by_name[O_PLASMA]
|
||||
P.stored_plasma += weeds_plasma_rate
|
||||
P.stored_plasma = min(max(P.stored_plasma,0),P.max_plasma)
|
||||
..()
|
||||
|
||||
/datum/species/xenos/proc/regenerate(var/mob/living/carbon/human/H)
|
||||
var/heal_rate = weeds_heal_rate
|
||||
var/mend_prob = 10
|
||||
if (!H.resting)
|
||||
heal_rate = weeds_heal_rate / 3
|
||||
mend_prob = 1
|
||||
|
||||
//first heal damages
|
||||
if (H.getBruteLoss() || H.getFireLoss() || H.getOxyLoss() || H.getToxLoss())
|
||||
H.adjustBruteLoss(-heal_rate)
|
||||
H.adjustFireLoss(-heal_rate)
|
||||
H.adjustOxyLoss(-heal_rate)
|
||||
H.adjustToxLoss(-heal_rate)
|
||||
if (prob(5))
|
||||
H << "<span class='alium'>You feel a soothing sensation come over you...</span>"
|
||||
return 1
|
||||
|
||||
//next internal organs
|
||||
for(var/obj/item/organ/I in H.internal_organs)
|
||||
if(I.damage > 0)
|
||||
I.damage = max(I.damage - heal_rate, 0)
|
||||
if (prob(5))
|
||||
H << "<span class='alium'>You feel a soothing sensation within your [I.parent_organ]...</span>"
|
||||
return 1
|
||||
|
||||
//next mend broken bones, approx 10 ticks each
|
||||
for(var/obj/item/organ/external/E in H.bad_external_organs)
|
||||
if (E.status & ORGAN_BROKEN)
|
||||
if (prob(mend_prob))
|
||||
if (E.mend_fracture())
|
||||
H << "<span class='alium'>You feel something mend itself inside your [E.name].</span>"
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/datum/species/xenos/handle_login_special(var/mob/living/carbon/human/H)
|
||||
H.AddInfectionImages()
|
||||
..()
|
||||
|
||||
/datum/species/xenos/handle_logout_special(var/mob/living/carbon/human/H)
|
||||
H.RemoveInfectionImages()
|
||||
..()
|
||||
|
||||
/datum/species/xenos/drone
|
||||
name = "Xenomorph Drone"
|
||||
caste_name = "drone"
|
||||
weeds_plasma_rate = 15
|
||||
slowdown = 1
|
||||
tail = "xenos_drone_tail"
|
||||
rarity_value = 5
|
||||
|
||||
icobase = 'icons/mob/human_races/xenos/r_xenos_drone.dmi'
|
||||
deform = 'icons/mob/human_races/xenos/r_xenos_drone.dmi'
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/xeno,
|
||||
O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/queen,
|
||||
O_ACID = /obj/item/organ/internal/xenos/acidgland,
|
||||
O_HIVE = /obj/item/organ/internal/xenos/hivenode,
|
||||
O_RESIN = /obj/item/organ/internal/xenos/resinspinner,
|
||||
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients
|
||||
)
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/proc/ventcrawl,
|
||||
/mob/living/carbon/human/proc/regurgitate,
|
||||
/mob/living/carbon/human/proc/plant,
|
||||
/mob/living/carbon/human/proc/transfer_plasma,
|
||||
/mob/living/carbon/human/proc/evolve,
|
||||
/mob/living/carbon/human/proc/resin,
|
||||
/mob/living/carbon/human/proc/corrosive_acid
|
||||
)
|
||||
|
||||
/datum/species/xenos/drone/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
|
||||
var/mob/living/carbon/human/A = H
|
||||
if(!istype(A))
|
||||
return ..()
|
||||
..()
|
||||
|
||||
/datum/species/xenos/hunter
|
||||
|
||||
name = "Xenomorph Hunter"
|
||||
weeds_plasma_rate = 5
|
||||
caste_name = "hunter"
|
||||
slowdown = -2
|
||||
total_health = 150
|
||||
tail = "xenos_hunter_tail"
|
||||
|
||||
icobase = 'icons/mob/human_races/xenos/r_xenos_hunter.dmi'
|
||||
deform = 'icons/mob/human_races/xenos/r_xenos_hunter.dmi'
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/xeno,
|
||||
O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/hunter,
|
||||
O_HIVE = /obj/item/organ/internal/xenos/hivenode,
|
||||
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients
|
||||
)
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/proc/ventcrawl,
|
||||
/mob/living/carbon/human/proc/tackle,
|
||||
/mob/living/carbon/human/proc/gut,
|
||||
/mob/living/carbon/human/proc/leap,
|
||||
/mob/living/carbon/human/proc/psychic_whisper,
|
||||
/mob/living/carbon/human/proc/regurgitate
|
||||
)
|
||||
|
||||
/datum/species/xenos/sentinel
|
||||
name = "Xenomorph Sentinel"
|
||||
weeds_plasma_rate = 10
|
||||
caste_name = "sentinel"
|
||||
slowdown = 0
|
||||
total_health = 125
|
||||
tail = "xenos_sentinel_tail"
|
||||
|
||||
icobase = 'icons/mob/human_races/xenos/r_xenos_sentinel.dmi'
|
||||
deform = 'icons/mob/human_races/xenos/r_xenos_sentinel.dmi'
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/xeno,
|
||||
O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/sentinel,
|
||||
O_ACID = /obj/item/organ/internal/xenos/acidgland,
|
||||
O_HIVE = /obj/item/organ/internal/xenos/hivenode,
|
||||
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients
|
||||
)
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/proc/ventcrawl,
|
||||
/mob/living/carbon/human/proc/tackle,
|
||||
/mob/living/carbon/human/proc/regurgitate,
|
||||
/mob/living/carbon/human/proc/transfer_plasma,
|
||||
/mob/living/carbon/human/proc/corrosive_acid,
|
||||
/mob/living/carbon/human/proc/neurotoxin
|
||||
)
|
||||
|
||||
/datum/species/xenos/queen
|
||||
|
||||
name = "Xenomorph Queen"
|
||||
total_health = 250
|
||||
weeds_heal_rate = 5
|
||||
weeds_plasma_rate = 20
|
||||
caste_name = "queen"
|
||||
slowdown = 4
|
||||
tail = "xenos_queen_tail"
|
||||
rarity_value = 10
|
||||
|
||||
icobase = 'icons/mob/human_races/xenos/r_xenos_queen.dmi'
|
||||
deform = 'icons/mob/human_races/xenos/r_xenos_queen.dmi'
|
||||
|
||||
has_organ = list(
|
||||
O_HEART = /obj/item/organ/internal/heart,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/xeno,
|
||||
O_EGG = /obj/item/organ/internal/xenos/eggsac,
|
||||
O_PLASMA = /obj/item/organ/internal/xenos/plasmavessel/queen,
|
||||
O_ACID = /obj/item/organ/internal/xenos/acidgland,
|
||||
O_HIVE = /obj/item/organ/internal/xenos/hivenode,
|
||||
O_RESIN = /obj/item/organ/internal/xenos/resinspinner,
|
||||
O_NUTRIENT = /obj/item/organ/internal/diona/nutrients
|
||||
)
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/proc/ventcrawl,
|
||||
/mob/living/carbon/human/proc/psychic_whisper,
|
||||
/mob/living/carbon/human/proc/regurgitate,
|
||||
/mob/living/carbon/human/proc/lay_egg,
|
||||
/mob/living/carbon/human/proc/plant,
|
||||
/mob/living/carbon/human/proc/transfer_plasma,
|
||||
/mob/living/carbon/human/proc/corrosive_acid,
|
||||
/mob/living/carbon/human/proc/neurotoxin,
|
||||
/mob/living/carbon/human/proc/resin
|
||||
)
|
||||
|
||||
/datum/species/xenos/queen/handle_login_special(var/mob/living/carbon/human/H)
|
||||
..()
|
||||
// Make sure only one official queen exists at any point.
|
||||
if(!alien_queen_exists(1,H))
|
||||
H.real_name = "alien queen ([alien_number])"
|
||||
H.name = H.real_name
|
||||
else
|
||||
H.real_name = "alien princess ([alien_number])"
|
||||
H.name = H.real_name
|
||||
|
||||
/datum/hud_data/alien
|
||||
|
||||
icon = 'icons/mob/screen1_alien.dmi'
|
||||
has_a_intent = 1
|
||||
has_m_intent = 1
|
||||
has_warnings = 1
|
||||
has_hands = 1
|
||||
has_drop = 1
|
||||
has_throw = 1
|
||||
has_resist = 1
|
||||
has_pressure = 0
|
||||
has_nutrition = 0
|
||||
has_bodytemp = 0
|
||||
has_internals = 0
|
||||
|
||||
gear = list(
|
||||
"o_clothing" = list("loc" = ui_belt, "name" = "Suit", "slot" = slot_wear_suit, "state" = "equip", "dir" = SOUTH),
|
||||
"head" = list("loc" = ui_id, "name" = "Hat", "slot" = slot_head, "state" = "hair"),
|
||||
"storage1" = list("loc" = ui_storage1, "name" = "Left Pocket", "slot" = slot_l_store, "state" = "pocket"),
|
||||
"storage2" = list("loc" = ui_storage2, "name" = "Right Pocket", "slot" = slot_r_store, "state" = "pocket"),
|
||||
)
|
||||
@@ -1,49 +0,0 @@
|
||||
proc/create_new_xenomorph(var/alien_caste,var/target)
|
||||
|
||||
target = get_turf(target)
|
||||
if(!target || !alien_caste) return
|
||||
|
||||
var/mob/living/carbon/human/new_alien = new(target)
|
||||
new_alien.set_species("Xenomorph [alien_caste]")
|
||||
return new_alien
|
||||
|
||||
/mob/living/carbon/human/xdrone/New(var/new_loc)
|
||||
h_style = "Bald"
|
||||
..(new_loc, "Xenomorph Drone")
|
||||
|
||||
/mob/living/carbon/human/xsentinel/New(var/new_loc)
|
||||
h_style = "Bald"
|
||||
..(new_loc, "Xenomorph Sentinel")
|
||||
|
||||
/mob/living/carbon/human/xhunter/New(var/new_loc)
|
||||
h_style = "Bald"
|
||||
..(new_loc, "Xenomorph Hunter")
|
||||
|
||||
/mob/living/carbon/human/xqueen/New(var/new_loc)
|
||||
h_style = "Bald"
|
||||
..(new_loc, "Xenomorph Queen")
|
||||
|
||||
// I feel like we should generalize/condense down all the various icon-rendering antag procs.
|
||||
/*----------------------------------------
|
||||
Proc: AddInfectionImages()
|
||||
Des: Gives the client of the alien an image on each infected mob.
|
||||
----------------------------------------*/
|
||||
/mob/living/carbon/human/proc/AddInfectionImages()
|
||||
if (client)
|
||||
for (var/mob/living/C in mob_list)
|
||||
if(C.status_flags & XENO_HOST)
|
||||
var/obj/item/alien_embryo/A = locate() in C
|
||||
var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]")
|
||||
client.images += I
|
||||
return
|
||||
|
||||
/*----------------------------------------
|
||||
Proc: RemoveInfectionImages()
|
||||
Des: Removes all infected images from the alien.
|
||||
----------------------------------------*/
|
||||
/mob/living/carbon/human/proc/RemoveInfectionImages()
|
||||
if (client)
|
||||
for(var/image/I in client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
qdel(I)
|
||||
return
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_back
|
||||
var/facehugger
|
||||
|
||||
//IAN! SQUEEEEEEEEE~
|
||||
/mob/living/simple_animal/corgi/Ian
|
||||
@@ -124,12 +123,6 @@
|
||||
if(back_icon)
|
||||
overlays += back_icon
|
||||
|
||||
if(facehugger)
|
||||
if(istype(src, /mob/living/simple_animal/corgi/puppy))
|
||||
overlays += image('icons/mob/mask.dmi',"facehugger_corgipuppy")
|
||||
else
|
||||
overlays += image('icons/mob/mask.dmi',"facehugger_corgi")
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,18 @@
|
||||
emote_see = list("jiggles", "bounces in place")
|
||||
var/colour = "grey"
|
||||
|
||||
/mob/living/simple_animal/slime/science
|
||||
name = "Kendrick"
|
||||
colour = "rainbow"
|
||||
icon_state = "rainbow baby slime"
|
||||
icon_living = "rainbow baby slime"
|
||||
icon_dead = "rainbow baby slime dead"
|
||||
|
||||
/mob/living/simple_animal/slime/science/initialize()
|
||||
..()
|
||||
overlays.Cut()
|
||||
overlays += "aslime-:33"
|
||||
|
||||
/mob/living/simple_animal/adultslime
|
||||
name = "pet slime"
|
||||
desc = "A lovable, domesticated slime."
|
||||
@@ -33,8 +45,7 @@
|
||||
..()
|
||||
overlays += "aslime-:33"
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/adult/death()
|
||||
/mob/living/simple_animal/adultslime/death()
|
||||
var/mob/living/simple_animal/slime/S1 = new /mob/living/simple_animal/slime (src.loc)
|
||||
S1.icon_state = "[src.colour] baby slime"
|
||||
S1.icon_living = "[src.colour] baby slime"
|
||||
|
||||
@@ -50,13 +50,6 @@
|
||||
stance = HOSTILE_STANCE_ATTACK
|
||||
T = M
|
||||
break
|
||||
|
||||
if(istype(A, /obj/machinery/bot))
|
||||
var/obj/machinery/bot/B = A
|
||||
if (B.health > 0)
|
||||
stance = HOSTILE_STANCE_ATTACK
|
||||
T = B
|
||||
break
|
||||
return T
|
||||
|
||||
|
||||
@@ -101,9 +94,6 @@
|
||||
var/obj/mecha/M = target_mob
|
||||
M.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext)
|
||||
return M
|
||||
if(istype(target_mob,/obj/machinery/bot))
|
||||
var/obj/machinery/bot/B = target_mob
|
||||
B.attack_generic(src,rand(melee_damage_lower,melee_damage_upper),attacktext)
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/LoseTarget()
|
||||
stance = HOSTILE_STANCE_IDLE
|
||||
|
||||
@@ -359,10 +359,6 @@
|
||||
var/obj/mecha/M = target_mob
|
||||
if (M.occupant)
|
||||
return (0)
|
||||
if (istype(target_mob,/obj/machinery/bot))
|
||||
var/obj/machinery/bot/B = target_mob
|
||||
if(B.health > 0)
|
||||
return (0)
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/say(var/message)
|
||||
|
||||
@@ -505,17 +505,6 @@
|
||||
namecounts[name] = 1
|
||||
creatures[name] = O
|
||||
|
||||
if(istype(O, /obj/machinery/bot))
|
||||
var/name = "BOT: [O.name]"
|
||||
if (names.Find(name))
|
||||
namecounts[name]++
|
||||
name = "[name] ([namecounts[name]])"
|
||||
else
|
||||
names.Add(name)
|
||||
namecounts[name] = 1
|
||||
creatures[name] = O
|
||||
|
||||
|
||||
for(var/mob/M in sortAtom(mob_list))
|
||||
var/name = M.name
|
||||
if (names.Find(name))
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
// fun if you want to typecast humans/monkeys/etc without writing long path-filled lines.
|
||||
/proc/isxenomorph(A)
|
||||
if(istype(A, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = A
|
||||
return istype(H.species, /datum/species/xenos)
|
||||
return 0
|
||||
|
||||
/proc/issmall(A)
|
||||
if(A && istype(A, /mob/living))
|
||||
var/mob/living/L = A
|
||||
|
||||
@@ -103,10 +103,6 @@
|
||||
name = "Shoulder-length Hair"
|
||||
icon_state = "hair_b"
|
||||
|
||||
longalt
|
||||
name = "Shoulder-length Hair Alt"
|
||||
icon_state = "hair_longfringe"
|
||||
|
||||
/*longish
|
||||
name = "Longer Hair"
|
||||
icon_state = "hair_b2"*/
|
||||
@@ -115,10 +111,6 @@
|
||||
name = "Long Hair"
|
||||
icon_state = "hair_vlong"
|
||||
|
||||
longeralt
|
||||
name = "Long Hair Alt"
|
||||
icon_state = "hair_vlongfringe"
|
||||
|
||||
longest
|
||||
name = "Very Long Hair"
|
||||
icon_state = "hair_longest"
|
||||
@@ -482,7 +474,7 @@
|
||||
name = "Shaved"
|
||||
icon_state = "bald"
|
||||
gender = NEUTER
|
||||
species_allowed = list("Human","Unathi","Tajara","Skrell","Vox","Machine","Teshari")
|
||||
species_allowed = list("Human","Unathi","Tajara","Skrell", "Machine","Teshari")
|
||||
|
||||
teshari_beard
|
||||
name = "Teshari Beard"
|
||||
@@ -677,11 +669,6 @@
|
||||
icon_state = "hair_messy"
|
||||
species_allowed = list("Tajara")
|
||||
|
||||
vox_quills_short
|
||||
name = "Short Vox Quills"
|
||||
icon_state = "vox_shortquills"
|
||||
species_allowed = list("Vox")
|
||||
|
||||
/datum/sprite_accessory/facial_hair
|
||||
|
||||
taj_sideburns
|
||||
|
||||
@@ -161,30 +161,6 @@
|
||||
qdel(src)
|
||||
return O
|
||||
|
||||
//human -> alien
|
||||
/mob/living/carbon/human/proc/Alienize()
|
||||
if (transforming)
|
||||
return
|
||||
for(var/obj/item/W in src)
|
||||
drop_from_inventory(W)
|
||||
regenerate_icons()
|
||||
transforming = 1
|
||||
canmove = 0
|
||||
icon = null
|
||||
invisibility = 101
|
||||
for(var/t in organs)
|
||||
qdel(t)
|
||||
|
||||
var/alien_caste = pick("Hunter","Sentinel","Drone")
|
||||
var/mob/living/carbon/human/new_xeno = create_new_xenomorph(alien_caste,loc)
|
||||
|
||||
new_xeno.a_intent = I_HURT
|
||||
new_xeno.key = key
|
||||
|
||||
new_xeno << "<B>You are now an alien.</B>"
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/slimeize(adult as num, reproduce as num)
|
||||
if (transforming)
|
||||
return
|
||||
|
||||
@@ -56,6 +56,3 @@
|
||||
if(owner && owner.stat != DEAD && !is_broken())
|
||||
backup_time = world.time
|
||||
if(owner.mind) backup = owner.mind
|
||||
|
||||
/obj/item/organ/internal/stack/vox/stack
|
||||
name = "vox cortical stack"
|
||||
|
||||
@@ -1326,9 +1326,6 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
/obj/item/organ/external/head/seromi
|
||||
eye_icon = "eyes_seromi"
|
||||
|
||||
/obj/item/organ/external/head/vox
|
||||
eye_icon = "vox_eyes_s"
|
||||
|
||||
/obj/item/organ/external/head/no_eyes
|
||||
eye_icon = "blank_eyes"
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
//XENOMORPH ORGANS
|
||||
/obj/item/organ/internal/xenos
|
||||
name = "xeno organ"
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
desc = "It smells like an accident in a chemical factory."
|
||||
|
||||
/obj/item/organ/internal/xenos/eggsac
|
||||
name = "egg sac"
|
||||
parent_organ = BP_GROIN
|
||||
icon_state = "xgibmid1"
|
||||
organ_tag = O_EGG
|
||||
|
||||
/obj/item/organ/internal/xenos/plasmavessel
|
||||
name = "plasma vessel"
|
||||
parent_organ = BP_TORSO
|
||||
icon_state = "xgibdown1"
|
||||
organ_tag = O_PLASMA
|
||||
var/stored_plasma = 0
|
||||
var/max_plasma = 500
|
||||
|
||||
/obj/item/organ/internal/xenos/plasmavessel/queen
|
||||
name = "bloated plasma vessel"
|
||||
stored_plasma = 200
|
||||
max_plasma = 500
|
||||
|
||||
/obj/item/organ/internal/xenos/plasmavessel/sentinel
|
||||
stored_plasma = 100
|
||||
max_plasma = 250
|
||||
|
||||
/obj/item/organ/internal/xenos/plasmavessel/hunter
|
||||
name = "tiny plasma vessel"
|
||||
stored_plasma = 100
|
||||
max_plasma = 150
|
||||
|
||||
/obj/item/organ/internal/xenos/acidgland
|
||||
name = "acid gland"
|
||||
parent_organ = BP_HEAD
|
||||
icon_state = "xgibtorso"
|
||||
organ_tag = O_ACID
|
||||
|
||||
/obj/item/organ/internal/xenos/hivenode
|
||||
name = "hive node"
|
||||
parent_organ = BP_TORSO
|
||||
icon_state = "xgibmid2"
|
||||
organ_tag = O_HIVE
|
||||
|
||||
/obj/item/organ/internal/xenos/resinspinner
|
||||
name = "resin spinner"
|
||||
parent_organ = BP_HEAD
|
||||
icon_state = "xgibmid2"
|
||||
organ_tag = O_RESIN
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//Vox pinning weapon.
|
||||
// Alien pinning weapon.
|
||||
/obj/item/weapon/gun/launcher/spikethrower
|
||||
|
||||
name = "spike thrower"
|
||||
@@ -37,14 +37,6 @@
|
||||
/obj/item/weapon/gun/launcher/spikethrower/update_icon()
|
||||
icon_state = "spikethrower[spikes]"
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/special_check(user)
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.species && H.species.get_bodytype() != "Vox")
|
||||
user << "<span class='warning'>\The [src] does not respond to you!</span>"
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/update_release_force()
|
||||
return
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
item_state = "bolt"
|
||||
|
||||
/obj/item/weapon/arrow/quill
|
||||
name = "vox quill"
|
||||
name = "alien quill"
|
||||
desc = "A wickedly barbed quill from some bizarre animal."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "quill"
|
||||
@@ -116,7 +116,7 @@
|
||||
//double check that the user hasn't removed the bolt in the meantime
|
||||
if(!(bolt && tension && loc == current_user))
|
||||
return
|
||||
|
||||
|
||||
tension++
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
embed = 1 //the dart is shot fast enough to pierce space suits, so I guess splintering inside the target can be a thing. Should be rare due to low damage.
|
||||
var/reagent_amount = 15
|
||||
kill_count = 15 //shorter range
|
||||
|
||||
|
||||
muzzle_type = null
|
||||
|
||||
/obj/item/projectile/bullet/chemdart/New()
|
||||
@@ -194,13 +194,3 @@
|
||||
unload_ammo(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/vox
|
||||
name = "alien dart gun"
|
||||
desc = "A small gas-powered dartgun, fitted for nonhuman hands."
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/vox/medical
|
||||
starting_chems = list("kelotane","bicaridine","anti_toxin")
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/vox/raider
|
||||
starting_chems = list("space_drugs","stoxin","impedrezene")
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
var/options = list("robot", "slime")
|
||||
for(var/t in all_species)
|
||||
options += t
|
||||
options -= "Xenomorph Queen"
|
||||
options -= "Xenomorph"
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.species)
|
||||
|
||||
@@ -178,11 +178,8 @@
|
||||
W.visible_message("<span class='notice'>The fungi are completely dissolved by the solution!</span>")
|
||||
|
||||
/datum/reagent/toxin/plantbgone/touch_obj(var/obj/O, var/volume)
|
||||
if(istype(O, /obj/effect/alien/weeds/))
|
||||
var/obj/effect/alien/weeds/alien_weeds = O
|
||||
alien_weeds.health -= rand(15, 35)
|
||||
alien_weeds.healthcheck()
|
||||
else if(istype(O, /obj/effect/plant))
|
||||
..()
|
||||
if(istype(O, /obj/effect/plant))
|
||||
qdel(O)
|
||||
|
||||
/datum/reagent/toxin/plantbgone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
|
||||
var/trans = reagents.trans_to_obj(target, amount_per_transfer_from_this)
|
||||
user << "<span class='notice'>You add [trans] units of the condiment to \the [target].</span>"
|
||||
else(..())
|
||||
else
|
||||
..()
|
||||
|
||||
feed_sound(var/mob/user)
|
||||
playsound(user.loc, 'sound/items/drink.ogg', rand(10, 50), 1)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/obj/machinery/computer/shuttle_control/multi/vox
|
||||
/obj/machinery/computer/shuttle_control/multi/skipjack
|
||||
name = "skipjack control console"
|
||||
req_access = list(access_syndicate)
|
||||
shuttle_tag = "Skipjack"
|
||||
|
||||
@@ -12,46 +12,6 @@
|
||||
var/obj/item/organ/external/affected = target.get_organ(target_zone)
|
||||
return affected && affected.open == (affected.encased ? 3 : 2)
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// ALIEN EMBRYO SURGERY //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/datum/surgery_step/internal/remove_embryo
|
||||
allowed_tools = list(
|
||||
/obj/item/weapon/hemostat = 100, \
|
||||
/obj/item/weapon/wirecutters = 75, \
|
||||
/obj/item/weapon/material/kitchen/utensil/fork = 20
|
||||
)
|
||||
blood_level = 2
|
||||
|
||||
min_duration = 80
|
||||
max_duration = 100
|
||||
|
||||
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
|
||||
var/embryo = 0
|
||||
for(var/obj/item/alien_embryo/A in target)
|
||||
embryo = 1
|
||||
break
|
||||
|
||||
if (!hasorgans(target))
|
||||
return
|
||||
var/obj/item/organ/external/affected = target.get_organ(target_zone)
|
||||
return ..() && affected && embryo && affected.open == 3 && target_zone == BP_TORSO
|
||||
|
||||
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
|
||||
var/msg = "[user] starts to pull something out from [target]'s ribcage with \the [tool]."
|
||||
var/self_msg = "You start to pull something out from [target]'s ribcage with \the [tool]."
|
||||
user.visible_message(msg, self_msg)
|
||||
target.custom_pain("Something hurts horribly in your chest!",1)
|
||||
..()
|
||||
|
||||
end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
|
||||
user.visible_message("<span class='warning'>[user] rips the larva out of [target]'s ribcage!</span>",
|
||||
"You rip the larva out of [target]'s ribcage!")
|
||||
|
||||
for(var/obj/item/alien_embryo/A in target)
|
||||
A.loc = A.loc.loc
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// CHEST INTERNAL ORGAN SURGERY //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -89,7 +89,6 @@ h1.alert, h2.alert {color: #000000;}
|
||||
.soghun {color: #228B22;}
|
||||
.solcom {color: #22228B;}
|
||||
.changeling {color: #800080;}
|
||||
.vox {color: #AA00AA;}
|
||||
.rough {font-family: "Trebuchet MS", cursive, sans-serif;}
|
||||
.say_quote {font-family: Georgia, Verdana, sans-serif;}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |