Holocalls
This commit is contained in:
+115
-34
@@ -57,8 +57,16 @@ Possible to do for anyone motivated enough:
|
||||
holopads += src
|
||||
|
||||
/obj/machinery/holopad/Destroy()
|
||||
for (var/mob/living/silicon/ai/master in masters)
|
||||
clear_holo(master)
|
||||
if(outgoing_call)
|
||||
LAZYADD(holo_calls, outgoing_call)
|
||||
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
HC.ConnectionFailure(src)
|
||||
LAZYCLEARLIST(holo_calls)
|
||||
|
||||
for (var/I in masters)
|
||||
clear_holo(I)
|
||||
holopads -= src
|
||||
return ..()
|
||||
|
||||
@@ -128,12 +136,49 @@ Possible to do for anyone motivated enough:
|
||||
temp = "A request for AI presence was already sent recently.<BR>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
|
||||
else if(href_list["Holocall"])
|
||||
if(outgoing_call)
|
||||
return
|
||||
|
||||
temp = "You must stand on the holopad to make a call!<br>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
if(usr.loc == loc)
|
||||
var/list/callnames = list()
|
||||
for(var/I in holopads)
|
||||
var/area/A = get_area(I)
|
||||
if(A)
|
||||
LAZYADD(callnames[A], I)
|
||||
callnames -= get_area(src)
|
||||
|
||||
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
|
||||
if(QDELETED(usr) || !result || outgoing_call)
|
||||
return
|
||||
|
||||
if(usr.loc == loc)
|
||||
temp = "Dialing...<br>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
new /datum/holocall(usr, src, callnames[result])
|
||||
|
||||
else if(href_list["connectcall"])
|
||||
var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
|
||||
if(!QDELETED(call_to_connect))
|
||||
call_to_connect.Answer(src)
|
||||
temp = ""
|
||||
|
||||
else if(href_list["disconnectcall"])
|
||||
var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"])
|
||||
if(!QDELETED(call_to_disconnect))
|
||||
call_to_disconnect.Disconnect(src)
|
||||
temp = ""
|
||||
|
||||
else if(href_list["mainmenu"])
|
||||
temp = ""
|
||||
if(outgoing_call)
|
||||
outgoing_call.Disconnect()
|
||||
|
||||
updateDialog()
|
||||
add_fingerprint(usr)
|
||||
|
||||
//do not allow AIs to answer calls or people will use it to meta the AI sattelite
|
||||
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
|
||||
if (!istype(user))
|
||||
return
|
||||
@@ -148,39 +193,75 @@ Possible to do for anyone motivated enough:
|
||||
clear_holo(user)
|
||||
|
||||
/obj/machinery/holopad/process()
|
||||
if(masters.len)//If there is a hologram.
|
||||
for (var/mob/living/silicon/ai/master in masters)
|
||||
if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
|
||||
if(!(stat & NOPOWER))//If the machine has power.
|
||||
if(HOLOPAD_MODE == RANGE_BASED)
|
||||
if(get_dist(master.eyeobj, src) <= holo_range)
|
||||
return TRUE
|
||||
else
|
||||
var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, master.eyeobj)
|
||||
if(get_dist(pad_close, master.eyeobj) <= holo_range)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
|
||||
unset_holo(master)
|
||||
pad_close.set_holo(master, h)
|
||||
return TRUE
|
||||
|
||||
else if (HOLOPAD_MODE == AREA_BASED)
|
||||
|
||||
var/area/holo_area = get_area(src)
|
||||
var/area/eye_area = get_area(master.eyeobj)
|
||||
|
||||
if(eye_area in holo_area.related)
|
||||
return TRUE
|
||||
|
||||
clear_holo(master)//If not, we want to get rid of the hologram.
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/activate_holo(mob/living/silicon/ai/user)
|
||||
if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it
|
||||
if (istype(user.current, /obj/machinery/holopad))
|
||||
for(var/I in masters)
|
||||
var/mob/living/master = I
|
||||
var/mob/living/silicon/ai/AI = master
|
||||
if(!istype(AI))
|
||||
AI = null
|
||||
|
||||
if(!QDELETED(master) && !master.incapacitated() && master.client && (!AI || AI.eyeobj))//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
|
||||
if(is_operational())//If the machine has power.
|
||||
if(AI) //ais are range based
|
||||
if(get_dist(AI.eyeobj, src) <= holo_range)
|
||||
continue
|
||||
else
|
||||
var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, AI.eyeobj)
|
||||
if(get_dist(pad_close, AI.eyeobj) <= holo_range)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
|
||||
unset_holo(master)
|
||||
pad_close.set_holo(master, h)
|
||||
continue
|
||||
else
|
||||
continue
|
||||
clear_holo(master)//If not, we want to get rid of the hologram.
|
||||
|
||||
if(outgoing_call)
|
||||
outgoing_call.Check()
|
||||
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad != src)
|
||||
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(outgoing_call)
|
||||
HC.Disconnect(src)//can't answer calls while calling
|
||||
else
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring!
|
||||
|
||||
/obj/machinery/holopad/proc/activate_holo(mob/living/user)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(!istype(AI))
|
||||
AI = null
|
||||
|
||||
if(is_operational() && (!AI || AI.eyeobj.loc == loc))//If the projector has power and client eye is on it
|
||||
if (AI && istype(AI.current, /obj/machinery/holopad))
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> \black Image feed in progress.")
|
||||
return
|
||||
create_holo(user)//Create one.
|
||||
src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
|
||||
|
||||
var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location.
|
||||
if(AI)
|
||||
Hologram.icon = AI.holo_icon
|
||||
else //make it like real life
|
||||
Hologram.icon = user.icon
|
||||
Hologram.icon_state = user.icon_state
|
||||
Hologram.copy_overlays(user, TRUE)
|
||||
//codersprite some holo effects here
|
||||
Hologram.alpha = 100
|
||||
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
|
||||
Hologram.Impersonation = user
|
||||
|
||||
Hologram.languages_spoken = user.languages_spoken
|
||||
Hologram.mouse_opacity = 0//So you can't click on it.
|
||||
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
|
||||
Hologram.anchored = 1//So space wind cannot drag it.
|
||||
Hologram.name = "[user.name] (Hologram)"//If someone decides to right click.
|
||||
Hologram.set_light(2) //hologram lighting
|
||||
|
||||
set_holo(user, Hologram)
|
||||
visible_message("A holographic image of [user] flicks to life right before your eyes!")
|
||||
|
||||
return Hologram
|
||||
else
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> \black Unable to project hologram.")
|
||||
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
diff a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm (rejected hunks)
|
||||
@@ -26,16 +26,12 @@ Possible to do for anyone motivated enough:
|
||||
|
||||
#define HOLOPAD_PASSIVE_POWER_USAGE 1
|
||||
#define HOLOGRAM_POWER_USAGE 2
|
||||
-#define RANGE_BASED 4
|
||||
-#define AREA_BASED 6
|
||||
-
|
||||
-var/const/HOLOPAD_MODE = RANGE_BASED
|
||||
|
||||
var/list/holopads = list()
|
||||
|
||||
/obj/machinery/holopad
|
||||
- name = "\improper AI holopad"
|
||||
- desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely."
|
||||
+ name = "Holopad"
|
||||
+ desc = "It's a floor-mounted device for projecting holographic images."
|
||||
icon_state = "holopad0"
|
||||
layer = LOW_OBJ_LAYER
|
||||
flags = HEAR
|
||||
@@ -48,10 +44,13 @@ var/list/holopads = list()
|
||||
obj_integrity = 300
|
||||
max_integrity = 300
|
||||
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 0)
|
||||
- var/list/masters = list()//List of AIs that use the holopad
|
||||
+ var/list/masters = list()//List of living mobs that use the holopad
|
||||
var/last_request = 0 //to prevent request spam. ~Carn
|
||||
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
|
||||
var/temp = ""
|
||||
+ var/list/holo_calls //array of /datum/holocalls
|
||||
+ var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
|
||||
+ var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
|
||||
|
||||
/obj/machinery/holopad/Initialize()
|
||||
..()
|
||||
@@ -94,20 +101,60 @@ var/list/holopads = list()
|
||||
return
|
||||
return ..()
|
||||
|
||||
+/obj/machinery/holopad/proc/CheckCallClose()
|
||||
+ for(var/I in holo_calls)
|
||||
+ var/datum/holocall/HC = I
|
||||
+ if(usr == HC.eye)
|
||||
+ HC.Disconnect(HC.calling_holopad) //disconnect via clicking the called holopad
|
||||
+ return TRUE
|
||||
+ return FALSE
|
||||
+
|
||||
+/obj/machinery/holopad/Click(location,control,params)
|
||||
+ if(!CheckCallClose())
|
||||
+ return ..()
|
||||
+
|
||||
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
|
||||
- interact(user)
|
||||
+ if(!CheckCallClose())
|
||||
+ interact(user)
|
||||
|
||||
/obj/machinery/holopad/interact(mob/living/carbon/human/user) //Carn: Hologram requests.
|
||||
if(!istype(user))
|
||||
return
|
||||
- if(user.stat || stat & (NOPOWER|BROKEN))
|
||||
+ if(user.incapacitated() || !is_operational())
|
||||
+ return
|
||||
+
|
||||
+ if(outgoing_call) //someone is making a call, leave them be
|
||||
return
|
||||
+
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(temp)
|
||||
dat = temp
|
||||
else
|
||||
- dat = "<A href='?src=\ref[src];AIrequest=1'>request an AI's presence.</A>"
|
||||
+ dat = "<a href='?src=\ref[src];AIrequest=1'>Request an AI's presence.</a><br>"
|
||||
+ dat += "<a href='?src=\ref[src];Holocall=1'>Call another holopad.</a><br>"
|
||||
+
|
||||
+ if(LAZYLEN(holo_calls))
|
||||
+ dat += "=====================================================<br>"
|
||||
+
|
||||
+ var/one_answered_call = FALSE
|
||||
+ var/one_unanswered_call = FALSE
|
||||
+ for(var/I in holo_calls)
|
||||
+ var/datum/holocall/HC = I
|
||||
+ if(HC.connected_holopad != src)
|
||||
+ dat += "<a href='?src=\ref[src];connectcall=\ref[HC]'>Answer call from [get_area(HC.calling_holopad)].</a><br>"
|
||||
+ one_unanswered_call = TRUE
|
||||
+ else
|
||||
+ one_answered_call = TRUE
|
||||
+
|
||||
+ if(one_answered_call && one_unanswered_call)
|
||||
+ dat += "=====================================================<br>"
|
||||
+ //we loop twice for formatting
|
||||
+ for(var/I in holo_calls)
|
||||
+ var/datum/holocall/HC = I
|
||||
+ if(HC.connected_holopad == src)
|
||||
+ dat += "<a href='?src=\ref[src];disconnectcall=\ref[HC]'>Disconnect call from [HC.user].</a><br>"
|
||||
+
|
||||
|
||||
var/datum/browser/popup = new(user, "holopad", name, 300, 130)
|
||||
popup.set_content(dat)
|
||||
@@ -115,7 +162,10 @@ var/list/holopads = list()
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/holopad/Topic(href, href_list)
|
||||
- if(..())
|
||||
+ if(..() || isAI(usr))
|
||||
+ return
|
||||
+ add_fingerprint(usr)
|
||||
+ if(!is_operational())
|
||||
return
|
||||
if (href_list["AIrequest"])
|
||||
if(last_request + 200 < world.time)
|
||||
@@ -194,59 +317,81 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
for(var/mob/living/silicon/ai/master in masters)
|
||||
if(masters[master] && speaker != master)
|
||||
master.relay_speech(message, speaker, message_langs, raw_message, radio_freq, spans)
|
||||
+
|
||||
+ for(var/I in holo_calls)
|
||||
+ var/datum/holocall/HC = I
|
||||
+ if(HC.connected_holopad == src && speaker != HC.hologram)
|
||||
+ HC.user.Hear(message, speaker, message_langs, raw_message, radio_freq, spans)
|
||||
+
|
||||
+ if(outgoing_call && speaker == outgoing_call.user)
|
||||
+ outgoing_call.hologram.say(raw_message)
|
||||
+
|
||||
+/obj/machinery/holopad/proc/SetLightsAndPower()
|
||||
+ var/total_users = masters.len + LAZYLEN(holo_calls)
|
||||
+ use_power = HOLOPAD_PASSIVE_POWER_USAGE + HOLOGRAM_POWER_USAGE * total_users
|
||||
+ if(total_users)
|
||||
+ set_light(2)
|
||||
+ icon_state = "holopad1"
|
||||
+ else
|
||||
+ set_light(0)
|
||||
+ icon_state = "holopad0"
|
||||
|
||||
-/obj/machinery/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
|
||||
- var/obj/effect/overlay/holo_pad_hologram/h = new(T)//Spawn a blank effect at the location.
|
||||
- h.icon = A.holo_icon
|
||||
- h.mouse_opacity = 0//So you can't click on it.
|
||||
- h.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
|
||||
- h.anchored = 1//So space wind cannot drag it.
|
||||
- h.name = "[A.name] (Hologram)"//If someone decides to right click.
|
||||
- h.set_light(2) //hologram lighting
|
||||
- set_holo(A, h)
|
||||
- return TRUE
|
||||
-
|
||||
-/obj/machinery/holopad/proc/set_holo(mob/living/silicon/ai/A, var/obj/effect/overlay/holo_pad_hologram/h)
|
||||
- masters[A] = h
|
||||
- set_light(2) // pad lighting
|
||||
- icon_state = "holopad1"
|
||||
- A.current = src
|
||||
- use_power += HOLOGRAM_POWER_USAGE
|
||||
+/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h)
|
||||
+ masters[user] = h
|
||||
+ var/mob/living/silicon/ai/AI = user
|
||||
+ if(istype(AI))
|
||||
+ AI.current = src
|
||||
+ SetLightsAndPower()
|
||||
return TRUE
|
||||
|
||||
-/obj/machinery/holopad/proc/clear_holo(mob/living/silicon/ai/user)
|
||||
+/obj/machinery/holopad/proc/clear_holo(mob/living/user)
|
||||
qdel(masters[user]) // Get rid of user's hologram
|
||||
unset_holo(user)
|
||||
return TRUE
|
||||
|
||||
-/obj/machinery/holopad/proc/unset_holo(mob/living/silicon/ai/user)
|
||||
- if(user.current == src)
|
||||
- user.current = null
|
||||
+/obj/machinery/holopad/proc/unset_holo(mob/living/user)
|
||||
+ var/mob/living/silicon/ai/AI = user
|
||||
+ if(istype(AI) && AI.current == src)
|
||||
+ AI.current = null
|
||||
masters -= user // Discard AI from the list of those who use holopad
|
||||
- use_power = max(HOLOPAD_PASSIVE_POWER_USAGE, use_power - HOLOGRAM_POWER_USAGE)//Reduce power usage
|
||||
- if (!masters.len) // If no users left
|
||||
- set_light(0) // pad lighting (hologram lighting will be handled automatically since its owner was deleted)
|
||||
- icon_state = "holopad0"
|
||||
- use_power = HOLOPAD_PASSIVE_POWER_USAGE
|
||||
+ SetLightsAndPower()
|
||||
return TRUE
|
||||
|
||||
-/obj/machinery/holopad/proc/move_hologram(mob/living/silicon/ai/user)
|
||||
+/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
|
||||
if(masters[user])
|
||||
- step_to(masters[user], user.eyeobj)
|
||||
var/obj/effect/overlay/holo_pad_hologram/H = masters[user]
|
||||
- H.loc = get_turf(user.eyeobj)
|
||||
+ step_to(H, new_turf)
|
||||
+ H.loc = new_turf
|
||||
+ var/area/holo_area = get_area(src)
|
||||
+ var/area/eye_area = new_turf.loc
|
||||
+
|
||||
+ if(!(eye_area in holo_area.related))
|
||||
+ clear_holo(user)
|
||||
return TRUE
|
||||
|
||||
+/obj/effect/overlay/holo_pad_hologram
|
||||
+ var/mob/living/Impersonation
|
||||
+ var/datum/holocall/HC
|
||||
+
|
||||
+/obj/effect/overlay/holo_pad_hologram/Destroy()
|
||||
+ Impersonation = null
|
||||
+ if(HC)
|
||||
+ HC.Disconnect(HC.calling_holopad)
|
||||
+ return ..()
|
||||
+
|
||||
/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
|
||||
+/obj/effect/overlay/holo_pad_hologram/examine(mob/user)
|
||||
+ if(Impersonation)
|
||||
+ return Impersonation.examine(user)
|
||||
+ return ..()
|
||||
+
|
||||
/obj/item/weapon/circuitboard/machine/holopad
|
||||
name = "AI Holopad (Machine Board)"
|
||||
build_path = /obj/machinery/holopad
|
||||
origin_tech = "programming=1"
|
||||
req_components = list(/obj/item/weapon/stock_parts/capacitor = 1)
|
||||
|
||||
-#undef RANGE_BASED
|
||||
-#undef AREA_BASED
|
||||
#undef HOLOPAD_PASSIVE_POWER_USAGE
|
||||
-#undef HOLOGRAM_POWER_USAGE
|
||||
+#undef HOLOGRAM_POWER_USAGE
|
||||
\ No newline at end of file
|
||||
Reference in New Issue
Block a user