mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-27 06:54:18 +01:00
Removes Old Deprecated Stuff (#15241)
This commit is contained in:
@@ -1,419 +0,0 @@
|
||||
#define SECBOT_IDLE 0 // idle
|
||||
#define SECBOT_HUNT 1 // found target, hunting
|
||||
#define SECBOT_ARREST 2 // arresting target
|
||||
#define SECBOT_START_PATROL 3 // start patrol
|
||||
#define SECBOT_WAIT_PATROL 4 // waiting for signals
|
||||
#define SECBOT_PATROL 5 // patrolling
|
||||
#define SECBOT_SUMMON 6 // summoned by PDA
|
||||
#define SECBOT_STOP 7 // basically 'do nothing'
|
||||
#define SECBOT_FOLLOW 8 // follows a target
|
||||
|
||||
/mob/living/bot/secbot/ed209
|
||||
name = "Security Assault Robot"
|
||||
desc = "A security robot. He looks less than thrilled."
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
icon_state = "ed2090"
|
||||
density = 0
|
||||
health = 100
|
||||
maxHealth = 100
|
||||
|
||||
bot_version = "2.5"
|
||||
is_ranged = 1
|
||||
preparing_arrest_sounds = new()
|
||||
|
||||
a_intent = I_HURT
|
||||
mob_bump_flag = HEAVY
|
||||
mob_swap_flags = ~HEAVY
|
||||
mob_push_flags = HEAVY
|
||||
|
||||
var/shot_delay = 4
|
||||
var/last_shot = 0
|
||||
|
||||
// vars for verbal commands
|
||||
var/short_name = null
|
||||
var/list/command_buffer = list()
|
||||
var/list/known_commands = list("stay", "stop", "arrest", "detain", "follow", "patrol")
|
||||
var/emote_hear = "states"
|
||||
move_to_delay = 3
|
||||
|
||||
/mob/living/bot/secbot/ed209/Initialize()
|
||||
. = ..()
|
||||
if(!short_name)
|
||||
short_name = name
|
||||
|
||||
/mob/living/bot/secbot/ed209/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
|
||||
if(thinking_enabled && !stat && has_ui_access(speaker))
|
||||
command_buffer.Add(speaker)
|
||||
command_buffer.Add(lowertext(html_decode(message)))
|
||||
return 0
|
||||
|
||||
/mob/living/bot/secbot/ed209/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/part_c, var/mob/speaker = null, var/hard_to_hear = 0)
|
||||
if(thinking_enabled && !stat && has_ui_access(speaker))
|
||||
command_buffer.Add(speaker)
|
||||
command_buffer.Add(lowertext(html_decode(message)))
|
||||
return 0
|
||||
|
||||
/mob/living/bot/secbot/ed209/think()
|
||||
while(command_buffer.len > 0)
|
||||
var/mob/speaker = command_buffer[1]
|
||||
var/text = command_buffer[2]
|
||||
var/filtered_name = lowertext(html_decode(name))
|
||||
var/filtered_short = lowertext(html_decode(short_name))
|
||||
if(dd_hasprefix(text,filtered_name))
|
||||
var/substring = copytext(text,length(filtered_name)+1) //get rid of the name.
|
||||
listen(speaker,substring)
|
||||
else if(dd_hasprefix(text,filtered_short))
|
||||
var/substring = copytext(text,length(filtered_short)+1) //get rid of the name.
|
||||
listen(speaker,substring)
|
||||
command_buffer.Remove(command_buffer[1],command_buffer[2])
|
||||
..()
|
||||
switch(mode)
|
||||
if(SECBOT_FOLLOW)
|
||||
follow_target()
|
||||
if(SECBOT_STOP)
|
||||
commanded_stop()
|
||||
|
||||
/mob/living/bot/secbot/ed209/on_think_disabled()
|
||||
..()
|
||||
command_buffer.Cut()
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/follow_target()
|
||||
if(!target)
|
||||
return
|
||||
if(target in view(7, src))
|
||||
walk_to(src,target,1,move_to_delay)
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/commanded_stop() //basically a proc that runs whenever we are asked to stay put. Probably going to remain unused.
|
||||
return
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/listen(var/mob/speaker, var/text)
|
||||
for(var/command in known_commands)
|
||||
if(findtext(text,command))
|
||||
switch(command)
|
||||
if("stay")
|
||||
if(stay_command(speaker,text)) //find a valid command? Stop. Dont try and find more.
|
||||
break
|
||||
if("stop")
|
||||
if(stop_command(speaker,text))
|
||||
break
|
||||
if("arrest")
|
||||
if(arrest_command(speaker,text))
|
||||
break
|
||||
if("detain")
|
||||
if(arrest_command(speaker,text))
|
||||
break
|
||||
if("follow")
|
||||
if(follow_command(speaker,text))
|
||||
break
|
||||
if("patrol")
|
||||
if(patrol_command(speaker, text))
|
||||
break
|
||||
|
||||
return 1
|
||||
|
||||
//returns a list of everybody we wanna do stuff with.
|
||||
/mob/living/bot/secbot/ed209/proc/get_target_by_name(var/text)
|
||||
var/list/possible_targets = hearers(src,10)
|
||||
for(var/mob/M in possible_targets)
|
||||
if(findtext(text, "[M]"))
|
||||
return M
|
||||
else
|
||||
var/list/parsed_name = splittext(replace_characters(lowertext(html_decode("[M]")),list("-"=" ", "."=" ", "," = " ", "'" = " ")), " ") //this big MESS is basically 'turn this into words, no punctuation, lowercase so we can check first name/last name/etc'
|
||||
for(var/a in parsed_name)
|
||||
if(a == "the" || length(a) < 2) //get rid of shit words.
|
||||
continue
|
||||
if(findtext(text,"[a]"))
|
||||
return M
|
||||
return null
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/arrest_command(var/mob/speaker,var/text)
|
||||
target = null //want me to attack something? Well I better forget my old target.
|
||||
walk_to(src,0)
|
||||
|
||||
target = get_target_by_name(text)
|
||||
if(!(target in view(7, src)))
|
||||
return 0
|
||||
|
||||
if(findtext(text,"detain"))
|
||||
arrest_type = 1
|
||||
else
|
||||
arrest_type = 0
|
||||
|
||||
if(isnull(target))
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"Error, unit is unable to find target in view range!\"")
|
||||
return 0
|
||||
else
|
||||
if(ishuman(target))
|
||||
idcheck = TRUE
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/perpname = H.name
|
||||
var/obj/item/card/id/id = H.GetIdCard()
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
|
||||
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
||||
if(R && R.security)
|
||||
R.security.criminal = "*Arrest*"
|
||||
else
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"Warning, [target] does not have Security records! Enabling security records check mode!\"")
|
||||
check_records = TRUE
|
||||
mode = SECBOT_HUNT
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"[arrest_type ? ("Detaining") : ("Arresting")] [target]\"")
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/stay_command(var/mob/speaker,var/text)
|
||||
walk_to(src, src, 0, move_to_delay)
|
||||
mode = SECBOT_IDLE
|
||||
auto_patrol = 0
|
||||
target = null
|
||||
check_records = FALSE
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"Roger that, going into idle mode. Auto patrol disabled.\"")
|
||||
return 1
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/stop_command(var/mob/speaker,var/text)
|
||||
if(!on)
|
||||
return
|
||||
walk_to(src, src, 0, move_to_delay)
|
||||
check_records = FALSE
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"Roger that, unit going offline.\"")
|
||||
turn_off()
|
||||
return 1
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/patrol_command(var/mob/speaker,var/text)
|
||||
walk_to(src, src, 0, move_to_delay)
|
||||
mode = SECBOT_IDLE
|
||||
auto_patrol = 1
|
||||
target = null
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"Roger that, starting patrol now.\"")
|
||||
return 1
|
||||
|
||||
/mob/living/bot/secbot/ed209/proc/follow_command(var/mob/speaker,var/text)
|
||||
//we can assume 'stop following' is handled by stop_command
|
||||
if(findtext(text,"me"))
|
||||
mode = SECBOT_FOLLOW
|
||||
target = speaker
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"Roger that, following you\"")
|
||||
return 1
|
||||
|
||||
target = get_target_by_name(text)
|
||||
if(!(target in view(7, src)))
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
return 0
|
||||
|
||||
mode = SECBOT_FOLLOW
|
||||
custom_emote(AUDIBLE_MESSAGE, "[emote_hear], \"Roger that, following [target]\"")
|
||||
|
||||
return 1
|
||||
|
||||
/mob/living/bot/secbot/ed209/verb/change_name()
|
||||
set name = "Change nickname"
|
||||
set category = "IC"
|
||||
set src in view(1)
|
||||
|
||||
if(!usr.mind) return 0
|
||||
|
||||
// Check if they are set to arrest
|
||||
if(ishuman(usr))
|
||||
var/mob/living/carbon/human/H = usr
|
||||
var/perpname = H.name
|
||||
var/obj/item/card/id/id = H.GetIdCard()
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
|
||||
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
||||
if(R && R.security && R.security.criminal == "*Arrest*")
|
||||
to_chat(usr, "<span class='warning'>Warning, you do not have access!</span>")
|
||||
|
||||
// Check if they have access to the bot
|
||||
if(!has_ui_access(usr))
|
||||
to_chat(usr, "<span class='warning'>Warning, you do not have access!</span>")
|
||||
return 0
|
||||
|
||||
var/short_input = sanitizeSafe(input("What do you want [src] respond to?", , ""), MAX_NAME_LEN)
|
||||
|
||||
if(src && short_input && !usr.stat && in_range(usr,src))
|
||||
short_name = short_input
|
||||
return 1
|
||||
|
||||
/mob/living/bot/secbot/ed209/update_icon()
|
||||
if(on && is_attacking)
|
||||
icon_state = "ed209-c"
|
||||
else
|
||||
icon_state = "ed209[on]"
|
||||
|
||||
/mob/living/bot/secbot/ed209/explode()
|
||||
visible_message("<span class='danger'>[src] blows apart!</span>")
|
||||
var/turf/Tsec = get_turf(src)
|
||||
|
||||
new /obj/item/secbot_assembly/ed209_assembly(Tsec)
|
||||
|
||||
var/obj/item/gun/energy/taser/G = new /obj/item/gun/energy/taser(Tsec)
|
||||
G.power_supply.charge = 0
|
||||
if(prob(50))
|
||||
new /obj/item/robot_parts/l_leg(Tsec)
|
||||
if(prob(50))
|
||||
new /obj/item/robot_parts/r_leg(Tsec)
|
||||
if(prob(50))
|
||||
if(prob(50))
|
||||
new /obj/item/clothing/head/helmet(Tsec)
|
||||
else
|
||||
new /obj/item/clothing/suit/armor/vest(Tsec)
|
||||
|
||||
spark(src, 3, alldirs)
|
||||
|
||||
new /obj/effect/decal/cleanable/blood/oil(Tsec)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/secbot/ed209/RangedAttack(var/atom/A)
|
||||
if(!(target in view(7, src)))
|
||||
walk_to(src, target, 6, move_to_delay)
|
||||
return
|
||||
if(last_shot + shot_delay > world.time)
|
||||
to_chat(src, "You are not ready to fire yet!")
|
||||
return
|
||||
|
||||
last_shot = world.time
|
||||
var/projectile = /obj/item/projectile/beam/stun
|
||||
if(emagged)
|
||||
projectile = /obj/item/projectile/beam
|
||||
|
||||
playsound(loc, emagged ? 'sound/weapons/laser1.ogg' : 'sound/weapons/Taser.ogg', 50, 1)
|
||||
var/obj/item/projectile/P = new projectile(loc)
|
||||
var/def_zone = get_exposed_defense_zone(A)
|
||||
P.launch_projectile(A, def_zone)
|
||||
// Assembly
|
||||
|
||||
/obj/item/secbot_assembly/ed209_assembly
|
||||
name = "security assault robot assembly"
|
||||
desc = "Some sort of bizarre assembly."
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
icon_state = "ed209_frame"
|
||||
item_state = "ed209_frame"
|
||||
created_name = "Security Assault Robot"
|
||||
var/lasercolor = ""
|
||||
|
||||
/obj/item/secbot_assembly/ed209_assembly/attackby(var/obj/item/W as obj, var/mob/user as mob)
|
||||
..()
|
||||
|
||||
if(W.ispen())
|
||||
var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN)
|
||||
if(!t)
|
||||
return
|
||||
if(!in_range(src, usr) && src.loc != usr)
|
||||
return
|
||||
created_name = t
|
||||
return
|
||||
|
||||
switch(build_step)
|
||||
if(0, 1)
|
||||
if(istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg))
|
||||
user.drop_from_inventory(W,get_turf(src))
|
||||
qdel(W)
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You add the robot leg to [src].</span>")
|
||||
name = "legs/frame assembly"
|
||||
if(build_step == 1)
|
||||
item_state = "ed209_leg"
|
||||
icon_state = "ed209_leg"
|
||||
else
|
||||
item_state = "ed209_legs"
|
||||
icon_state = "ed209_legs"
|
||||
return 1
|
||||
|
||||
if(2)
|
||||
if(istype(W, /obj/item/clothing/accessory/armor_plate))
|
||||
user.drop_from_inventory(W,get_turf(src))
|
||||
qdel(W)
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You add the armor to [src].</span>")
|
||||
name = "vest/legs/frame assembly"
|
||||
item_state = "ed209_shell"
|
||||
icon_state = "ed209_shell"
|
||||
return 1
|
||||
|
||||
if(3)
|
||||
if(W.iswelder())
|
||||
var/obj/item/weldingtool/WT = W
|
||||
if(WT.use(0, user))
|
||||
build_step++
|
||||
name = "shielded frame assembly"
|
||||
to_chat(user, "<span class='notice'>You welded the armor to [src].</span>")
|
||||
return 1
|
||||
if(4)
|
||||
if(istype(W, /obj/item/clothing/head/helmet))
|
||||
user.drop_from_inventory(W,get_turf(src))
|
||||
qdel(W)
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You add the helmet to [src].</span>")
|
||||
name = "covered and shielded frame assembly"
|
||||
item_state = "ed209_hat"
|
||||
icon_state = "ed209_hat"
|
||||
return 1
|
||||
|
||||
if(5)
|
||||
if(isprox(W))
|
||||
user.drop_from_inventory(W,get_turf(src))
|
||||
qdel(W)
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You add the prox sensor to [src].</span>")
|
||||
name = "covered, shielded and sensored frame assembly"
|
||||
item_state = "ed209_prox"
|
||||
icon_state = "ed209_prox"
|
||||
return 1
|
||||
|
||||
if(6)
|
||||
if(W.iscoil())
|
||||
var/obj/item/stack/cable_coil/C = W
|
||||
if (C.get_amount() < 1)
|
||||
to_chat(user, "<span class='warning'>You need one coil of wire to wire [src].</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start to wire [src].</span>")
|
||||
if(W.use_tool(src, user, 40, volume = 50) && build_step == 6)
|
||||
if(C.use(1))
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You wire the security assault robot assembly.</span>")
|
||||
name = "wired security assault robot assembly"
|
||||
return
|
||||
|
||||
if(7)
|
||||
if(istype(W, /obj/item/gun/energy/disruptorpistol))
|
||||
name = "taser security assault robot assembly"
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You add [W] to [src].</span>")
|
||||
item_state = "ed209_taser"
|
||||
icon_state = "ed209_taser"
|
||||
user.drop_from_inventory(W,get_turf(src))
|
||||
qdel(W)
|
||||
return 1
|
||||
|
||||
if(8)
|
||||
if(W.isscrewdriver())
|
||||
var/turf/T = get_turf(user)
|
||||
to_chat(user, "<span class='notice'>Now attaching the gun to the frame...</span>")
|
||||
if(!W.use_tool(src, user, 40, volume = 50)) return
|
||||
if(get_turf(user) == T && build_step == 8)
|
||||
build_step++
|
||||
name = "armed [name]"
|
||||
to_chat(user, "<span class='notice'>Taser gun attached.</span>")
|
||||
|
||||
if(9)
|
||||
if(istype(W, /obj/item/cell))
|
||||
build_step++
|
||||
to_chat(user, "<span class='notice'>You complete the security assault robot.</span>")
|
||||
var/turf/T = get_turf(src)
|
||||
new /mob/living/bot/secbot/ed209(T,created_name,lasercolor)
|
||||
user.drop_from_inventory(W,get_turf(src))
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
return 1
|
||||
|
||||
#undef SECBOT_IDLE
|
||||
#undef SECBOT_HUNT
|
||||
#undef SECBOT_ARREST
|
||||
#undef SECBOT_START_PATROL
|
||||
#undef SECBOT_WAIT_PATROL
|
||||
#undef SECBOT_PATROL
|
||||
#undef SECBOT_SUMMON
|
||||
#undef SECBOT_STOP
|
||||
#undef SECBOT_FOLLOW
|
||||
@@ -1,398 +0,0 @@
|
||||
/mob/living/bot/floorbot
|
||||
name = "Floorbot"
|
||||
desc = "A little floor repairing robot, he looks so excited!"
|
||||
icon_state = "floorbot0"
|
||||
req_one_access = list(access_construction, access_robotics)
|
||||
|
||||
var/amount = 10 // 1 for tile, 2 for lattice
|
||||
var/maxAmount = 60
|
||||
var/tilemake = 0 // When it reaches 100, bot makes a tile
|
||||
var/repairing = 0
|
||||
var/improvefloors = 0
|
||||
var/eattiles = 0
|
||||
var/maketiles = 0
|
||||
var/targetdirection = null
|
||||
var/list/path = list()
|
||||
var/list/ignorelist = list()
|
||||
var/turf/target
|
||||
var/floor_build_type = /decl/flooring/tiling // Basic steel floor.
|
||||
|
||||
/mob/living/bot/floorbot/update_icon()
|
||||
if(repairing)
|
||||
icon_state = "floorbot-c"
|
||||
else if(amount > 0)
|
||||
icon_state = "floorbot[on]"
|
||||
else
|
||||
icon_state = "floorbot[on]e"
|
||||
|
||||
/mob/living/bot/floorbot/attack_hand(var/mob/user)
|
||||
if (!has_ui_access(user))
|
||||
to_chat(user, "<span class='warning'>The unit's interface refuses to unlock!</span>")
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
|
||||
var/dat = ""
|
||||
dat += "Status: <A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A><BR>"
|
||||
dat += "Maintenance panel is [open ? "opened" : "closed"]<BR>"
|
||||
//dat += "Tiles left: [amount]<BR>"
|
||||
dat += "Behvaiour controls are [locked ? "locked" : "unlocked"]<BR>"
|
||||
if(!locked || issilicon(user))
|
||||
dat += "Improves floors: <A href='?src=\ref[src];operation=improve'>[improvefloors ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Finds tiles: <A href='?src=\ref[src];operation=tiles'>[eattiles ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Make singles pieces of metal into tiles when empty: <A href='?src=\ref[src];operation=make'>[maketiles ? "Yes" : "No"]</A><BR>"
|
||||
var/bmode
|
||||
if(targetdirection)
|
||||
bmode = dir2text(targetdirection)
|
||||
else
|
||||
bmode = "Disabled"
|
||||
dat += "<BR><BR>Bridge Mode : <A href='?src=\ref[src];operation=bridgemode'>[bmode]</A><BR>"
|
||||
|
||||
var/datum/browser/bot_win = new(user, "autorepair", "Automatic Repairbot v1.2 Controls")
|
||||
bot_win.set_content(dat)
|
||||
bot_win.open()
|
||||
|
||||
/mob/living/bot/floorbot/emag_act(var/remaining_charges, var/mob/user)
|
||||
. = ..()
|
||||
if(!emagged)
|
||||
emagged = 1
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>The [src] buzzes and beeps.</span>")
|
||||
return 1
|
||||
|
||||
/mob/living/bot/floorbot/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
if (!has_ui_access(usr))
|
||||
to_chat(usr, "<span class='warning'>Insufficient permissions.</span>")
|
||||
return
|
||||
|
||||
switch(href_list["operation"])
|
||||
if("start")
|
||||
if (on)
|
||||
turn_off()
|
||||
else
|
||||
turn_on()
|
||||
if("improve")
|
||||
improvefloors = !improvefloors
|
||||
if("tiles")
|
||||
eattiles = !eattiles
|
||||
if("make")
|
||||
maketiles = !maketiles
|
||||
if("bridgemode")
|
||||
switch(targetdirection)
|
||||
if(null)
|
||||
targetdirection = 1
|
||||
if(1)
|
||||
targetdirection = 2
|
||||
if(2)
|
||||
targetdirection = 4
|
||||
if(4)
|
||||
targetdirection = 8
|
||||
if(8)
|
||||
targetdirection = null
|
||||
else
|
||||
targetdirection = null
|
||||
attack_hand(usr)
|
||||
|
||||
/mob/living/bot/floorbot/turn_off()
|
||||
..()
|
||||
target = null
|
||||
path = list()
|
||||
ignorelist = list()
|
||||
|
||||
/mob/living/bot/floorbot/Life()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
++tilemake
|
||||
if(tilemake >= 100)
|
||||
tilemake = 0
|
||||
addTiles(1)
|
||||
|
||||
if(prob(5))
|
||||
custom_emote(AUDIBLE_MESSAGE, "makes an excited booping beeping sound!")
|
||||
|
||||
/mob/living/bot/floorbot/think()
|
||||
..()
|
||||
if (!on)
|
||||
return
|
||||
if(amount && !emagged)
|
||||
if(!target && targetdirection) // Building a bridge
|
||||
var/turf/T = get_step(src, targetdirection)
|
||||
while(T in range(src))
|
||||
if(istype(T, /turf/space))
|
||||
target = T
|
||||
break
|
||||
T = get_step(T, targetdirection)
|
||||
|
||||
if(!target) // Fixing floors
|
||||
for(var/turf/T in view(src))
|
||||
if (istype(T.loc, /area/space))
|
||||
continue
|
||||
if(T in ignorelist)
|
||||
continue
|
||||
if(istype(T, /turf/space))
|
||||
if(get_turf(T) == loc || prob(40)) // So they target the same tile all the time
|
||||
target = T
|
||||
if(improvefloors && istype(T, /turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = T
|
||||
if(!F.flooring && (get_turf(T) == loc || prob(40)))
|
||||
target = T
|
||||
|
||||
if(emagged) // Time to griff
|
||||
for(var/turf/simulated/floor/D in view(src))
|
||||
if (istype(D.loc, /area/space))
|
||||
continue
|
||||
if(D in ignorelist)
|
||||
continue
|
||||
target = D
|
||||
break
|
||||
|
||||
if(!target && amount < maxAmount && eattiles || maketiles) // Eat tiles
|
||||
if(eattiles)
|
||||
for(var/obj/item/stack/tile/floor/T in view(src))
|
||||
if(T in ignorelist)
|
||||
continue
|
||||
target = T
|
||||
break
|
||||
if(maketiles && !target)
|
||||
for(var/obj/item/stack/material/steel/T in view(src))
|
||||
if(T in ignorelist)
|
||||
continue
|
||||
target = T
|
||||
break
|
||||
|
||||
if(target && get_turf(target) == loc)
|
||||
INVOKE_ASYNC(src, .proc/UnarmedAttack, target)
|
||||
|
||||
if(target && get_turf(target) != loc && !path.len)
|
||||
spawn(0)
|
||||
path = AStar(loc, get_turf(target), /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id = botcard)
|
||||
if(!path)
|
||||
path = list()
|
||||
ignorelist += target
|
||||
target = null
|
||||
|
||||
if(path.len)
|
||||
step_to(src, path[1])
|
||||
path -= path[1]
|
||||
|
||||
if(ignorelist.len) // Don't stick forever
|
||||
for(var/T in ignorelist)
|
||||
if(prob(1))
|
||||
ignorelist -= T
|
||||
|
||||
/mob/living/bot/floorbot/on_think_disabled()
|
||||
..()
|
||||
ignorelist.Cut()
|
||||
path.Cut()
|
||||
target = null
|
||||
|
||||
/mob/living/bot/floorbot/UnarmedAttack(var/atom/A, var/proximity)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
if(repairing)
|
||||
return
|
||||
|
||||
if(!src.Adjacent(A))
|
||||
return
|
||||
|
||||
if(emagged && istype(A, /turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = A
|
||||
repairing = 1
|
||||
update_icon()
|
||||
if(F.is_plating())
|
||||
visible_message("<span class='warning'>[src] begins to tear the floor tile from the floor!</span>")
|
||||
if(do_after(src, 50))
|
||||
F.break_tile_to_plating()
|
||||
addTiles(1)
|
||||
else
|
||||
visible_message("<span class='danger'>[src] begins to tear through the floor!</span>")
|
||||
if(do_after(src, 150)) // Extra time because this can and will kill.
|
||||
F.ReplaceWithLattice()
|
||||
addTiles(1)
|
||||
target = null
|
||||
repairing = 0
|
||||
update_icon()
|
||||
else if(istype(A, /turf/space))
|
||||
var/building = 2
|
||||
if(locate(/obj/structure/lattice, A))
|
||||
building = 1
|
||||
if(amount < building)
|
||||
return
|
||||
repairing = 1
|
||||
update_icon()
|
||||
visible_message("<span class='notice'>[src] begins to repair the hole.</span>")
|
||||
if(do_after(src, 50))
|
||||
if(A && (locate(/obj/structure/lattice, A) && building == 1 || !locate(/obj/structure/lattice, A) && building == 2)) // Make sure that it still needs repairs
|
||||
var/obj/item/I
|
||||
if(building == 1)
|
||||
I = new /obj/item/stack/tile/floor(src)
|
||||
else
|
||||
I = new /obj/item/stack/rods(src)
|
||||
A.attackby(I, src)
|
||||
target = null
|
||||
repairing = 0
|
||||
update_icon()
|
||||
else if(istype(A, /turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = A
|
||||
if(!F.flooring && amount)
|
||||
repairing = 1
|
||||
update_icon()
|
||||
visible_message("<span class='notice'>[src] begins to improve the floor.</span>")
|
||||
if(do_after(src, 50))
|
||||
if(!F.flooring)
|
||||
F.set_flooring(decls_repository.get_decl(floor_build_type))
|
||||
addTiles(-1)
|
||||
target = null
|
||||
repairing = 0
|
||||
update_icon()
|
||||
else if(istype(A, /obj/item/stack/tile/floor) && amount < maxAmount)
|
||||
var/obj/item/stack/tile/floor/T = A
|
||||
visible_message("<span class='notice'>[src] begins to collect tiles.</span>")
|
||||
repairing = 1
|
||||
update_icon()
|
||||
if(do_after(src, 20))
|
||||
if(T)
|
||||
var/eaten = min(maxAmount - amount, T.get_amount())
|
||||
T.use(eaten)
|
||||
addTiles(eaten)
|
||||
target = null
|
||||
repairing = 0
|
||||
update_icon()
|
||||
else if(istype(A, /obj/item/stack/material) && amount + 4 <= maxAmount)
|
||||
var/obj/item/stack/material/M = A
|
||||
if(M.get_material_name() == DEFAULT_WALL_MATERIAL)
|
||||
visible_message("<span class='notice'>[src] begins to make tiles.</span>")
|
||||
repairing = 1
|
||||
update_icon()
|
||||
if(do_after(50))
|
||||
if(M)
|
||||
M.use(1)
|
||||
addTiles(4)
|
||||
|
||||
/mob/living/bot/floorbot/explode()
|
||||
turn_off()
|
||||
visible_message("<span class='danger'>[src] blows apart!</span>")
|
||||
var/turf/Tsec = get_turf(src)
|
||||
|
||||
var/obj/item/storage/toolbox/mechanical/N = new /obj/item/storage/toolbox/mechanical(Tsec)
|
||||
N.contents = list()
|
||||
new /obj/item/device/assembly/prox_sensor(Tsec)
|
||||
if(prob(50))
|
||||
new /obj/item/robot_parts/l_arm(Tsec)
|
||||
var/obj/item/stack/tile/floor/T = new /obj/item/stack/tile/floor(Tsec)
|
||||
T.amount = amount
|
||||
spark(src, 3, alldirs)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/floorbot/proc/addTiles(var/am)
|
||||
amount += am
|
||||
if(amount < 0)
|
||||
amount = 0
|
||||
else if(amount > maxAmount)
|
||||
amount = maxAmount
|
||||
|
||||
/* Assembly */
|
||||
|
||||
/obj/item/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/floor/T, mob/user as mob)
|
||||
if(!istype(T, /obj/item/stack/tile/floor))
|
||||
..()
|
||||
return
|
||||
if(contents.len >= 1)
|
||||
to_chat(user, "<span class='notice'>They wont fit in as there is already stuff inside.</span>")
|
||||
return
|
||||
if(user.s_active)
|
||||
user.s_active.close(user)
|
||||
if(T.use(10))
|
||||
var/obj/item/toolbox_tiles/B = new /obj/item/toolbox_tiles
|
||||
user.put_in_hands(B)
|
||||
to_chat(user, "<span class='notice'>You add the tiles into the empty toolbox. They protrude from the top.</span>")
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need 10 floor tiles for a floorbot.</span>")
|
||||
return
|
||||
|
||||
/obj/item/toolbox_tiles
|
||||
desc = "It's a toolbox with tiles sticking out the top"
|
||||
name = "tiles and toolbox"
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
icon_state = "toolbox_tiles"
|
||||
force = 3.0
|
||||
throwforce = 10.0
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
var/created_name = "Floorbot"
|
||||
|
||||
/obj/item/toolbox_tiles/attackby(var/obj/item/W, mob/user as mob)
|
||||
..()
|
||||
if(isprox(W))
|
||||
qdel(W)
|
||||
var/obj/item/toolbox_tiles_sensor/B = new /obj/item/toolbox_tiles_sensor()
|
||||
B.created_name = created_name
|
||||
user.put_in_hands(B)
|
||||
to_chat(user, "<span class='notice'>You add the sensor to the toolbox and tiles!</span>")
|
||||
qdel(src)
|
||||
return 1
|
||||
else if (W.ispen())
|
||||
var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN)
|
||||
if(!t)
|
||||
return
|
||||
if(!in_range(src, user) && loc != user)
|
||||
return
|
||||
created_name = t
|
||||
|
||||
/obj/item/toolbox_tiles_sensor
|
||||
desc = "It's a toolbox with tiles sticking out the top and a sensor attached"
|
||||
name = "tiles, toolbox and sensor arrangement"
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
icon_state = "toolbox_tiles_sensor"
|
||||
force = 3.0
|
||||
throwforce = 10.0
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
var/created_name = "Floorbot"
|
||||
|
||||
/obj/item/toolbox_tiles_sensor/attackby(var/obj/item/W, mob/user as mob)
|
||||
..()
|
||||
if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm))
|
||||
qdel(W)
|
||||
var/turf/T = get_turf(user.loc)
|
||||
var/mob/living/bot/floorbot/A = new /mob/living/bot/floorbot(T)
|
||||
A.name = created_name
|
||||
to_chat(user, "<span class='notice'>You add the robot arm to the odd looking toolbox assembly! Boop beep!</span>")
|
||||
qdel(src)
|
||||
return 1
|
||||
else if(W.ispen())
|
||||
var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN)
|
||||
if(!t)
|
||||
return
|
||||
if(!in_range(src, user) && loc != user)
|
||||
return
|
||||
created_name = t
|
||||
|
||||
/mob/living/bot/floorbot/floorbob
|
||||
name = "B.O.B."
|
||||
desc = "A little floor repairing robot, he can build it!"
|
||||
icon_state = "floorbob0"
|
||||
req_one_access = list(access_construction, access_robotics)
|
||||
|
||||
amount = 120 // 1 for tile, 2 for lattice
|
||||
maxAmount = 120
|
||||
|
||||
/mob/living/bot/floorbot/floorbob/update_icon()
|
||||
if(repairing)
|
||||
icon_state = "floorbob-c"
|
||||
else if(amount > 0)
|
||||
icon_state = "floorbob[on]"
|
||||
else
|
||||
icon_state = "floorbob[on]e"
|
||||
@@ -1,726 +0,0 @@
|
||||
#define SECBOT_IDLE 0 // idle
|
||||
#define SECBOT_HUNT 1 // found target, hunting
|
||||
#define SECBOT_ARREST 2 // arresting target
|
||||
#define SECBOT_START_PATROL 3 // start patrol
|
||||
#define SECBOT_WAIT_PATROL 4 // waiting for signals
|
||||
#define SECBOT_PATROL 5 // patrolling
|
||||
#define SECBOT_SUMMON 6 // summoned by PDA
|
||||
|
||||
/mob/living/bot/secbot
|
||||
name = "Securitron"
|
||||
desc = "A little security robot. He looks less than thrilled."
|
||||
icon_state = "secbot0"
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
req_one_access = list(access_security, access_forensics_lockers, access_weapons)
|
||||
botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels)
|
||||
|
||||
var/mob/target
|
||||
|
||||
var/idcheck = 0 // If true, arrests for having weapons without authorization.
|
||||
var/check_records = 0 // If true, arrests people without a record.
|
||||
var/check_arrest = 1 // If true, arrests people who are set to arrest.
|
||||
var/arrest_type = 0 // If true, doesn't handcuff. You monster.
|
||||
var/declare_arrests = 0 // If true, announces arrests over sechuds.
|
||||
var/auto_patrol = 0 // If true, patrols on its own
|
||||
|
||||
var/mode = 0
|
||||
|
||||
var/is_attacking = 0
|
||||
var/is_ranged = 0
|
||||
var/awaiting_surrender = 0
|
||||
|
||||
var/obj/secbot_listener/listener = null
|
||||
var/beacon_freq = 1445 // Navigation beacon frequency
|
||||
var/control_freq = BOT_FREQ // Bot control frequency
|
||||
var/list/turf/path = list()
|
||||
var/frustration = 0
|
||||
var/turf/patrol_target = null // This is where we are headed
|
||||
var/closest_dist // Used to find the closest beakon
|
||||
var/destination = "__nearest__" // This is the current beacon's ID
|
||||
var/next_destination = "__nearest__" // This is the next beacon's ID
|
||||
var/nearest_beacon // Tag of the beakon that we assume to be the closest one
|
||||
|
||||
var/bot_version = 1.5
|
||||
var/list/threat_found_sounds = list(
|
||||
'sound/voice/bcriminal.ogg',
|
||||
'sound/voice/bjustice.ogg',
|
||||
'sound/voice/bfreeze.ogg'
|
||||
)
|
||||
var/list/preparing_arrest_sounds = list(
|
||||
'sound/voice/bgod.ogg',
|
||||
'sound/voice/biamthelaw.ogg',
|
||||
'sound/voice/bsecureday.ogg',
|
||||
'sound/voice/bradio.ogg',
|
||||
'sound/voice/binsult.ogg',
|
||||
'sound/voice/bcreep.ogg'
|
||||
)
|
||||
|
||||
var/datum/callback/patrol_callback // this is here so we don't constantly recreate this datum, it being identical each time.
|
||||
var/move_to_delay = 4 //delay for the automated movement.
|
||||
can_take_pai = FALSE
|
||||
|
||||
/mob/living/bot/secbot/beepsky
|
||||
name = "Officer Beepsky"
|
||||
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
|
||||
auto_patrol = 1
|
||||
|
||||
/mob/living/bot/secbot/Initialize()
|
||||
. = ..()
|
||||
listener = new /obj/secbot_listener(src)
|
||||
listener.secbot = src
|
||||
|
||||
if(SSradio)
|
||||
SSradio.add_object(listener, control_freq, filter = RADIO_SECBOT)
|
||||
SSradio.add_object(listener, beacon_freq, filter = RADIO_NAVBEACONS)
|
||||
|
||||
/mob/living/bot/secbot/Destroy()
|
||||
QDEL_NULL(listener)
|
||||
target = null
|
||||
return ..()
|
||||
|
||||
/mob/living/bot/secbot/turn_off()
|
||||
..()
|
||||
walk_to(src, src, 0, move_to_delay)
|
||||
target = null
|
||||
frustration = 0
|
||||
mode = SECBOT_IDLE
|
||||
|
||||
/mob/living/bot/secbot/update_icon()
|
||||
if(on && is_attacking)
|
||||
icon_state = "secbot-c"
|
||||
else
|
||||
icon_state = "secbot[on]"
|
||||
|
||||
if(on)
|
||||
set_light(1.4, 1, "#FF6A00")
|
||||
else
|
||||
set_light(0)
|
||||
|
||||
/mob/living/bot/secbot/attack_hand(var/mob/user)
|
||||
if (!has_ui_access(user))
|
||||
to_chat(user, "<span class='warning'>The unit's interface refuses to unlock!</span>")
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat = ""
|
||||
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
|
||||
dat += "Maintenance panel is [open ? "opened" : "closed"]"
|
||||
if(!locked || issilicon(user))
|
||||
dat += "<BR>Check for Weapon Authorization: <A href='?src=\ref[src];operation=idcheck'>[idcheck ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Check Security Records: <A href='?src=\ref[src];operation=ignorerec'>[check_records ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Check Arrest Status: <A href='?src=\ref[src];operation=ignorearr'>[check_arrest ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Operating Mode: <A href='?src=\ref[src];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A><BR>"
|
||||
dat += "Report Arrests: <A href='?src=\ref[src];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Auto Patrol: <A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>"
|
||||
|
||||
var/datum/browser/bot_win = new(user, "autosec", "Automatic Securitron v[bot_version] Controls")
|
||||
bot_win.set_content(dat)
|
||||
bot_win.open()
|
||||
|
||||
/mob/living/bot/secbot/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
if (!has_ui_access(usr))
|
||||
to_chat(usr, "<span class='warning'>Insufficient permissions.</span>")
|
||||
return
|
||||
|
||||
if(href_list["power"])
|
||||
if(on)
|
||||
turn_off()
|
||||
else
|
||||
turn_on()
|
||||
attack_hand(usr)
|
||||
|
||||
if (locked && !issilicon(usr))
|
||||
return
|
||||
|
||||
switch(href_list["operation"])
|
||||
if("idcheck")
|
||||
idcheck = !idcheck
|
||||
if("ignorerec")
|
||||
check_records = !check_records
|
||||
if("ignorearr")
|
||||
check_arrest = !check_arrest
|
||||
if("switchmode")
|
||||
arrest_type = !arrest_type
|
||||
if("patrol")
|
||||
auto_patrol = !auto_patrol
|
||||
mode = SECBOT_IDLE
|
||||
if("declarearrests")
|
||||
declare_arrests = !declare_arrests
|
||||
attack_hand(usr)
|
||||
|
||||
/mob/living/bot/secbot/attackby(var/obj/item/O, var/mob/user)
|
||||
var/curhealth = health
|
||||
..()
|
||||
if(health < curhealth)
|
||||
target = user
|
||||
awaiting_surrender = 5
|
||||
mode = SECBOT_HUNT
|
||||
|
||||
/mob/living/bot/secbot/think()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(QDELETED(target))
|
||||
scan_view()
|
||||
|
||||
if(!locked && (mode == SECBOT_START_PATROL || mode == SECBOT_PATROL)) // Stop running away when we set you up
|
||||
mode = SECBOT_IDLE
|
||||
|
||||
switch(mode)
|
||||
if(SECBOT_IDLE)
|
||||
if(auto_patrol && locked)
|
||||
mode = SECBOT_START_PATROL
|
||||
return
|
||||
|
||||
if(SECBOT_HUNT) // Target is in the view or has been recently - chase it
|
||||
if(frustration > 7)
|
||||
target = null
|
||||
frustration = 0
|
||||
awaiting_surrender = 0
|
||||
mode = SECBOT_IDLE
|
||||
return
|
||||
if(target)
|
||||
var/threat = check_threat(target)
|
||||
if(threat < 4) // Re-evaluate in case they dropped the weapon or something
|
||||
target = null
|
||||
frustration = 0
|
||||
awaiting_surrender = 0
|
||||
mode = SECBOT_IDLE
|
||||
return
|
||||
if(!(target in view(7, src)))
|
||||
++frustration
|
||||
if(Adjacent(target))
|
||||
mode = SECBOT_ARREST
|
||||
return
|
||||
else
|
||||
if(is_ranged)
|
||||
RangedAttack(target)
|
||||
else
|
||||
walk_to(src, target, 1, move_to_delay) // Melee bots chase a bit faster
|
||||
|
||||
if(SECBOT_ARREST) // Target is next to us - attack it
|
||||
if(!target)
|
||||
mode = SECBOT_IDLE
|
||||
if(!Adjacent(target))
|
||||
awaiting_surrender = 5 // I'm done playing nice
|
||||
mode = SECBOT_HUNT
|
||||
return
|
||||
var/threat = check_threat(target)
|
||||
walk_to(src, src, 0, move_to_delay)
|
||||
if(threat < 4)
|
||||
target = null
|
||||
awaiting_surrender = 0
|
||||
frustration = 0
|
||||
mode = SECBOT_IDLE
|
||||
return
|
||||
if(awaiting_surrender < 5 && ishuman(target) && !target.lying)
|
||||
if(awaiting_surrender == 0)
|
||||
say("Down on the floor, [target]! You have five seconds to comply.")
|
||||
++awaiting_surrender
|
||||
else
|
||||
UnarmedAttack(target)
|
||||
if(ishuman(target) && declare_arrests)
|
||||
var/area/location = get_area(src)
|
||||
broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect <b>[target]</b> in <b>[location]</b>.", src)
|
||||
return
|
||||
|
||||
if(SECBOT_START_PATROL)
|
||||
if(path.len && patrol_target)
|
||||
mode = SECBOT_PATROL
|
||||
return
|
||||
else if(patrol_target)
|
||||
spawn(0)
|
||||
calc_path()
|
||||
if(!path.len)
|
||||
patrol_target = null
|
||||
mode = SECBOT_IDLE
|
||||
else
|
||||
mode = SECBOT_PATROL
|
||||
if(!patrol_target)
|
||||
if(next_destination)
|
||||
find_next_target()
|
||||
else
|
||||
find_patrol_target()
|
||||
say("Engaging patrol mode.")
|
||||
mode = SECBOT_WAIT_PATROL
|
||||
return
|
||||
|
||||
if(SECBOT_WAIT_PATROL)
|
||||
if(patrol_target)
|
||||
mode = SECBOT_START_PATROL
|
||||
else
|
||||
++frustration
|
||||
if(frustration > 120)
|
||||
frustration = 0
|
||||
mode = SECBOT_IDLE
|
||||
|
||||
if(SECBOT_PATROL)
|
||||
patrol_step()
|
||||
return
|
||||
|
||||
if(SECBOT_SUMMON)
|
||||
patrol_step()
|
||||
return
|
||||
|
||||
/mob/living/bot/secbot/UnarmedAttack(var/mob/M, var/proximity)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(!istype(M))
|
||||
return
|
||||
|
||||
if(istype(M, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = M
|
||||
var/cuff = 1
|
||||
if(istype(C, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(istype(H.back, /obj/item/rig) && istype(H.gloves,/obj/item/clothing/gloves/rig))
|
||||
cuff = 0
|
||||
if(!C.lying || C.handcuffed || arrest_type)
|
||||
cuff = 0
|
||||
if(!cuff)
|
||||
C.stun_effect_act(0, 60, null)
|
||||
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
|
||||
do_attack_animation(C)
|
||||
is_attacking = 1
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/stop_attacking_cb), 2)
|
||||
visible_message("<span class='warning'>[C] was prodded by [src] with a stun baton!</span>")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
|
||||
visible_message("<span class='warning'>[src] is trying to put handcuffs on [C]!</span>")
|
||||
if(do_mob(src, C, 60))
|
||||
if(!C.handcuffed)
|
||||
C.handcuffed = new /obj/item/handcuffs(C)
|
||||
C.update_inv_handcuffed()
|
||||
if(preparing_arrest_sounds.len)
|
||||
playsound(loc, pick(preparing_arrest_sounds), 50, 0)
|
||||
else if(istype(M, /mob/living/simple_animal) && !istype(M, /mob/living/bot/secbot))
|
||||
var/mob/living/simple_animal/S = M
|
||||
S.adjustBruteLoss(15)
|
||||
do_attack_animation(M)
|
||||
playsound(loc, /decl/sound_category/swing_hit_sound, 50, 1, -1)
|
||||
is_attacking = 1
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/stop_attacking_cb), 2)
|
||||
visible_message("<span class='warning'>[M] was beaten by [src] with a stun baton!</span>")
|
||||
|
||||
/mob/living/bot/secbot/proc/stop_attacking_cb()
|
||||
is_attacking = FALSE
|
||||
update_icon()
|
||||
|
||||
/mob/living/bot/secbot/explode()
|
||||
visible_message("<span class='warning'>[src] blows apart!</span>")
|
||||
var/turf/Tsec = get_turf(src)
|
||||
|
||||
var/obj/item/secbot_assembly/Sa = new /obj/item/secbot_assembly(Tsec)
|
||||
Sa.build_step = 1
|
||||
Sa.add_overlay("hs_hole")
|
||||
Sa.created_name = name
|
||||
new /obj/item/device/assembly/prox_sensor(Tsec)
|
||||
new /obj/item/melee/baton(Tsec)
|
||||
if(prob(50))
|
||||
new /obj/item/robot_parts/l_arm(Tsec)
|
||||
|
||||
spark(src, 3, alldirs)
|
||||
|
||||
new /obj/effect/decal/cleanable/blood/oil(Tsec)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/bot/secbot/emag_act(var/remaining_charges, var/mob/user, var/feedback)
|
||||
if(!emagged)
|
||||
emagged = 1
|
||||
to_chat(user, (feedback ? feedback : "You short out the lock of \the [src]."))
|
||||
return 1
|
||||
|
||||
/mob/living/bot/secbot/proc/scan_view()
|
||||
target = null
|
||||
for(var/mob/living/M in view(7, src))
|
||||
if(M.invisibility >= INVISIBILITY_LEVEL_ONE)
|
||||
continue
|
||||
if(M.stat)
|
||||
continue
|
||||
|
||||
var/threat = check_threat(M)
|
||||
|
||||
if(threat >= 4)
|
||||
target = M
|
||||
say("Level [threat] infraction alert!")
|
||||
custom_emote(VISIBLE_MESSAGE, "points at [M.name]!")
|
||||
mode = SECBOT_HUNT
|
||||
break
|
||||
return
|
||||
|
||||
/mob/living/bot/secbot/proc/calc_path(var/turf/avoid = null)
|
||||
path = AStar(loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
|
||||
if(isnull(path) || !path.len)
|
||||
path = list()
|
||||
return
|
||||
var/list/path_new = list()
|
||||
var/turf/last = path[path.len]
|
||||
path_new.Add(path[1])
|
||||
for(var/i = 2, i < path.len, i++)
|
||||
if((path[i + 1].x == path[i].x) || (path[i + 1].y == path[i].y)) // we have a straight line, scan for more to cut down
|
||||
path_new.Add(path[i])
|
||||
for(var/j = i + 1, j < path.len, j++)
|
||||
if((path[j + 1].x != path[j - 1].x) && (path[j + 1].y != path[j - 1].y)) // This is a corner and end point of our line
|
||||
path_new.Add(path[j])
|
||||
i = j + 1
|
||||
break
|
||||
else if(j == path.len - 1)
|
||||
path = list()
|
||||
path = path_new.Copy()
|
||||
path.Add(last)
|
||||
return
|
||||
else
|
||||
path_new.Add(path[i])
|
||||
path = list()
|
||||
path = path_new.Copy()
|
||||
path.Add(last)
|
||||
|
||||
/mob/living/bot/secbot/proc/check_threat(var/mob/living/M)
|
||||
if(!M || !istype(M) || M.stat || src == M)
|
||||
return 0
|
||||
|
||||
if(emagged)
|
||||
return 10
|
||||
|
||||
return M.assess_perp(access_scanner, 0, idcheck, check_records, check_arrest)
|
||||
|
||||
/mob/living/bot/secbot/proc/patrol_step()
|
||||
if(loc == patrol_target)
|
||||
patrol_target = null
|
||||
path = list()
|
||||
mode = SECBOT_IDLE
|
||||
walk_to(src, src, 0, move_to_delay + 2)
|
||||
return
|
||||
|
||||
if(path.len && patrol_target)
|
||||
var/turf/next = path[1]
|
||||
if(loc == next)
|
||||
path -= next
|
||||
walk_to(src, src, 0, move_to_delay + 2)
|
||||
return
|
||||
walk_to(src, next, 0, move_to_delay + 2)
|
||||
return
|
||||
else
|
||||
mode = SECBOT_START_PATROL
|
||||
|
||||
|
||||
/mob/living/bot/secbot/proc/find_patrol_target()
|
||||
send_status()
|
||||
nearest_beacon = null
|
||||
next_destination = "__nearest__"
|
||||
listener.post_signal(beacon_freq, "findbeacon", "patrol")
|
||||
|
||||
/mob/living/bot/secbot/proc/find_next_target()
|
||||
send_status()
|
||||
nearest_beacon = null
|
||||
listener.post_signal(beacon_freq, "findbeacon", "patrol")
|
||||
|
||||
/mob/living/bot/secbot/proc/send_status()
|
||||
var/list/kv = list(
|
||||
"type" = "secbot",
|
||||
"name" = name,
|
||||
"loca" = get_area(loc),
|
||||
"mode" = mode
|
||||
)
|
||||
listener.post_signal_multiple(control_freq, kv)
|
||||
|
||||
/obj/secbot_listener
|
||||
var/mob/living/bot/secbot/secbot = null
|
||||
|
||||
/obj/secbot_listener/Destroy()
|
||||
secbot = null
|
||||
return ..()
|
||||
|
||||
/obj/secbot_listener/proc/post_signal(var/freq, var/key, var/value) // send a radio signal with a single data key/value pair
|
||||
post_signal_multiple(freq, list("[key]" = value))
|
||||
|
||||
/obj/secbot_listener/proc/post_signal_multiple(var/freq, var/list/keyval) // send a radio signal with multiple data key/values
|
||||
var/datum/radio_frequency/frequency = SSradio.return_frequency(freq)
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = new()
|
||||
signal.source = secbot
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
signal.data = keyval.Copy()
|
||||
|
||||
if(signal.data["findbeacon"])
|
||||
frequency.post_signal(secbot, signal, filter = RADIO_NAVBEACONS)
|
||||
else if(signal.data["type"] == "secbot")
|
||||
frequency.post_signal(secbot, signal, filter = RADIO_SECBOT)
|
||||
else
|
||||
frequency.post_signal(secbot, signal)
|
||||
|
||||
/obj/secbot_listener/receive_signal(datum/signal/signal)
|
||||
if(!secbot || !secbot.on)
|
||||
return
|
||||
|
||||
var/recv = signal.data["command"]
|
||||
if(recv == "bot_status")
|
||||
secbot.send_status()
|
||||
return
|
||||
|
||||
if(signal.data["active"] == secbot)
|
||||
switch(recv)
|
||||
if("stop")
|
||||
secbot.mode = SECBOT_IDLE
|
||||
secbot.auto_patrol = 0
|
||||
return
|
||||
|
||||
if("go")
|
||||
secbot.mode = SECBOT_IDLE
|
||||
secbot.auto_patrol = 1
|
||||
return
|
||||
|
||||
if("summon")
|
||||
secbot.patrol_target = signal.data["target"]
|
||||
secbot.next_destination = secbot.destination
|
||||
secbot.destination = null
|
||||
//secbot.awaiting_beacon = 0
|
||||
secbot.mode = SECBOT_SUMMON
|
||||
secbot.calc_path()
|
||||
secbot.say("Responding.")
|
||||
return
|
||||
|
||||
recv = signal.data["beacon"]
|
||||
var/valid = signal.data["patrol"]
|
||||
if(!recv || !valid)
|
||||
return
|
||||
|
||||
if(recv == secbot.next_destination) // This beacon is our target
|
||||
secbot.destination = secbot.next_destination
|
||||
secbot.patrol_target = signal.source.loc
|
||||
secbot.next_destination = signal.data["next_patrol"]
|
||||
else if(secbot.next_destination == "__nearest__")
|
||||
var/dist = get_dist(secbot, signal.source.loc)
|
||||
if(dist <= 1)
|
||||
return
|
||||
|
||||
if(secbot.nearest_beacon)
|
||||
if(dist < secbot.closest_dist)
|
||||
secbot.nearest_beacon = recv
|
||||
secbot.patrol_target = secbot.nearest_beacon
|
||||
secbot.next_destination = signal.data["next_patrol"]
|
||||
secbot.closest_dist = dist
|
||||
return
|
||||
else
|
||||
secbot.nearest_beacon = recv
|
||||
secbot.patrol_target = secbot.nearest_beacon
|
||||
secbot.next_destination = signal.data["next_patrol"]
|
||||
secbot.closest_dist = dist
|
||||
|
||||
/mob/living/bot/secbot/attack_hand(mob/living/carbon/human/M as mob)
|
||||
..()
|
||||
|
||||
if(M.a_intent == I_HURT ) //assume he wants to hurt us.
|
||||
idcheck = TRUE
|
||||
target = M
|
||||
mode = SECBOT_HUNT
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/perpname = H.name
|
||||
var/obj/item/card/id/id = H.GetIdCard()
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
|
||||
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
||||
if(R && R.security)
|
||||
R.security.criminal = "*Arrest*"
|
||||
else
|
||||
check_records = TRUE
|
||||
broadcast_security_hud_message("[src] is under attack by <b>[target]</b>, [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect in <b>[get_area(src)]</b>. Requesting backup", src)
|
||||
|
||||
/mob/living/bot/secbot/attack_generic(var/mob/user, var/damage, var/attack_message)
|
||||
..()
|
||||
|
||||
target = user
|
||||
mode = SECBOT_HUNT
|
||||
if(ishuman(user))
|
||||
idcheck = TRUE
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/perpname = H.name
|
||||
var/obj/item/card/id/id = H.GetIdCard()
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
|
||||
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
||||
if(R && R.security)
|
||||
R.security.criminal = "*Arrest*"
|
||||
else
|
||||
check_records = TRUE
|
||||
broadcast_security_hud_message("[src] is under attack by <b>[target]</b>, [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect in <b>[get_area(src)]</b>. Requesting backup", src)
|
||||
|
||||
/mob/living/bot/secbot/bullet_act(var/obj/item/projectile/P, var/def_zone)
|
||||
..()
|
||||
|
||||
if (ismob(P.firer))
|
||||
var/found = 0
|
||||
// Check if we can see them.
|
||||
for(var/mob/living/M in view(7, src))
|
||||
if(M.invisibility >= INVISIBILITY_LEVEL_ONE)
|
||||
continue
|
||||
if(M.stat)
|
||||
continue
|
||||
if(M == P.firer)
|
||||
found = 1
|
||||
break
|
||||
|
||||
if(!found)
|
||||
broadcast_security_hud_message("[src] was shot with <b>[P]</b>, Unable to locate source! Requesting backup", src)
|
||||
return
|
||||
|
||||
target = P.firer
|
||||
mode = SECBOT_HUNT
|
||||
if(ishuman(P.firer))
|
||||
idcheck = TRUE
|
||||
var/mob/living/carbon/human/H = P.firer
|
||||
var/perpname = H.name
|
||||
var/obj/item/card/id/id = H.GetIdCard()
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
|
||||
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
||||
if(R && R.security)
|
||||
R.security.criminal = "*Arrest*"
|
||||
else
|
||||
check_records = TRUE
|
||||
broadcast_security_hud_message("[src] was shot with <b>[P]</b>, projectile came from <b>[target]</b>, [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect in <b>[get_area(src)]</b>. Requesting backup", src)
|
||||
|
||||
/mob/living/bot/secbot/attackby(var/obj/item/O, var/mob/user)
|
||||
..()
|
||||
if(O.GetID() || O.ispen())
|
||||
return
|
||||
|
||||
target = user
|
||||
mode = SECBOT_HUNT
|
||||
if(ishuman(user))
|
||||
idcheck = TRUE
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/perpname = H.name
|
||||
var/obj/item/card/id/id = H.GetIdCard()
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
|
||||
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
||||
if(R && R.security)
|
||||
R.security.criminal = "*Arrest*"
|
||||
else
|
||||
check_records = TRUE
|
||||
broadcast_security_hud_message("[src] is under attack by <b>[target]</b> with <b>[O]</b>, [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect in <b>[get_area(src)]</b>. Requesting backup", src)
|
||||
|
||||
/mob/living/bot/secbot/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)
|
||||
..()
|
||||
|
||||
if(istype(AM,/obj/))
|
||||
var/obj/O = AM
|
||||
if(ismob(O.thrower))
|
||||
target = O.thrower
|
||||
mode = SECBOT_HUNT
|
||||
if(ishuman(O.thrower))
|
||||
idcheck = TRUE
|
||||
var/mob/living/carbon/human/H = O.thrower
|
||||
var/perpname = H.name
|
||||
var/obj/item/card/id/id = H.GetIdCard()
|
||||
if(id)
|
||||
perpname = id.registered_name
|
||||
|
||||
var/datum/record/general/R = SSrecords.find_record("name", perpname)
|
||||
if(R && R.security)
|
||||
R.security.criminal = "*Arrest*"
|
||||
else
|
||||
check_records = TRUE
|
||||
broadcast_security_hud_message("[src] is under attack by <b>[target]</b> with <b>[O]</b>, [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect in <b>[get_area(src)]</b>. Requesting backup", src)
|
||||
|
||||
//Secbot Construction
|
||||
|
||||
/obj/item/clothing/head/helmet/attackby(var/obj/item/device/assembly/signaler/S, mob/user as mob)
|
||||
..()
|
||||
if(!issignaler(S))
|
||||
..()
|
||||
return
|
||||
|
||||
if(type != /obj/item/clothing/head/helmet/security) //Eh, but we don't want people making secbots out of space helmets.
|
||||
return
|
||||
|
||||
if(S.secured)
|
||||
qdel(S)
|
||||
var/obj/item/secbot_assembly/A = new /obj/item/secbot_assembly
|
||||
user.put_in_hands(A)
|
||||
to_chat(user, "You add the signaler to the helmet.")
|
||||
user.drop_from_inventory(src)
|
||||
qdel(src)
|
||||
return 1
|
||||
else
|
||||
return
|
||||
|
||||
/obj/item/secbot_assembly
|
||||
name = "helmet/signaler assembly"
|
||||
desc = "Some sort of bizarre assembly."
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
icon_state = "helmet_signaler"
|
||||
item_state = "helmet"
|
||||
var/build_step = 0
|
||||
var/created_name = "Securitron"
|
||||
|
||||
/obj/item/secbot_assembly/attackby(var/obj/item/O, var/mob/user)
|
||||
..()
|
||||
if(O.iswelder() && !build_step)
|
||||
var/obj/item/weldingtool/WT = O
|
||||
if(WT.use(0, user))
|
||||
build_step = 1
|
||||
add_overlay("hs_hole")
|
||||
to_chat(user, "You weld a hole in \the [src].")
|
||||
return 1
|
||||
|
||||
else if(isprox(O) && (build_step == 1))
|
||||
build_step = 2
|
||||
to_chat(user, "You add \the [O] to [src].")
|
||||
add_overlay("hs_eye")
|
||||
name = "helmet/signaler/prox sensor assembly"
|
||||
user.drop_from_inventory(O,get_turf(src))
|
||||
qdel(O)
|
||||
return 1
|
||||
|
||||
else if((istype(O, /obj/item/robot_parts/l_arm) || istype(O, /obj/item/robot_parts/r_arm)) && build_step == 2)
|
||||
build_step = 3
|
||||
to_chat(user, "You add \the [O] to [src].")
|
||||
name = "helmet/signaler/prox sensor/robot arm assembly"
|
||||
add_overlay("hs_arm")
|
||||
user.drop_from_inventory(O,get_turf(src))
|
||||
qdel(O)
|
||||
return 1
|
||||
|
||||
else if(istype(O, /obj/item/melee/baton) && build_step == 3)
|
||||
to_chat(user, "You complete the Securitron! Beep boop.")
|
||||
var/mob/living/bot/secbot/S = new /mob/living/bot/secbot(get_turf(src))
|
||||
S.name = created_name
|
||||
user.drop_from_inventory(O,get_turf(src))
|
||||
qdel(O)
|
||||
qdel(src)
|
||||
return 1
|
||||
|
||||
else if(O.ispen())
|
||||
var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN)
|
||||
if(!t)
|
||||
return
|
||||
if(!in_range(src, usr) && loc != usr)
|
||||
return
|
||||
created_name = t
|
||||
|
||||
#undef SECBOT_IDLE
|
||||
#undef SECBOT_HUNT
|
||||
#undef SECBOT_ARREST
|
||||
#undef SECBOT_START_PATROL
|
||||
#undef SECBOT_WAIT_PATROL
|
||||
#undef SECBOT_PATROL
|
||||
#undef SECBOT_SUMMON
|
||||
@@ -1,24 +1,25 @@
|
||||
/mob/living/carbon/alien
|
||||
|
||||
name = "alien"
|
||||
desc = "What IS that?"
|
||||
name = "La Creatura"
|
||||
desc = "La creatura. Huh wuh?"
|
||||
icon = 'icons/mob/npc/alien.dmi'
|
||||
icon_state = "alien_s"
|
||||
icon_state = "la_creatura"
|
||||
pass_flags = PASSTABLE
|
||||
health = 100
|
||||
maxHealth = 100
|
||||
health = 50
|
||||
maxHealth = 50
|
||||
mob_size = 4
|
||||
|
||||
var/adult_form
|
||||
var/dead_icon
|
||||
var/icon_dead
|
||||
var/amount_grown = 0
|
||||
var/max_grown = 200
|
||||
var/time_of_birth
|
||||
var/language
|
||||
var/death_msg = "lets out a waning guttural screech, green blood bubbling from its maw."
|
||||
var/death_msg = "lets out a waning guttural screech!"
|
||||
var/meat_amount = 0
|
||||
var/meat_type = /obj/item/reagent_containers/food/snacks/xenomeat
|
||||
|
||||
icon_dead = "la_creatura_dead"
|
||||
|
||||
/mob/living/carbon/alien/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -47,9 +48,7 @@
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/alien/show_inv(mob/user as mob)
|
||||
return //Consider adding cuffs and hats to this, for the sake of fun.
|
||||
return // Consider adding cuffs and hats to this, for the sake of fun.
|
||||
|
||||
/mob/living/carbon/alien/cannot_use_vents()
|
||||
return
|
||||
|
||||
|
||||
return
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/carbon/alien/death(gibbed)
|
||||
if(!gibbed && dead_icon)
|
||||
icon_state = dead_icon
|
||||
if(!gibbed && icon_dead)
|
||||
icon_state = icon_dead
|
||||
return ..(gibbed,death_msg)
|
||||
@@ -1,18 +1,3 @@
|
||||
/obj/item/organ/pariah_brain
|
||||
name = "brain remnants"
|
||||
desc = "Did someone tread on this? It looks useless for cloning or cyborgification."
|
||||
organ_tag = "brain"
|
||||
parent_organ = BP_HEAD
|
||||
icon = 'icons/mob/npc/alien.dmi'
|
||||
icon_state = "chitin"
|
||||
vital = TRUE
|
||||
|
||||
/obj/item/organ/internal/brain/xeno
|
||||
name = "thinkpan"
|
||||
desc = "It looks kind of like an enormous wad of purple bubblegum."
|
||||
icon = 'icons/mob/npc/alien.dmi'
|
||||
icon_state = "chitin"
|
||||
|
||||
/obj/item/organ/internal/brain/slime
|
||||
name = "slime core"
|
||||
desc = "A complex, organic knot of jelly and crystalline particles."
|
||||
@@ -32,4 +17,4 @@
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_books.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_books.dmi'
|
||||
)
|
||||
can_prepare = 0
|
||||
can_prepare = 0
|
||||
@@ -380,13 +380,9 @@
|
||||
mob_win.open()
|
||||
|
||||
// called when something steps onto a human
|
||||
// this handles mulebots and vehicles
|
||||
// this handles 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, /obj/vehicle))
|
||||
var/obj/vehicle/V = AM
|
||||
V.RunOver(src)
|
||||
|
||||
@@ -1,661 +0,0 @@
|
||||
// === MEMETIC ANOMALY ===
|
||||
// =======================
|
||||
//Taken from ancient baystation code- LL
|
||||
|
||||
/**
|
||||
This life form is a form of parasite that can gain a certain level of control
|
||||
over its host. Its player will share vision and hearing with the host, and it'll
|
||||
be able to influence the host through various commands.
|
||||
**/
|
||||
|
||||
// The maximum amount of points a meme can gather.
|
||||
var/global/const/MAXIMUM_MEME_POINTS = 750
|
||||
var/mob/living/parasite/host_brain
|
||||
var/controlling
|
||||
|
||||
|
||||
// === PARASITE ===
|
||||
// ================
|
||||
|
||||
// a list of all the parasites in the mob
|
||||
/mob/living/carbon/var/list/parasites = list()
|
||||
|
||||
/mob/living/parasite
|
||||
var/mob/living/carbon/host // the host that this parasite occupies
|
||||
|
||||
/mob/living/parasite/LateLogin()
|
||||
..()
|
||||
// make the client see through the host instead
|
||||
client.eye = host
|
||||
client.perspective = EYE_PERSPECTIVE
|
||||
|
||||
/mob/living/parasite/proc/enter_host(mob/living/carbon/host)
|
||||
// by default, parasites can't share a body with other life forms
|
||||
if(host.parasites.len > 0)
|
||||
return 0
|
||||
|
||||
src.host = host
|
||||
src.forceMove(host)
|
||||
host.parasites.Add(src)
|
||||
|
||||
if(client) client.eye = host
|
||||
|
||||
return 1
|
||||
|
||||
/mob/living/parasite/proc/exit_host()
|
||||
src.host.parasites.Remove(src)
|
||||
src.host = null
|
||||
src.loc = null
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
// === MEME ===
|
||||
// ============
|
||||
|
||||
|
||||
// Memes use points for many actions
|
||||
/mob/living/parasite/meme/var/meme_points = 100
|
||||
/mob/living/parasite/meme/var/dormant = 0
|
||||
|
||||
// Memes have a list of indoctrinated hosts
|
||||
/mob/living/parasite/meme/var/list/indoctrinated = list()
|
||||
|
||||
/mob/living/parasite/meme/Life()
|
||||
..()
|
||||
|
||||
if(client)
|
||||
if(blinded) client.eye = null
|
||||
else client.eye = host
|
||||
|
||||
if(!host) return
|
||||
|
||||
// recover meme points slowly
|
||||
var/gain = 3
|
||||
if(dormant) gain = 9 // dormant recovers points faster
|
||||
|
||||
meme_points = min(meme_points + gain, MAXIMUM_MEME_POINTS)
|
||||
|
||||
// if there are sleep toxins in the host's body, that's bad
|
||||
if(host.reagents.has_reagent(/decl/reagent/soporific))
|
||||
to_chat(src, "<span class='danger'>Something in your host's blood makes you lose consciousness, you fade away...</span>")
|
||||
src.death()
|
||||
return
|
||||
// a host without brain is no good
|
||||
if(!host.mind)
|
||||
to_chat(src, "<span class='danger'>Your host has no mind, you fade away...</span>")
|
||||
src.death()
|
||||
return
|
||||
if(host.stat == 2)
|
||||
to_chat(src, "<span class='danger'>Your host has died, you fade away...</span>")
|
||||
src.death()
|
||||
return
|
||||
|
||||
if(host.blinded && host.stat != 1) src.blinded = 1
|
||||
else src.blinded = 0
|
||||
|
||||
/mob/living/parasite/meme/death()
|
||||
// make sure the mob is on the actual map before gibbing
|
||||
if(host)
|
||||
src.forceMove(host.loc)
|
||||
src.stat = 2
|
||||
..()
|
||||
qdel(src)
|
||||
|
||||
// When a meme speaks, it speaks through its host
|
||||
/mob/living/parasite/meme/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
|
||||
if(dormant)
|
||||
to_chat(src, "<span class='notice'>You are dormant! </span>")
|
||||
return
|
||||
if(!host)
|
||||
to_chat(usr, "<span class='notice'>You can't speak without a host! </span>")
|
||||
return
|
||||
|
||||
return host.say(message)
|
||||
|
||||
// Same as speak, just with whisper
|
||||
/mob/living/parasite/meme/whisper(message as text)
|
||||
if(dormant)
|
||||
to_chat(src, "<span class='notice'>You are dormant! </span>")
|
||||
return
|
||||
if(!host)
|
||||
to_chat(usr, "<span class='notice'>You can't speak without a host! </span>")
|
||||
return
|
||||
|
||||
return host.whisper(message)
|
||||
|
||||
// Make the host do things
|
||||
/mob/living/parasite/meme/me_verb(message as text)
|
||||
set name = "Me"
|
||||
|
||||
if(dormant)
|
||||
to_chat(src, "<span class='notice'>You are dormant! </span>")
|
||||
return
|
||||
|
||||
if(!host)
|
||||
to_chat(usr, "<span class='notice'>You can't speak without a host! </span>")
|
||||
return
|
||||
|
||||
return host.me_verb(message)
|
||||
|
||||
// A meme understands everything their host understands
|
||||
/mob/living/parasite/meme/say_understands(mob/other)
|
||||
if(!host) return 0
|
||||
|
||||
return host.say_understands(other)
|
||||
|
||||
// Try to use amount points, return 1 if successful
|
||||
/mob/living/parasite/meme/proc/use_points(amount)
|
||||
if(dormant)
|
||||
to_chat(src, "<span class='notice'>You are dormant! </span>")
|
||||
return
|
||||
if(src.meme_points < amount)
|
||||
to_chat(src, "<span class='notice'>You don't have enough meme points(need [amount]).</span>")
|
||||
return 0
|
||||
|
||||
src.meme_points -= round(amount)
|
||||
return 1
|
||||
|
||||
// Let the meme choose one of his indoctrinated mobs as target
|
||||
/mob/living/parasite/meme/proc/select_indoctrinated(var/title, var/message)
|
||||
var/list/candidates
|
||||
|
||||
// Can only affect other mobs thant he host if not blinded
|
||||
if(blinded)
|
||||
candidates = list()
|
||||
to_chat(src, "<span class='notice'>You are blinded, so you can not affect mobs other than your host.</span>")
|
||||
else
|
||||
candidates = indoctrinated.Copy()
|
||||
|
||||
candidates.Add(src.host)
|
||||
|
||||
var/mob/target = null
|
||||
if(candidates.len == 1)
|
||||
target = candidates[1]
|
||||
else
|
||||
var/selected
|
||||
|
||||
var/list/text_candidates = list()
|
||||
var/list/map_text_to_mob = list()
|
||||
|
||||
for(var/mob/living/carbon/human/M in candidates)
|
||||
text_candidates += M.real_name
|
||||
map_text_to_mob[M.real_name] = M
|
||||
|
||||
selected = input(message,title) as null|anything in text_candidates
|
||||
if(!selected) return null
|
||||
|
||||
target = map_text_to_mob[selected]
|
||||
|
||||
return target
|
||||
|
||||
|
||||
// A meme can make people hear things with the thought ability
|
||||
/mob/living/parasite/meme/verb/Thought(mob/M as mob in oview())
|
||||
set category = "Meme"
|
||||
set name = "Thought(150)"
|
||||
set desc = "Implants a thought into the target."
|
||||
|
||||
if(!use_points(150)) return
|
||||
|
||||
var/message = sanitize(input("Message:", "Thought") as text|null)
|
||||
if(message)
|
||||
log_say("MemeThought: [key_name(src)]->[M.key] : [message]",ckey=key_name(src))
|
||||
to_chat(M, "[message]")
|
||||
to_chat(src, "You said: \"[message]\" to [M]")
|
||||
return
|
||||
|
||||
// Mutes the host
|
||||
/mob/living/parasite/meme/verb/Mute()
|
||||
set category = "Meme"
|
||||
set name = "Mute(250)"
|
||||
set desc = "Prevents your host from talking for a while."
|
||||
|
||||
if(!src.host) return
|
||||
/*if(!host.silent)
|
||||
to_chat(usr, "\red Your host already can't speak..")
|
||||
return*/
|
||||
if(!use_points(250)) return
|
||||
|
||||
spawn
|
||||
// backup the host incase we switch hosts after using the verb
|
||||
//var/mob/host = src.host
|
||||
to_chat(host, "<span class='danger'>Your tongue feels numb.. You lose your ability to speak.</span>")
|
||||
to_chat(usr, "<span class='notice'>Your host can't speak anymore.</span>")
|
||||
|
||||
host.silent += 60
|
||||
|
||||
sleep(1200)
|
||||
to_chat(host, "<span class='danger'>Your tongue has feeling again.</span>")
|
||||
to_chat(usr, "<span class='notice'>[host] can speak again.</span>")
|
||||
|
||||
// Makes the host unable to emote
|
||||
/mob/living/parasite/meme/verb/Paralyze()
|
||||
set category = "Meme"
|
||||
set name = "Paralyze(250)"
|
||||
set desc = "Prevents your host from using emote for a while."
|
||||
|
||||
if(!src.host) return
|
||||
/*if(!host.Weaken())
|
||||
to_chat(usr, "\red Your host already can't use body language..")
|
||||
return*/
|
||||
if(!use_points(250)) return
|
||||
|
||||
spawn
|
||||
// backup the host incase we switch hosts after using the verb
|
||||
var/mob/host = src.host
|
||||
|
||||
to_chat(host, "<span class='danger'>Your body feels numb. You lose your ability to use body language.</span>")
|
||||
to_chat(usr, "<span class='notice'>Your host can't use body language anymore.</span>")
|
||||
|
||||
host.Weaken(60)
|
||||
|
||||
sleep(1200)
|
||||
to_chat(host, "<span class='warning'>Your body has feeling again.</span>")
|
||||
to_chat(usr, "<span class='notice'>[host] can use body language again.</span>")
|
||||
|
||||
|
||||
|
||||
// Cause great agony with the host, used for conditioning the host
|
||||
/mob/living/parasite/meme/verb/Agony()
|
||||
set category = "Meme"
|
||||
set name = "Agony(200)"
|
||||
set desc = "Causes significant pain in your host."
|
||||
|
||||
if(!src.host) return
|
||||
if(!use_points(200)) return
|
||||
|
||||
spawn
|
||||
// backup the host incase we switch hosts after using the verb
|
||||
var/mob/host = src.host
|
||||
|
||||
host.paralysis = max(host.paralysis, 2)
|
||||
|
||||
host.flash_pain(10)
|
||||
to_chat(host, "<span class='danger'><font size=5>You feel excrutiating pain all over your body! It is so bad you can't think or articulate yourself properly.</font></span>")
|
||||
|
||||
to_chat(usr, "<span class='notice'>You send a jolt of agonizing pain through [host], they should be unable to concentrate on anything else for half a minute.</span>")
|
||||
|
||||
host.emote("scream")
|
||||
|
||||
for(var/i=0, i<10, i++)
|
||||
host.stuttering = 2
|
||||
sleep(50)
|
||||
if(prob(80)) host.flash_pain(10)
|
||||
if(prob(10)) host.paralysis = max(host.paralysis, 2)
|
||||
if(prob(15)) host.emote("twitch")
|
||||
else if(prob(15)) host.emote("scream")
|
||||
else if(prob(10)) host.emote("collapse")
|
||||
|
||||
if(i == 10)
|
||||
to_chat(host, "<span class='danger'>THE PAIN! AGHH, THE PAIN! MAKE IT STOP! ANYTHING TO MAKE IT STOP!</span>")
|
||||
|
||||
to_chat(host, "<span class='warning'>The pain subsides.</span>")
|
||||
|
||||
// Cause great joy with the host, used for conditioning the host
|
||||
/mob/living/parasite/meme/verb/Joy()
|
||||
set category = "Meme"
|
||||
set name = "Joy(200)"
|
||||
set desc = "Causes significant joy in your host."
|
||||
|
||||
if(!src.host) return
|
||||
if(!use_points(200)) return
|
||||
|
||||
spawn
|
||||
var/mob/host = src.host
|
||||
host.druggy = max(host.druggy, 50)
|
||||
host.slurring = max(host.slurring, 10)
|
||||
|
||||
to_chat(usr, "<span class='notice'>You stimulate [host.name]'s brain, injecting waves of endorphines and dopamine into the tissue. They should now forget all their worries, particularly relating to you, for around a minute.</span>")
|
||||
|
||||
to_chat(host, "<span class='notice'><font size=5>You are feeling wonderful! Your head is numb and drowsy, and you can't help forgetting all the worries in the world.</font></span>")
|
||||
|
||||
while(host.druggy > 0)
|
||||
sleep(10)
|
||||
|
||||
to_chat(host, "<span class='warning'>You are feeling clear-headed again.</span>")
|
||||
|
||||
// Cause the target to hallucinate.
|
||||
/mob/living/parasite/meme/verb/Hallucinate(mob/living/carbon/human/target as mob in oview())
|
||||
set category = "Meme"
|
||||
set name = "Hallucinate(300)"
|
||||
set desc = "Makes your host hallucinate, has a short delay."
|
||||
|
||||
if(!istype(target, /mob/living/carbon/human) || !target.mind)
|
||||
to_chat(src, "<span class='warning'>You can't remotely ruin this ones mind.</span>")
|
||||
return
|
||||
if(!(target in view(host)))
|
||||
to_chat(src, "<span class='warning'>You need to make eye-contact with the target.</span>")
|
||||
return
|
||||
if(!(target in indoctrinated))
|
||||
to_chat(src, "<span class='warning'>You need to attune the target first.</span>")
|
||||
return
|
||||
if(!target) return
|
||||
if(!use_points(300)) return
|
||||
|
||||
spawn(rand(300,600))
|
||||
if(target) target.hallucination += 400
|
||||
|
||||
to_chat(usr, "<span class='notice'>You make [target] hallucinate.</span>")
|
||||
|
||||
// Jump to a closeby target through a whisper
|
||||
/mob/living/parasite/meme/verb/SubtleJump(mob/living/carbon/human/target as mob in oview())
|
||||
set category = "Meme"
|
||||
set name = "Subtle Jump(350)"
|
||||
set desc = "Move to a closeby human through a whisper."
|
||||
|
||||
if(!istype(target, /mob/living/carbon/human) || !target.mind)
|
||||
to_chat(src, "<span class='warning'>You can't jump to this creature.</span>")
|
||||
return
|
||||
|
||||
if(target.isSynthetic())
|
||||
to_chat(src, "<span class='warning'>You can't affect synthetics.</span>")
|
||||
return
|
||||
|
||||
if(!(target in view(1, host)+src))
|
||||
to_chat(src, "<span class='warning'>The target is not close enough.</span>")
|
||||
return
|
||||
|
||||
// Find out whether we can speak
|
||||
if (host.silent || (host.disabilities & 64))
|
||||
to_chat(src, "<span class='warning'>Your host can't speak.</span>")
|
||||
return
|
||||
|
||||
if(!use_points(350)) return
|
||||
|
||||
for(var/mob/M in view(1, host))
|
||||
M.show_message("<B>[host]</B> whispers something incoherent.",2) // 2 stands for hearable message
|
||||
|
||||
// Find out whether the target can hear
|
||||
if(target.disabilities & 32 || isdeaf(target))
|
||||
to_chat(src, "<span class='warning'>Your target doesn't seem to hear you.</span>")
|
||||
return
|
||||
|
||||
if(target.parasites.len > 0)
|
||||
to_chat(src, "<span class='warning'>Your target already is possessed by something.</span>")
|
||||
return
|
||||
|
||||
src.exit_host()
|
||||
src.enter_host(target)
|
||||
|
||||
to_chat(usr, "<span class='notice'>You successfully jumped to [target].</span>")
|
||||
log_admin("[src.key] has jumped to [target]",ckey=key_name(src))
|
||||
message_admins("[src.key] has jumped to [target]")
|
||||
|
||||
// Jump to a distant target through a shout
|
||||
/mob/living/parasite/meme/verb/ObviousJump(mob/living/carbon/human/target as mob in world)
|
||||
set category = "Meme"
|
||||
set name = "Obvious Jump(750)"
|
||||
set desc = "Move to any mob in view through a shout."
|
||||
|
||||
if(!istype(target, /mob/living/carbon/human) || !target.mind)
|
||||
to_chat(src, "<span class='warning'>You can't jump to this creature.</span>")
|
||||
return
|
||||
|
||||
if(target.isSynthetic())
|
||||
to_chat(src, "<span class='warning'>You can't affect synthetics.</span>")
|
||||
return
|
||||
|
||||
if(!(target in view(host)))
|
||||
to_chat(src, "<span class='warning'>The target is not close enough.</span>")
|
||||
return
|
||||
|
||||
// Find out whether we can speak
|
||||
if (host.silent || (host.disabilities & 64))
|
||||
to_chat(src, "<span class='warning'>Your host can't speak.</span>")
|
||||
return
|
||||
|
||||
if(!use_points(750)) return
|
||||
|
||||
for(var/mob/M in view(host)+src)
|
||||
M.show_message("<B>[host]</B> screams something incoherent!",2) // 2 stands for hearable message
|
||||
|
||||
// Find out whether the target can hear
|
||||
if(target.disabilities & 32 || isdeaf(target))
|
||||
to_chat(src, "<span class='warning'>Your target doesn't seem to hear you.</span>")
|
||||
return
|
||||
|
||||
if(target.parasites.len > 0)
|
||||
to_chat(src, "<span class='warning'>Your target already is possessed by something.</span>")
|
||||
return
|
||||
|
||||
src.exit_host()
|
||||
src.enter_host(target)
|
||||
|
||||
to_chat(usr, "<span class='notice'>You successfully jumped to [target].</span>")
|
||||
log_admin("[src.key] has jumped to [target]",ckey=key_name(src))
|
||||
message_admins("[src.key] has jumped to [target]")
|
||||
|
||||
// Jump to an attuned mob for free
|
||||
/mob/living/parasite/meme/verb/AttunedJump(mob/living/carbon/human/target as mob in world)
|
||||
set category = "Meme"
|
||||
set name = "Attuned Jump(0)"
|
||||
set desc = "Move to a mob in sight that you have already attuned."
|
||||
|
||||
if(!istype(target, /mob/living/carbon/human) || !target.mind)
|
||||
to_chat(src, "<span class='warning'>You can't jump to this creature.</span>")
|
||||
return
|
||||
|
||||
if(target.isSynthetic())
|
||||
to_chat(src, "<span class='warning'>You can't affect synthetics.</span>")
|
||||
return
|
||||
|
||||
if(!(target in view(host)))
|
||||
to_chat(src, "<span class='warning'>You need to make eye-contact with the target.</span>")
|
||||
return
|
||||
if(!(target in indoctrinated))
|
||||
to_chat(src, "<span class='warning'>You need to attune the target first.</span>")
|
||||
return
|
||||
|
||||
src.exit_host()
|
||||
src.enter_host(target)
|
||||
|
||||
to_chat(usr, "<span class='notice'>You successfully jumped to [target].</span>")
|
||||
|
||||
log_admin("[src.key] has jumped to [target]",ckey=key_name(src))
|
||||
message_admins("[src.key] has jumped to [target]")
|
||||
|
||||
// ATTUNE a mob, adding it to the indoctrinated list
|
||||
/mob/living/parasite/meme/verb/Attune()
|
||||
set category = "Meme"
|
||||
set name = "Attune(400)"
|
||||
set desc = "Change the host's brain structure, making it easier for you to manipulate him."
|
||||
|
||||
if(host in src.indoctrinated)
|
||||
to_chat(usr, "<span class='notice'>You have already attuned this host.</span>")
|
||||
return
|
||||
|
||||
if(!host) return
|
||||
|
||||
for (var/obj/item/implant/mindshield/I in host)
|
||||
if (I.implanted)
|
||||
to_chat(src, "<span class='warning'>Your host's mind is shielded!</span>")
|
||||
return
|
||||
|
||||
if(!use_points(400)) return
|
||||
|
||||
src.indoctrinated.Add(host)
|
||||
|
||||
to_chat(usr, "<span class='notice'>You successfully indoctrinated [host].</span>")
|
||||
to_chat(host, "<span class='danger'>Your head feels a bit roomier...</span>")
|
||||
|
||||
log_admin("[src.key] has attuned [host]",ckey=key_name(src))
|
||||
message_admins("[src.key] has attuned [host]")
|
||||
|
||||
// Enables the mob to take a lot more damage
|
||||
/mob/living/parasite/meme/verb/Analgesic()
|
||||
set category = "Meme"
|
||||
set name = "Analgesic(500)"
|
||||
set desc = "Combat drug that allows the host to move normally, even under life-threatening pain."
|
||||
|
||||
if(!host) return
|
||||
if(!(host in indoctrinated))
|
||||
to_chat(usr, "<span class='warning'>You need to attune the host first.</span>")
|
||||
return
|
||||
if(!use_points(500)) return
|
||||
|
||||
to_chat(usr, "<span class='notice'>You inject drugs into [host].</span>")
|
||||
to_chat(host, "<span class='danger'>You feel your body strengthen and your pain subside.</span>")
|
||||
host.analgesic = 60
|
||||
while(host.analgesic > 0)
|
||||
sleep(60)
|
||||
to_chat(host, "<span class='notice'>The dizziness wears off, and you can feel pain again.</span>")
|
||||
|
||||
|
||||
/mob/proc/clearHUD()
|
||||
//update_clothing()
|
||||
if(client) client.screen.Cut()
|
||||
|
||||
// Take control of the mob
|
||||
/mob/living/parasite/meme/verb/Possession()
|
||||
set category = "Meme"
|
||||
set name = "Possession(500)"
|
||||
set desc = "Take direct control of the host for a while."
|
||||
|
||||
if(!host)
|
||||
to_chat(src, "You have discovered a severe bug - NO HOST. CONTACT DEVELOPER.")
|
||||
return
|
||||
|
||||
if(src.stat)
|
||||
to_chat(src, "<span class='warning'>You cannot do that in your current state.</span>")
|
||||
return
|
||||
|
||||
for (var/obj/item/implant/mindshield/I in host)
|
||||
if (I.implanted)
|
||||
to_chat(src, "<span class='warning'>Your host's mind is shielded!</span>")
|
||||
return
|
||||
|
||||
if(!use_points(500)) return
|
||||
|
||||
to_chat(src, "<span class='danger'>You assume direct control!</span>")
|
||||
|
||||
spawn()
|
||||
|
||||
if(!host || !src || controlling)
|
||||
return
|
||||
else
|
||||
|
||||
to_chat(src, "<span class='warning'>You shroud your hosts brain, assuming control!</span>")
|
||||
to_chat(host, "<span class='danger'>You can feel thoughts that arent your own begin to dictate your body's actions.</span>")
|
||||
|
||||
// host -> brain
|
||||
var/h2b_id = host.computer_id
|
||||
var/h2b_ip= host.lastKnownIP
|
||||
host.computer_id = null
|
||||
host.lastKnownIP = null
|
||||
|
||||
qdel(host_brain)
|
||||
host_brain = new(src)
|
||||
|
||||
host_brain.ckey = host.ckey
|
||||
|
||||
host_brain.name = host.name
|
||||
|
||||
if(!host_brain.computer_id)
|
||||
host_brain.computer_id = h2b_id
|
||||
|
||||
if(!host_brain.lastKnownIP)
|
||||
host_brain.lastKnownIP = h2b_ip
|
||||
|
||||
// self -> host
|
||||
var/s2h_id = src.computer_id
|
||||
var/s2h_ip= src.lastKnownIP
|
||||
src.computer_id = null
|
||||
src.lastKnownIP = null
|
||||
|
||||
host.ckey = src.ckey
|
||||
|
||||
if(!host.computer_id)
|
||||
host.computer_id = s2h_id
|
||||
|
||||
if(!host.lastKnownIP)
|
||||
host.lastKnownIP = s2h_ip
|
||||
|
||||
controlling = 1
|
||||
|
||||
spawn(300)
|
||||
detatch()
|
||||
|
||||
return
|
||||
|
||||
/mob/living/parasite/meme/proc/detatch()
|
||||
|
||||
if(!host || !controlling) return
|
||||
|
||||
if(istype(host,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = host
|
||||
var/obj/item/organ/external/head = H.get_organ(BP_HEAD)
|
||||
head.implants -= src
|
||||
|
||||
controlling = 0
|
||||
|
||||
if(host_brain)
|
||||
|
||||
// these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed.
|
||||
// computer_id and IP are not updated magically on their own in offline mobs -walter0o
|
||||
|
||||
// host -> self
|
||||
var/h2s_id = host.computer_id
|
||||
var/h2s_ip= host.lastKnownIP
|
||||
host.computer_id = null
|
||||
host.lastKnownIP = null
|
||||
|
||||
src.ckey = host.ckey
|
||||
|
||||
if(!src.computer_id)
|
||||
src.computer_id = h2s_id
|
||||
|
||||
if(!host_brain.lastKnownIP)
|
||||
src.lastKnownIP = h2s_ip
|
||||
|
||||
// brain -> host
|
||||
var/b2h_id = host_brain.computer_id
|
||||
var/b2h_ip= host_brain.lastKnownIP
|
||||
host_brain.computer_id = null
|
||||
host_brain.lastKnownIP = null
|
||||
|
||||
host.ckey = host_brain.ckey
|
||||
|
||||
if(!host.computer_id)
|
||||
host.computer_id = b2h_id
|
||||
|
||||
if(!host.lastKnownIP)
|
||||
host.lastKnownIP = b2h_ip
|
||||
|
||||
qdel(host_brain)
|
||||
|
||||
|
||||
// Enter dormant mode, increases meme point gain
|
||||
/mob/living/parasite/meme/verb/Dormant()
|
||||
set category = "Meme"
|
||||
set name = "Dormant(100)"
|
||||
set desc = "Speed up point recharging, will force you to cease all actions until all points are recharged."
|
||||
|
||||
if(!host) return
|
||||
if(!use_points(100)) return
|
||||
|
||||
to_chat(usr, "<span class='warning'>You enter dormant mode.You won't be able to take action until all your points have recharged.</span>")
|
||||
|
||||
dormant = 1
|
||||
|
||||
while(meme_points < MAXIMUM_MEME_POINTS)
|
||||
sleep(10)
|
||||
|
||||
dormant = 0
|
||||
|
||||
to_chat(usr, "<span class='danger'>You have regained all points and exited dormant mode!</span>")
|
||||
|
||||
/mob/living/parasite/meme/verb/Show_Points()
|
||||
set category = "Meme"
|
||||
|
||||
to_chat(usr, "<b>Meme Points: [src.meme_points]/[MAXIMUM_MEME_POINTS]</b>")
|
||||
|
||||
// Stat panel to show meme points, copypasted from alien
|
||||
/mob/living/parasite/meme/Stat()
|
||||
..()
|
||||
statpanel("Status")
|
||||
if (client && client.holder)
|
||||
stat(null, "([x], [y], [z])")
|
||||
|
||||
if (client && client.statpanel == "Status")
|
||||
stat(null, "Meme Points: [src.meme_points]")
|
||||
@@ -1,29 +0,0 @@
|
||||
/mob/living/parasite/captive_brain
|
||||
name = "host brain"
|
||||
real_name = "host brain"
|
||||
universal_understand = 1
|
||||
|
||||
/mob/living/parasite/captive_brain/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE)
|
||||
if(istype(src.loc,/mob/living/parasite/meme))
|
||||
|
||||
if (!message)
|
||||
return
|
||||
log_say("[key_name(src)] : [message]",ckey=key_name(src))
|
||||
if (stat == 2)
|
||||
return say_dead(message)
|
||||
|
||||
var/mob/living/parasite/meme/ME = src.loc
|
||||
to_chat(src, "You whisper silently, \"[message]\"")
|
||||
to_chat(ME.host, "The captive mind of [src] whispers, \"[message]\"")
|
||||
|
||||
for (var/mob/M in player_list)
|
||||
if (istype(M, /mob/abstract/new_player))
|
||||
continue
|
||||
else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
|
||||
to_chat(M, "The captive mind of [src] whispers, \"[message]\"")
|
||||
|
||||
/mob/living/parasite/captive_brain/emote(var/message)
|
||||
return
|
||||
|
||||
/mob/living/parasite/captive_brain/send_emote()
|
||||
return
|
||||
@@ -47,6 +47,3 @@
|
||||
stat(null, "Maintenance Lock: [B.locked ? "Locked" : "Unlocked"]")
|
||||
if(B.emagged)
|
||||
stat(null, "Bot M#$FUN90: MALFUNC--")
|
||||
if(istype(card.loc, /mob/living/bot/floorbot))
|
||||
var/mob/living/bot/floorbot/F = card.loc
|
||||
stat(null, "Metal Count: [F.amount]/[F.maxAmount]")
|
||||
|
||||
@@ -143,20 +143,6 @@
|
||||
return FALSE
|
||||
|
||||
/obj/item/robot_parts/robot_suit/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head)
|
||||
var/obj/item/stack/material/M = W
|
||||
if(M.use(1))
|
||||
var/obj/item/secbot_assembly/ed209_assembly/B = new /obj/item/secbot_assembly/ed209_assembly
|
||||
B.forceMove(get_turf(src))
|
||||
to_chat(user, SPAN_NOTICE("You armed the robot frame."))
|
||||
if(user.get_inactive_hand() == src)
|
||||
user.remove_from_mob(src)
|
||||
user.put_in_inactive_hand(B)
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, SPAN_WARNING("You need one sheet of metal to arm the robot frame."))
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/robot_parts/l_leg))
|
||||
if(l_leg)
|
||||
to_chat(user, SPAN_WARNING("\The [src] already has \a [l_leg] installed."))
|
||||
|
||||
@@ -1,102 +1,3 @@
|
||||
/mob/living/simple_animal/hostile/alien
|
||||
name = "alien hunter"
|
||||
desc = "Hiss!"
|
||||
icon = 'icons/mob/npc/alien.dmi'
|
||||
icon_state = "alienh_running"
|
||||
icon_living = "alienh_running"
|
||||
icon_dead = "alien_l"
|
||||
icon_gib = "syndicate_gib"
|
||||
response_help = "pokes"
|
||||
response_disarm = "shoves"
|
||||
response_harm = "hits"
|
||||
speed = -1
|
||||
meat_type = /obj/item/reagent_containers/food/snacks/xenomeat
|
||||
organ_names = list("chest", "lower body", "left arm", "right arm", "left leg", "right leg", "head")
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
blood_type = "#5BDD04"
|
||||
harm_intent_damage = 5
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
attacktext = "slashed"
|
||||
a_intent = I_HURT
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
min_oxy = 0
|
||||
max_oxy = 0
|
||||
min_tox = 0
|
||||
max_tox = 0
|
||||
min_co2 = 0
|
||||
max_co2 = 0
|
||||
min_n2 = 0
|
||||
max_n2 = 0
|
||||
unsuitable_atoms_damage = 15
|
||||
faction = "alien"
|
||||
environment_smash = 2
|
||||
status_flags = CANPUSH
|
||||
minbodytemp = 0
|
||||
heat_damage_per_tick = 20
|
||||
mob_size = 10
|
||||
|
||||
tameable = FALSE
|
||||
attack_emote = "growls at"
|
||||
smart_ranged = TRUE
|
||||
|
||||
butchering_products = list(/obj/item/stack/material/animalhide/xeno = 5)
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/drone
|
||||
name = "alien drone"
|
||||
icon_state = "aliend_running"
|
||||
icon_living = "aliend_running"
|
||||
icon_dead = "aliend_l"
|
||||
health = 60
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/sentinel
|
||||
name = "alien sentinel"
|
||||
icon_state = "aliens_running"
|
||||
icon_living = "aliens_running"
|
||||
icon_dead = "aliens_l"
|
||||
health = 120
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
ranged = 1
|
||||
projectiletype = /obj/item/projectile/neurotox
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/queen
|
||||
name = "alien queen"
|
||||
icon_state = "alienq_running"
|
||||
icon_living = "alienq_running"
|
||||
icon_dead = "alienq_l"
|
||||
health = 250
|
||||
maxHealth = 250
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
ranged = 1
|
||||
move_to_delay = 3
|
||||
projectiletype = /obj/item/projectile/neurotox
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
rapid = 1
|
||||
status_flags = 0
|
||||
mob_size = 12
|
||||
|
||||
/mob/living/simple_animal/hostile/alien/queen/large
|
||||
name = "alien empress"
|
||||
icon = 'icons/mob/npc/alienqueen.dmi'
|
||||
icon_state = "queen_s"
|
||||
icon_living = "queen_s"
|
||||
icon_dead = "queen_dead"
|
||||
move_to_delay = 4
|
||||
maxHealth = 400
|
||||
health = 400
|
||||
mob_size = 14
|
||||
|
||||
/obj/item/projectile/neurotox
|
||||
damage = 30
|
||||
icon_state = "toxin"
|
||||
|
||||
// Xenoarch aliens.
|
||||
/mob/living/simple_animal/hostile/retaliate/samak
|
||||
name = "samak"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/simple_animal/hostile/faithless
|
||||
name = "Faithless"
|
||||
desc = "The Wish Granter's faith in humanity, incarnate."
|
||||
name = "faithless"
|
||||
desc = "A creature. Darkness incarnate?"
|
||||
icon = 'icons/mob/npc/human.dmi'
|
||||
icon_state = "faithless"
|
||||
icon_living = "faithless"
|
||||
|
||||
Reference in New Issue
Block a user