mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
This adds a system for picture-in-picture UI windows using vis_contents. Essentially, it allows you to make UI windows that show an area of turfs. It also refactors how cameranet visibility works. Currently, this is implemented on AIs. They gain two new UI buttons - "Enter Multicam Mode", and "Create Multicam". When they go into Multicam Mode, they see a background of animated binary numbers, and they are allowed to create an infinite amount of these picture in picture windows, which subsequently creates an AI Eye for each one. They are able to control each AI eye individually, by first clicking on the PIP window to select it as "active" and then using the normal arrow key controls. The PIP windows can be freely resized and moved around the area. You can control everything inside these PIP windows EXACTLY the same as you can using a traditional AI Eye, as demonstrated below. For admins, there is a config option to disable PIP entirely - simply set `var/multicam_allowed = TRUE` to FALSE if you wish to disable it from being used. (Please be reasonable.) <3 You can see an example of how this works here:  AI Multicam functionality. Do note that if the lightbulb in the AI core is busted, the multicam room is dark(er) than it would be, but you can still see your camera windows just fine. (I'll probably fix this later.) It only affects the "matrix" backdrop, the PIP windows are still fine. This has been runtime-tested with the latest `master` revision and produces 0 runtimes, and has no noticeable impact on server CPU usage. Chompstation port is here! Port of https://github.com/VOREStation/VOREStation/pull/7752, YW port not incoming atm as they can fetch from upstream and frankly dog has done enuf ports for now x.x
186 lines
4.4 KiB
Plaintext
186 lines
4.4 KiB
Plaintext
/*
|
|
AI ClickOn()
|
|
|
|
Note currently ai restrained() returns 0 in all cases,
|
|
therefore restrained code has been removed
|
|
|
|
The AI can double click to move the camera (this was already true but is cleaner),
|
|
or double click a mob to track them.
|
|
|
|
Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner.
|
|
*/
|
|
/mob/living/silicon/ai/DblClickOn(var/atom/A, params)
|
|
if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
|
|
build_click(src, client.buildmode, params, A)
|
|
return
|
|
|
|
if(control_disabled || stat) return
|
|
|
|
if(ismob(A))
|
|
ai_actual_track(A)
|
|
else
|
|
A.move_camera_by_click()
|
|
|
|
|
|
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
|
|
if(!checkClickCooldown())
|
|
return
|
|
|
|
setClickCooldown(1)
|
|
|
|
if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
|
|
build_click(src, client.buildmode, params, A)
|
|
return
|
|
|
|
if(multicam_on)
|
|
var/turf/T = get_turf(A)
|
|
if(T)
|
|
for(var/obj/screen/movable/pic_in_pic/ai/P in T.vis_locs)
|
|
if(P.ai == src)
|
|
P.Click(params)
|
|
break
|
|
|
|
if(stat)
|
|
return
|
|
|
|
if(control_disabled)
|
|
return
|
|
|
|
var/list/modifiers = params2list(params)
|
|
if(modifiers["shift"] && modifiers["ctrl"])
|
|
CtrlShiftClickOn(A)
|
|
return
|
|
if(modifiers["middle"])
|
|
MiddleClickOn(A)
|
|
return
|
|
if(modifiers["shift"])
|
|
ShiftClickOn(A)
|
|
return
|
|
if(modifiers["alt"])
|
|
AltClickOn(A)
|
|
return
|
|
if(modifiers["ctrl"])
|
|
CtrlClickOn(A)
|
|
return
|
|
|
|
if(aiCamera.in_camera_mode)
|
|
aiCamera.camera_mode_off()
|
|
aiCamera.captureimage(A, usr)
|
|
return
|
|
|
|
A.add_hiddenprint(src)
|
|
A.attack_ai(src)
|
|
|
|
/*
|
|
AI has no need for the UnarmedAttack() and RangedAttack() procs,
|
|
because the AI code is not generic; attack_ai() is used instead.
|
|
The below is only really for safety, or you can alter the way
|
|
it functions and re-insert it above.
|
|
*/
|
|
/mob/living/silicon/ai/UnarmedAttack(atom/A)
|
|
A.attack_ai(src)
|
|
/mob/living/silicon/ai/RangedAttack(atom/A)
|
|
A.attack_ai(src)
|
|
|
|
/atom/proc/attack_ai(mob/user as mob)
|
|
return
|
|
|
|
/*
|
|
Since the AI handles shift, ctrl, and alt-click differently
|
|
than anything else in the game, atoms have separate procs
|
|
for AI shift, ctrl, and alt clicking.
|
|
*/
|
|
|
|
/mob/living/silicon/ai/ShiftClickOn(var/atom/A)
|
|
if(!control_disabled && A.AIShiftClick(src))
|
|
return
|
|
..()
|
|
|
|
/mob/living/silicon/ai/CtrlClickOn(var/atom/A)
|
|
if(!control_disabled && A.AICtrlClick(src))
|
|
return
|
|
..()
|
|
|
|
/mob/living/silicon/ai/AltClickOn(var/atom/A)
|
|
if(!control_disabled && A.AIAltClick(src))
|
|
return
|
|
..()
|
|
|
|
/mob/living/silicon/ai/MiddleClickOn(var/atom/A)
|
|
if(!control_disabled && A.AIMiddleClick(src))
|
|
return
|
|
..()
|
|
|
|
/*
|
|
The following criminally helpful code is just the previous code cleaned up;
|
|
I have no idea why it was in atoms.dm instead of respective files.
|
|
*/
|
|
|
|
/atom/proc/AICtrlShiftClick()
|
|
return
|
|
|
|
/atom/proc/AIShiftClick()
|
|
return
|
|
|
|
/obj/machinery/door/airlock/AIShiftClick() // Opens and closes doors!
|
|
if(density)
|
|
Topic(src, list("command"="open", "activate" = "1"))
|
|
else
|
|
Topic(src, list("command"="open", "activate" = "0"))
|
|
return 1
|
|
|
|
/atom/proc/AICtrlClick()
|
|
return
|
|
|
|
/obj/machinery/door/airlock/AICtrlClick() // Bolts doors
|
|
if(locked)
|
|
Topic(src, list("command"="bolts", "activate" = "0"))
|
|
else
|
|
Topic(src, list("command"="bolts", "activate" = "1"))
|
|
return 1
|
|
|
|
/obj/machinery/power/apc/AICtrlClick() // turns off/on APCs.
|
|
Topic(src, list("breaker"="1"))
|
|
return 1
|
|
|
|
/obj/machinery/turretid/AICtrlClick() //turns off/on Turrets
|
|
Topic(src, list("command"="enable", "value"="[!enabled]"))
|
|
return 1
|
|
|
|
/atom/proc/AIAltClick(var/atom/A)
|
|
return AltClick(A)
|
|
|
|
/obj/machinery/door/airlock/AIAltClick() // Electrifies doors.
|
|
if(!electrified_until)
|
|
// permanent shock
|
|
Topic(src, list("command"="electrify_permanently", "activate" = "1"))
|
|
else
|
|
// disable/6 is not in Topic; disable/5 disables both temporary and permanent shock
|
|
Topic(src, list("command"="electrify_permanently", "activate" = "0"))
|
|
return 1
|
|
|
|
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets
|
|
Topic(src, list("command"="lethal", "value"="[!lethal]"))
|
|
return 1
|
|
|
|
/atom/proc/AIMiddleClick(var/mob/living/silicon/user)
|
|
return 0
|
|
|
|
/obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights.
|
|
|
|
if(..())
|
|
return
|
|
|
|
if(!src.lights)
|
|
Topic(src, list("command"="lights", "activate" = "1"))
|
|
else
|
|
Topic(src, list("command"="lights", "activate" = "0"))
|
|
return 1
|
|
|
|
//
|
|
// Override AdjacentQuick for AltClicking
|
|
//
|
|
|
|
/mob/living/silicon/ai/TurfAdjacent(var/turf/T)
|
|
return (cameranet && cameranet.checkTurfVis(T))
|