diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 3d3eb5c419..d73f7c23b4 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -41,7 +41,8 @@ Possible to do for anyone motivated enough: max_integrity = 300 armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 0) circuit = /obj/item/circuitboard/machine/holopad - var/list/masters = list()//List of living mobs that use the holopad + var/list/masters //List of living mobs that use the holopad + var/list/holorays //Holoray-mob link. 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 = "" @@ -56,6 +57,7 @@ Possible to do for anyone motivated enough: var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging var/static/list/holopads = list() + var/obj/effect/overlay/holoray/ray /obj/machinery/holopad/Initialize() . = ..() @@ -289,33 +291,34 @@ Possible to do for anyone motivated enough: This may change in the future but for now will suffice.*/ if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already. user.eyeobj.setLoc(get_turf(src)) - else if(!masters[user])//If there is no hologram, possibly make one. + else if(!LAZYLEN(masters) || !masters[user])//If there is no hologram, possibly make one. activate_holo(user) else//If there is a hologram, remove it. clear_holo(user) /obj/machinery/holopad/process() - for(var/I in masters) - var/mob/living/master = I - var/mob/living/silicon/ai/AI = master - if(!istype(AI)) - AI = null + if(LAZYLEN(masters)) + 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) + 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 - continue - clear_holo(master)//If not, we want to get rid of the hologram. + 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() @@ -360,6 +363,7 @@ Possible to do for anyone motivated enough: Hologram.anchored = TRUE//So space wind cannot drag it. Hologram.name = "[user.name] (Hologram)"//If someone decides to right click. Hologram.set_light(2) //hologram lighting + move_hologram() set_holo(user, Hologram) visible_message("A holographic image of [user] flickers to life before your eyes!") @@ -371,7 +375,7 @@ Possible to do for anyone motivated enough: /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ /obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) - if(speaker && masters.len && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. + if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. for(var/mob/living/silicon/ai/master in masters) if(masters[master] && speaker != master) master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) @@ -388,7 +392,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ record_message(speaker,raw_message,message_language) /obj/machinery/holopad/proc/SetLightsAndPower() - var/total_users = masters.len + LAZYLEN(holo_calls) + var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls) use_power = total_users > 0 ? ACTIVE_POWER_USE : IDLE_POWER_USE active_power_usage = HOLOPAD_PASSIVE_POWER_USAGE + (HOLOGRAM_POWER_USAGE * total_users) if(total_users || replay_mode) @@ -398,22 +402,25 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ update_icon() /obj/machinery/holopad/update_icon() - var/total_users = masters.len + LAZYLEN(holo_calls) + var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls) if(total_users || replay_mode) icon_state = "holopad1" else icon_state = "holopad0" /obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h) - masters[user] = h + LAZYSET(masters, user, h) + LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc)) var/mob/living/silicon/ai/AI = user if(istype(AI)) AI.current = src SetLightsAndPower() + update_holoray(user, get_turf(loc)) return TRUE /obj/machinery/holopad/proc/clear_holo(mob/living/user) qdel(masters[user]) // Get rid of user's hologram + qdel(holorays[user]) unset_holo(user) return TRUE @@ -421,22 +428,47 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ 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 + LAZYREMOVE(masters, user) // Discard AI from the list of those who use holopad + LAZYREMOVE(holorays, user) SetLightsAndPower() return TRUE /obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf) - if(masters[user]) - var/obj/effect/overlay/holo_pad_hologram/H = masters[user] - step_to(H, new_turf) - H.forceMove(new_turf) + if(LAZYLEN(masters) && masters[user]) var/area/holo_area = get_area(src) - var/area/eye_area = new_turf.loc - - if(!(eye_area in holo_area.related)) + if(new_turf.loc in holo_area.related) + var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] + step_to(holo, new_turf) + holo.forceMove(new_turf) + update_holoray(user, new_turf) + else clear_holo(user) return TRUE + +/obj/machinery/holopad/proc/update_holoray(mob/living/user, turf/new_turf) + var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] + var/obj/effect/overlay/holoray/ray = holorays[user] + var/disty = holo.y - ray.y + var/distx = holo.x - ray.x + var/newangle + if(!disty) + if(distx >= 0) + newangle = 90 + else + newangle = 270 + else + newangle = arctan(distx/disty) + if(disty < 0) + newangle += 180 + else if(distx < 0) + newangle += 360 + var/matrix/M = matrix() + if (get_dist(get_turf(holo),new_turf) <= 1) + animate(ray, transform = turn(M.Scale(1,sqrt(distx*distx+disty*disty)),newangle),time = 1) + else + ray.transform = turn(M.Scale(1,sqrt(distx*distx+disty*disty)),newangle) + // RECORDED MESSAGES /obj/machinery/holopad/proc/setup_replay_holo(datum/holorecord/record) @@ -522,7 +554,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ if(!replay_mode) return if(disk.record.entries.len < entry_number) - if (loop_mode) + if (loop_mode) entry_number = 1 else replay_stop() @@ -574,12 +606,24 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ return ..() /obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0) - return 1 + return TRUE /obj/effect/overlay/holo_pad_hologram/examine(mob/user) if(Impersonation) return Impersonation.examine(user) return ..() +/obj/effect/overlay/holoray + name = "holoray" + icon = 'icons/effects/96x96.dmi' + icon_state = "holoray" + layer = FLY_LAYER + density = FALSE + anchored = TRUE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + pixel_x = -32 + pixel_y = -32 + alpha = 100 + #undef HOLOPAD_PASSIVE_POWER_USAGE -#undef HOLOGRAM_POWER_USAGE +#undef HOLOGRAM_POWER_USAGE \ No newline at end of file diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 70e097c9f4..7c227e7744 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ