[{"data":1,"prerenderedAt":2140},["ShallowReactive",2],{"/docs/jobs/ambulancejob/features/custom-medications":3,"/docs/jobs/ambulancejob/features/custom-medications-surround":2128,"/docs/jobs/ambulancejob/features/custom-medications-implemented-suggestions":2139},{"id":4,"title":5,"body":6,"description":2119,"extension":2120,"head":2121,"implementedSuggestions":2121,"meta":2122,"navigation":1336,"path":2123,"schemaOrg":2121,"seo":2124,"sitemap":2125,"stem":2126,"__hash__":2127},"docs/1.docs/0.jobs/0.ambulancejob/3.features/3.custom-medications.md","Custom Medications",{"type":7,"value":8,"toc":2096},"minimark",[9,14,49,84,87,95,176,178,182,559,562,584,587,627,630,632,640,654,661,664,697,700,719,722,771,778,806,812,815,831,844,854,890,893,914,916,920,924,1111,1118,1122,1607,1614,1621,1847,1854,1856,1863,1873,1899,1910,1912,1916,2014,2021,2023,2027,2092],[10,11,13],"h2",{"id":12},"what-it-is","What it is",[15,16,17,21,22,25,26,29,30,33,34,37,38,41,42,41,45,48],"p",{},[18,19,20],"code",{},"Config.CustomMedications"," is a third sibling table to ",[18,23,24],{},"Config.Medications"," and ",[18,27,28],{},"Config.HealingItems",". Each entry registers a usable inventory item that, when used, plays an animation on the patient, applies declarative vitals effects, and (optionally) runs paired ",[18,31,32],{},"onUseClient"," / ",[18,35,36],{},"onUseServer"," callbacks (and ",[18,39,40],{},"onTick","/",[18,43,44],{},"onFinish",[18,46,47],{},"onCancel"," variants) for full control.",[15,50,51,52,55,56,55,59,55,62,55,65,55,68,55,71,55,74,55,77,80,81,83],{},"Declarative fields (",[18,53,54],{},"pain",", ",[18,57,58],{},"bleeding",[18,60,61],{},"heal",[18,63,64],{},"effect",[18,66,67],{},"requiresOpenWound",[18,69,70],{},"stopBleeding",[18,72,73],{},"pauseBleedingSeconds",[18,75,76],{},"duration",[18,78,79],{},"effectDurationSeconds",") are forwarded to the same engine that powers ",[18,82,24],{},", so vitals stay synchronised without duplicated logic.",[85,86],"hr",{},[10,88,90,91,94],{"id":89},"the-three-type-values","The three ",[18,92,93],{},"type"," values",[96,97,98,111],"table",{},[99,100,101],"thead",{},[102,103,104,108],"tr",{},[105,106,107],"th",{},"Type",[105,109,110],{},"Behaviour",[112,113,114,134,166],"tbody",{},[102,115,116,122],{},[117,118,119],"td",{},[18,120,121],{},"\"medication\"",[117,123,124,125,128,129,33,131,133],{},"One-shot consumable. Plays anim for ",[18,126,127],{},"time"," ms, runs ",[18,130,32],{},[18,132,36],{}," once, applies declarative effects on finish.",[102,135,136,141],{},[117,137,138],{},[18,139,140],{},"\"infusion\"",[117,142,143,144,146,147,150,151,33,154,157,158,161,162,165],{},"Setup phase (",[18,145,127],{}," ms) then a tick loop running for ",[18,148,149],{},"injectingTime"," ms. ",[18,152,153],{},"onTickClient",[18,155,156],{},"onTickServer"," fire every ",[18,159,160],{},"tickIntervalMs"," (default ",[18,163,164],{},"1000","). Declarative effects apply once on finish.",[102,167,168,173],{},[117,169,170],{},[18,171,172],{},"\"custom\"",[117,174,175],{},"No built-in effects. Pure callback hook. Use this for anything that doesn't fit the declarative model — defibrillators, vehicle interactions, custom revives.",[85,177],{},[10,179,181],{"id":180},"field-reference","Field reference",[96,183,184,199],{},[99,185,186],{},[102,187,188,191,193,196],{},[105,189,190],{},"Field",[105,192,107],{},[105,194,195],{},"Required",[105,197,198],{},"Notes",[112,200,201,223,237,251,267,290,307,321,335,354,367,384,397,410,423,439,452,465,478,494,510,525,542],{},[102,202,203,207,210,213],{},[117,204,205],{},[18,206,93],{},[117,208,209],{},"string",[117,211,212],{},"yes",[117,214,215,55,217,219,220,222],{},[18,216,121],{},[18,218,140],{},", or ",[18,221,172],{},".",[102,224,225,229,232,234],{},[117,226,227],{},[18,228,127],{},[117,230,231],{},"number (ms)",[117,233,212],{},[117,235,236],{},"Duration of the progress phase. For infusions this is the setup phase before the tick loop starts.",[102,238,239,243,245,248],{},[117,240,241],{},[18,242,149],{},[117,244,231],{},[117,246,247],{},"infusion",[117,249,250],{},"How long the tick loop runs.",[102,252,253,257,259,262],{},[117,254,255],{},[18,256,160],{},[117,258,231],{},[117,260,261],{},"no",[117,263,264,265,222],{},"Tick cadence. Default ",[18,266,164],{},[102,268,269,274,277,279],{},[117,270,271],{},[18,272,273],{},"removeItem",[117,275,276],{},"boolean",[117,278,261],{},[117,280,281,282,285,286,289],{},"Remove the item on finish. Default ",[18,283,284],{},"true",". Set ",[18,287,288],{},"false"," for reusable items like a defibrillator.",[102,291,292,297,302,304],{},[117,293,294],{},[18,295,296],{},"anim",[117,298,299],{},[18,300,301],{},"{ dict, name }",[117,303,261],{},[117,305,306],{},"Played on the user's ped while the run is active.",[102,308,309,314,316,318],{},[117,310,311],{},[18,312,313],{},"lang",[117,315,209],{},[117,317,261],{},[117,319,320],{},"Progress label shown while the run is active.",[102,322,323,328,330,332],{},[117,324,325],{},[18,326,327],{},"langUsed",[117,329,209],{},[117,331,261],{},[117,333,334],{},"Success notification text shown on finish.",[102,336,337,342,345,347],{},[117,338,339],{},[18,340,341],{},"volume",[117,343,344],{},"number",[117,346,261],{},[117,348,349,350,353],{},"Informational. Surfaced on ",[18,351,352],{},"self.volume"," for callback use.",[102,355,356,360,362,364],{},[117,357,358],{},[18,359,54],{},[117,361,344],{},[117,363,261],{},[117,365,366],{},"Negative reduces pain, positive raises it. Routed through the existing pain-modifier system.",[102,368,369,373,375,377],{},[117,370,371],{},[18,372,58],{},[117,374,344],{},[117,376,261],{},[117,378,379,380,383],{},"Class delta (",[18,381,382],{},"-2"," reduces bleeding by 2 classes on the matched wound).",[102,385,386,390,392,394],{},[117,387,388],{},[18,389,61],{},[117,391,344],{},[117,393,261],{},[117,395,396],{},"HP to restore on finish.",[102,398,399,403,405,407],{},[117,400,401],{},[18,402,64],{},[117,404,209],{},[117,406,261],{},[117,408,409],{},"Screen effect name.",[102,411,412,416,418,420],{},[117,413,414],{},[18,415,79],{},[117,417,344],{},[117,419,261],{},[117,421,422],{},"Effect duration in seconds.",[102,424,425,429,431,433],{},[117,426,427],{},[18,428,67],{},[117,430,276],{},[117,432,261],{},[117,434,435,436,438],{},"If ",[18,437,284],{},", run only starts when the target has an active open wound.",[102,440,441,445,447,449],{},[117,442,443],{},[18,444,70],{},[117,446,276],{},[117,448,261],{},[117,450,451],{},"Permanently stops bleeding on every open wound.",[102,453,454,458,460,462],{},[117,455,456],{},[18,457,73],{},[117,459,344],{},[117,461,261],{},[117,463,464],{},"Pauses bleeding on every open wound for N seconds.",[102,466,467,471,473,475],{},[117,468,469],{},[18,470,76],{},[117,472,344],{},[117,474,261],{},[117,476,477],{},"Optional pain-modifier expiry in seconds.",[102,479,480,485,487,489],{},[117,481,482],{},[18,483,484],{},"access.lockAccess",[117,486,276],{},[117,488,261],{},[117,490,491,493],{},[18,492,284],{}," -> only on-duty medics can use the item. Inventory item use still targets the user themselves; treatment-menu use can pass an explicit patient target.",[102,495,496,502,505,507],{},[117,497,498,55,500],{},[18,499,32],{},[18,501,36],{},[117,503,504],{},"function",[117,506,261],{},[117,508,509],{},"Run once at start, on each side.",[102,511,512,518,520,522],{},[117,513,514,55,516],{},[18,515,153],{},[18,517,156],{},[117,519,504],{},[117,521,261],{},[117,523,524],{},"Infusions only. Run on each tick on each side.",[102,526,527,535,537,539],{},[117,528,529,55,532],{},[18,530,531],{},"onFinishClient",[18,533,534],{},"onFinishServer",[117,536,504],{},[117,538,261],{},[117,540,541],{},"Run once on completion on each side.",[102,543,544,552,554,556],{},[117,545,546,55,549],{},[18,547,548],{},"onCancelClient",[18,550,551],{},"onCancelServer",[117,553,504],{},[117,555,261],{},[117,557,558],{},"Run once on interruption on each side.",[15,560,561],{},"Legacy aliases (normalised at load):",[563,564,565,575],"ul",{},[566,567,568,571,572],"li",{},[18,569,570],{},"painReduce = N"," -> ",[18,573,574],{},"pain = -N",[566,576,577,580,581],{},[18,578,579],{},"lockAccess = true/false"," (top-level) -> ",[18,582,583],{},"access.lockAccess = ...",[15,585,586],{},"A single top-level knob applies to every entry:",[588,589,595],"pre",{"className":590,"code":591,"filename":592,"language":593,"meta":594,"style":594},"language-lua shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Config.CustomMedications._maxTargetDistance = 3.0  -- metres\n","config.lua","lua","",[18,596,597],{"__ignoreMap":594},[598,599,602,606,610,612,615,619,623],"span",{"class":600,"line":601},"line",1,[598,603,605],{"class":604},"sTEyZ","Config.",[598,607,609],{"class":608},"sBMFI","CustomMedications",[598,611,222],{"class":604},[598,613,614],{"class":608},"_maxTargetDistance",[598,616,618],{"class":617},"sMK4o"," =",[598,620,622],{"class":621},"sbssI"," 3.0",[598,624,626],{"class":625},"sHwdD","  -- metres\n",[15,628,629],{},"This is the range threshold that auto-cancels an in-progress cross-player infusion started through the treatment menu if the medic walks away.",[85,631],{},[10,633,635,636,639],{"id":634},"the-self-helper","The ",[18,637,638],{},"self"," helper",[15,641,642,643,645,646,653],{},"Each callback receives a ",[18,644,638],{}," table sized to its environment. ",[647,648,649,650,652],"strong",{},"Client-side ",[18,651,638],{}," cannot mutate vitals"," — only the server-side helper can. This makes the security model trivial: the client can't ask the server to mutate state through the helper.",[655,656,658,659],"h3",{"id":657},"client-self","Client ",[18,660,638],{},[15,662,663],{},"Static state (read-only):",[563,665,666,685,691],{},[566,667,668,55,671,55,674,55,676,55,679,55,682],{},[18,669,670],{},"self.itemName",[18,672,673],{},"self.type",[18,675,352],{},[18,677,678],{},"self.time",[18,680,681],{},"self.injectingTime",[18,683,684],{},"self.elapsed",[566,686,687,690],{},[18,688,689],{},"self.source"," — serverId of the user",[566,692,693,696],{},[18,694,695],{},"self.target"," — serverId resolved at start (explicit treatment-menu target, otherwise self)",[15,698,699],{},"Vital mirrors (refreshed every tick from a piggybacked snapshot — no extra round-trip):",[563,701,702],{},[566,703,704,55,707,55,710,55,713,55,716],{},[18,705,706],{},"self.blood",[18,708,709],{},"self.pain",[18,711,712],{},"self.heartRate",[18,714,715],{},"self.bloodPressure",[18,717,718],{},"self.oxygenLevel",[15,720,721],{},"Local helpers (run on the user's machine):",[563,723,724,732,737,742,752,761],{},[566,725,726,33,729],{},[18,727,728],{},"self:fadeOut(ms)",[18,730,731],{},"self:fadeIn(ms)",[566,733,734],{},[18,735,736],{},"self:ragdoll(ms)",[566,738,739],{},[18,740,741],{},"self:playSound(soundSet, soundName)",[566,743,744,747,748,751],{},[18,745,746],{},"self:playSoundAt(url, volume)"," — wraps ",[18,749,750],{},"exports.xsound:PlayUrlPos"," at the user's coords",[566,753,754,757,758],{},[18,755,756],{},"self:coords()"," — returns the user's ",[18,759,760],{},"vector3",[566,762,763,766,767,770],{},[18,764,765],{},"self:cancel(reason)"," — abort cleanly (no ",[18,768,769],{},"onFinish*",", no item consumption)",[15,772,773,774,777],{},"Targeting helpers (return a serverId or ",[18,775,776],{},"nil","):",[563,779,780,800],{},[566,781,782,785,786,161,789,792,793,796,797,222],{},[18,783,784],{},"self:nearbyPlayer(opts)"," — closest player ped within ",[18,787,788],{},"opts.maxDistance",[18,790,791],{},"3.0","); ",[18,794,795],{},"opts.requireFacing = true"," for forward-cone filter; ",[18,798,799],{},"opts.includeSelf = false",[566,801,802,805],{},[18,803,804],{},"self:aimingAt()"," — the ped the user is currently free-aiming at.",[655,807,809,810],{"id":808},"server-self","Server ",[18,811,638],{},[15,813,814],{},"Same static state, plus:",[563,816,817,825],{},[566,818,819,822,823],{},[18,820,821],{},"self.patient"," — the patient record for ",[18,824,695],{},[566,826,827,830],{},[18,828,829],{},"self:patientFor(serverId)"," — patient record for any other player",[15,832,833,834,55,837,55,840,843],{},"Direct read of the patient record is fine: ",[18,835,836],{},"self.patient.conditions.bloodVolume",[18,838,839],{},"self.patient.conditions.pain",[18,841,842],{},"self.patient.vitals.heart_rate",", etc.",[15,845,846,847,850,851,853],{},"State mutators (no event hop, direct call into the medication engine — ",[18,848,849],{},"target"," defaults to ",[18,852,695],{}," when omitted):",[563,855,856,864,873,878,884],{},[566,857,858,33,861],{},[18,859,860],{},"self:reducePain(amount, target?)",[18,862,863],{},"self:addPain(amount, target?)",[566,865,866,869,870],{},[18,867,868],{},"self:addBlood(amount, target?)"," — clamped to ",[18,871,872],{},"Config.BloodSystem.maxVolume",[566,874,875],{},[18,876,877],{},"self:setBleeding(zone, classDelta, target?)",[566,879,880,883],{},[18,881,882],{},"self:heal(amount, target?)"," — fires the existing heal event on the target",[566,885,886,889],{},[18,887,888],{},"self:revive(target?)"," — runs the standard revive flow",[15,891,892],{},"Helpers:",[563,894,895,904,909],{},[566,896,897,900,901],{},[18,898,899],{},"self:isMedic(serverId?)"," — uses ",[18,902,903],{},"Sky_Jobs.PlayerCache",[566,905,906],{},[18,907,908],{},"self:distance(target?)",[566,910,911,913],{},[18,912,765],{}," — server-driven cancel (e.g. when the target walks out of range mid-infusion)",[85,915],{},[10,917,919],{"id":918},"worked-examples","Worked examples",[655,921,923],{"id":922},"one-shot-medication","One-shot medication",[588,925,927],{"className":590,"code":926,"filename":592,"language":593,"meta":594,"style":594},"vomex = {\n    type        = \"medication\",\n    time        = 2000,\n    removeItem  = true,\n    anim        = {\n        dict = \"anim@heists@narcotics@funding@gang_idle\",\n        name = \"gang_chatting_idle01\"\n    },\n    lang        = \"Nehme Vomex...\",\n    langUsed    = \"Vomex eingenommen\",\n    pain        = -2,\n    access      = { lockAccess = false }\n},\n",[18,928,929,940,961,974,987,997,1014,1030,1036,1053,1070,1086,1105],{"__ignoreMap":594},[598,930,931,934,937],{"class":600,"line":601},[598,932,933],{"class":604},"vomex ",[598,935,936],{"class":617},"=",[598,938,939],{"class":604}," {\n",[598,941,943,946,948,951,955,958],{"class":600,"line":942},2,[598,944,945],{"class":604},"    type        ",[598,947,936],{"class":617},[598,949,950],{"class":617}," \"",[598,952,954],{"class":953},"sfazB","medication",[598,956,957],{"class":617},"\"",[598,959,960],{"class":604},",\n",[598,962,964,967,969,972],{"class":600,"line":963},3,[598,965,966],{"class":604},"    time        ",[598,968,936],{"class":617},[598,970,971],{"class":621}," 2000",[598,973,960],{"class":604},[598,975,977,980,982,985],{"class":600,"line":976},4,[598,978,979],{"class":604},"    removeItem  ",[598,981,936],{"class":617},[598,983,984],{"class":617}," true",[598,986,960],{"class":604},[598,988,990,993,995],{"class":600,"line":989},5,[598,991,992],{"class":604},"    anim        ",[598,994,936],{"class":617},[598,996,939],{"class":604},[598,998,1000,1003,1005,1007,1010,1012],{"class":600,"line":999},6,[598,1001,1002],{"class":604},"        dict ",[598,1004,936],{"class":617},[598,1006,950],{"class":617},[598,1008,1009],{"class":953},"anim@heists@narcotics@funding@gang_idle",[598,1011,957],{"class":617},[598,1013,960],{"class":604},[598,1015,1017,1020,1022,1024,1027],{"class":600,"line":1016},7,[598,1018,1019],{"class":604},"        name ",[598,1021,936],{"class":617},[598,1023,950],{"class":617},[598,1025,1026],{"class":953},"gang_chatting_idle01",[598,1028,1029],{"class":617},"\"\n",[598,1031,1033],{"class":600,"line":1032},8,[598,1034,1035],{"class":604},"    },\n",[598,1037,1039,1042,1044,1046,1049,1051],{"class":600,"line":1038},9,[598,1040,1041],{"class":604},"    lang        ",[598,1043,936],{"class":617},[598,1045,950],{"class":617},[598,1047,1048],{"class":953},"Nehme Vomex...",[598,1050,957],{"class":617},[598,1052,960],{"class":604},[598,1054,1056,1059,1061,1063,1066,1068],{"class":600,"line":1055},10,[598,1057,1058],{"class":604},"    langUsed    ",[598,1060,936],{"class":617},[598,1062,950],{"class":617},[598,1064,1065],{"class":953},"Vomex eingenommen",[598,1067,957],{"class":617},[598,1069,960],{"class":604},[598,1071,1073,1076,1078,1081,1084],{"class":600,"line":1072},11,[598,1074,1075],{"class":604},"    pain        ",[598,1077,936],{"class":617},[598,1079,1080],{"class":617}," -",[598,1082,1083],{"class":621},"2",[598,1085,960],{"class":604},[598,1087,1089,1092,1094,1097,1099,1102],{"class":600,"line":1088},12,[598,1090,1091],{"class":604},"    access      ",[598,1093,936],{"class":617},[598,1095,1096],{"class":604}," { lockAccess ",[598,1098,936],{"class":617},[598,1100,1101],{"class":617}," false",[598,1103,1104],{"class":604}," }\n",[598,1106,1108],{"class":600,"line":1107},13,[598,1109,1110],{"class":604},"},\n",[15,1112,1113,1114,1117],{},"Player uses ",[18,1115,1116],{},"vomex"," from inventory -> 2-second progress -> item removed -> pain drops by 2. No callbacks needed.",[655,1119,1121],{"id":1120},"sustained-infusion","Sustained infusion",[588,1123,1125],{"className":590,"code":1124,"filename":592,"language":593,"meta":594,"style":594},"fentanyl = {\n    type           = \"infusion\",\n    time           = 3000,\n    injectingTime  = 5 * 60 * 1000,\n    tickIntervalMs = 1000,\n    removeItem     = true,\n    volume         = 20,\n    anim           = { dict = \"anim@heists@narcotics@funding@gang_idle\",\n                       name = \"gang_chatting_idle01\" },\n    lang           = \"Verabreiche Fentanyl...\",\n    langUsed       = \"Fentanyl verabreicht\",\n    pain           = -8,\n    duration       = 300,\n    access         = { lockAccess = true },\n\n    -- Visual: ragdoll + fade. Runs on the patient's machine.\n    onUseClient    = function(self) self:fadeOut(15000) end,\n    onTickClient   = function(self) self:ragdoll(5000) end,\n    onFinishClient = function(self) self:fadeIn(15000) end,\n\n    -- Authoritative: blood + pain mutations. Runs on the server.\n    onTickServer   = function(self)\n        if self.patient.conditions.bloodVolume \u003C 60 then\n            self:addBlood(0.1)\n        end\n        local pain = self.patient.conditions.pain or 0\n        if pain > 0 then\n            self:reducePain(pain / 5)\n        end\n    end\n},\n",[18,1126,1127,1136,1151,1163,1186,1197,1208,1220,1240,1256,1272,1288,1302,1314,1331,1338,1344,1386,1419,1450,1455,1461,1478,1508,1524,1530,1559,1574,1591,1596,1602],{"__ignoreMap":594},[598,1128,1129,1132,1134],{"class":600,"line":601},[598,1130,1131],{"class":604},"fentanyl ",[598,1133,936],{"class":617},[598,1135,939],{"class":604},[598,1137,1138,1141,1143,1145,1147,1149],{"class":600,"line":942},[598,1139,1140],{"class":604},"    type           ",[598,1142,936],{"class":617},[598,1144,950],{"class":617},[598,1146,247],{"class":953},[598,1148,957],{"class":617},[598,1150,960],{"class":604},[598,1152,1153,1156,1158,1161],{"class":600,"line":963},[598,1154,1155],{"class":604},"    time           ",[598,1157,936],{"class":617},[598,1159,1160],{"class":621}," 3000",[598,1162,960],{"class":604},[598,1164,1165,1168,1170,1173,1176,1179,1181,1184],{"class":600,"line":976},[598,1166,1167],{"class":604},"    injectingTime  ",[598,1169,936],{"class":617},[598,1171,1172],{"class":621}," 5",[598,1174,1175],{"class":617}," *",[598,1177,1178],{"class":621}," 60",[598,1180,1175],{"class":617},[598,1182,1183],{"class":621}," 1000",[598,1185,960],{"class":604},[598,1187,1188,1191,1193,1195],{"class":600,"line":989},[598,1189,1190],{"class":604},"    tickIntervalMs ",[598,1192,936],{"class":617},[598,1194,1183],{"class":621},[598,1196,960],{"class":604},[598,1198,1199,1202,1204,1206],{"class":600,"line":999},[598,1200,1201],{"class":604},"    removeItem     ",[598,1203,936],{"class":617},[598,1205,984],{"class":617},[598,1207,960],{"class":604},[598,1209,1210,1213,1215,1218],{"class":600,"line":1016},[598,1211,1212],{"class":604},"    volume         ",[598,1214,936],{"class":617},[598,1216,1217],{"class":621}," 20",[598,1219,960],{"class":604},[598,1221,1222,1225,1227,1230,1232,1234,1236,1238],{"class":600,"line":1032},[598,1223,1224],{"class":604},"    anim           ",[598,1226,936],{"class":617},[598,1228,1229],{"class":604}," { dict ",[598,1231,936],{"class":617},[598,1233,950],{"class":617},[598,1235,1009],{"class":953},[598,1237,957],{"class":617},[598,1239,960],{"class":604},[598,1241,1242,1245,1247,1249,1251,1254],{"class":600,"line":1038},[598,1243,1244],{"class":604},"                       name ",[598,1246,936],{"class":617},[598,1248,950],{"class":617},[598,1250,1026],{"class":953},[598,1252,1253],{"class":617},"\" ",[598,1255,1110],{"class":604},[598,1257,1258,1261,1263,1265,1268,1270],{"class":600,"line":1055},[598,1259,1260],{"class":604},"    lang           ",[598,1262,936],{"class":617},[598,1264,950],{"class":617},[598,1266,1267],{"class":953},"Verabreiche Fentanyl...",[598,1269,957],{"class":617},[598,1271,960],{"class":604},[598,1273,1274,1277,1279,1281,1284,1286],{"class":600,"line":1072},[598,1275,1276],{"class":604},"    langUsed       ",[598,1278,936],{"class":617},[598,1280,950],{"class":617},[598,1282,1283],{"class":953},"Fentanyl verabreicht",[598,1285,957],{"class":617},[598,1287,960],{"class":604},[598,1289,1290,1293,1295,1297,1300],{"class":600,"line":1088},[598,1291,1292],{"class":604},"    pain           ",[598,1294,936],{"class":617},[598,1296,1080],{"class":617},[598,1298,1299],{"class":621},"8",[598,1301,960],{"class":604},[598,1303,1304,1307,1309,1312],{"class":600,"line":1107},[598,1305,1306],{"class":604},"    duration       ",[598,1308,936],{"class":617},[598,1310,1311],{"class":621}," 300",[598,1313,960],{"class":604},[598,1315,1317,1320,1322,1324,1326,1328],{"class":600,"line":1316},14,[598,1318,1319],{"class":604},"    access         ",[598,1321,936],{"class":617},[598,1323,1096],{"class":604},[598,1325,936],{"class":617},[598,1327,984],{"class":617},[598,1329,1330],{"class":604}," },\n",[598,1332,1334],{"class":600,"line":1333},15,[598,1335,1337],{"emptyLinePlaceholder":1336},true,"\n",[598,1339,1341],{"class":600,"line":1340},16,[598,1342,1343],{"class":625},"    -- Visual: ragdoll + fade. Runs on the patient's machine.\n",[598,1345,1347,1351,1354,1358,1361,1364,1367,1370,1373,1375,1378,1381,1384],{"class":600,"line":1346},17,[598,1348,1350],{"class":1349},"s2Zo4","    onUseClient",[598,1352,1353],{"class":617},"    =",[598,1355,1357],{"class":1356},"s7zQu"," function",[598,1359,1360],{"class":617},"(",[598,1362,638],{"class":1363},"sHdIc",[598,1365,1366],{"class":617},")",[598,1368,1369],{"class":604}," self:",[598,1371,1372],{"class":1349},"fadeOut",[598,1374,1360],{"class":604},[598,1376,1377],{"class":621},"15000",[598,1379,1380],{"class":604},") ",[598,1382,1383],{"class":1356},"end",[598,1385,960],{"class":604},[598,1387,1389,1392,1395,1397,1399,1401,1403,1405,1408,1410,1413,1415,1417],{"class":600,"line":1388},18,[598,1390,1391],{"class":1349},"    onTickClient",[598,1393,1394],{"class":617},"   =",[598,1396,1357],{"class":1356},[598,1398,1360],{"class":617},[598,1400,638],{"class":1363},[598,1402,1366],{"class":617},[598,1404,1369],{"class":604},[598,1406,1407],{"class":1349},"ragdoll",[598,1409,1360],{"class":604},[598,1411,1412],{"class":621},"5000",[598,1414,1380],{"class":604},[598,1416,1383],{"class":1356},[598,1418,960],{"class":604},[598,1420,1422,1425,1427,1429,1431,1433,1435,1437,1440,1442,1444,1446,1448],{"class":600,"line":1421},19,[598,1423,1424],{"class":1349},"    onFinishClient",[598,1426,618],{"class":617},[598,1428,1357],{"class":1356},[598,1430,1360],{"class":617},[598,1432,638],{"class":1363},[598,1434,1366],{"class":617},[598,1436,1369],{"class":604},[598,1438,1439],{"class":1349},"fadeIn",[598,1441,1360],{"class":604},[598,1443,1377],{"class":621},[598,1445,1380],{"class":604},[598,1447,1383],{"class":1356},[598,1449,960],{"class":604},[598,1451,1453],{"class":600,"line":1452},20,[598,1454,1337],{"emptyLinePlaceholder":1336},[598,1456,1458],{"class":600,"line":1457},21,[598,1459,1460],{"class":625},"    -- Authoritative: blood + pain mutations. Runs on the server.\n",[598,1462,1464,1467,1469,1471,1473,1475],{"class":600,"line":1463},22,[598,1465,1466],{"class":1349},"    onTickServer",[598,1468,1394],{"class":617},[598,1470,1357],{"class":1356},[598,1472,1360],{"class":617},[598,1474,638],{"class":1363},[598,1476,1477],{"class":617},")\n",[598,1479,1481,1484,1487,1490,1492,1495,1497,1500,1503,1505],{"class":600,"line":1480},23,[598,1482,1483],{"class":1356},"        if",[598,1485,1486],{"class":604}," self.",[598,1488,1489],{"class":608},"patient",[598,1491,222],{"class":604},[598,1493,1494],{"class":608},"conditions",[598,1496,222],{"class":604},[598,1498,1499],{"class":608},"bloodVolume",[598,1501,1502],{"class":617}," \u003C",[598,1504,1178],{"class":621},[598,1506,1507],{"class":1356}," then\n",[598,1509,1511,1514,1517,1519,1522],{"class":600,"line":1510},24,[598,1512,1513],{"class":604},"            self:",[598,1515,1516],{"class":1349},"addBlood",[598,1518,1360],{"class":604},[598,1520,1521],{"class":621},"0.1",[598,1523,1477],{"class":604},[598,1525,1527],{"class":600,"line":1526},25,[598,1528,1529],{"class":1356},"        end\n",[598,1531,1533,1536,1539,1541,1543,1545,1547,1549,1551,1553,1556],{"class":600,"line":1532},26,[598,1534,1535],{"class":617},"        local",[598,1537,1538],{"class":604}," pain ",[598,1540,936],{"class":617},[598,1542,1486],{"class":604},[598,1544,1489],{"class":608},[598,1546,222],{"class":604},[598,1548,1494],{"class":608},[598,1550,222],{"class":604},[598,1552,54],{"class":608},[598,1554,1555],{"class":617}," or",[598,1557,1558],{"class":621}," 0\n",[598,1560,1562,1564,1566,1569,1572],{"class":600,"line":1561},27,[598,1563,1483],{"class":1356},[598,1565,1538],{"class":604},[598,1567,1568],{"class":617},">",[598,1570,1571],{"class":621}," 0",[598,1573,1507],{"class":1356},[598,1575,1577,1579,1582,1585,1587,1589],{"class":600,"line":1576},28,[598,1578,1513],{"class":604},[598,1580,1581],{"class":1349},"reducePain",[598,1583,1584],{"class":604},"(pain ",[598,1586,41],{"class":617},[598,1588,1172],{"class":621},[598,1590,1477],{"class":604},[598,1592,1594],{"class":600,"line":1593},29,[598,1595,1529],{"class":1356},[598,1597,1599],{"class":600,"line":1598},30,[598,1600,1601],{"class":1356},"    end\n",[598,1603,1605],{"class":600,"line":1604},31,[598,1606,1110],{"class":604},[15,1608,1609,1610,1613],{},"Medic applies ",[18,1611,1612],{},"fentanyl"," through the treatment menu -> the selected patient is targeted -> 3 s setup -> tick loop fires every second for 5 minutes, ragdolling the patient and topping up blood until conscious.",[655,1615,1617,1618,1366],{"id":1616},"pure-callback-type-custom","Pure callback (",[18,1619,1620],{},"type = \"custom\"",[588,1622,1624],{"className":590,"code":1623,"filename":592,"language":593,"meta":594,"style":594},"defibrillator = {\n    type        = \"custom\",\n    time        = 8000,\n    removeItem  = false,\n    anim        = { dict = \"anim@heists@narcotics@funding@gang_idle\",\n                    name = \"gang_chatting_idle01\" },\n    lang        = \"Benutze Defibrillator...\",\n    langUsed    = \"Defibrillator benutzt\",\n    access      = { lockAccess = true },\n\n    onUseClient = function(self)\n        self:playSoundAt(\"https://example.com/defib.mp3\", 1.0)\n    end,\n    onUseServer = function(self)\n        Wait(6000)\n        self:revive(self.target)\n    end\n}\n",[18,1625,1626,1635,1650,1661,1671,1689,1704,1719,1734,1748,1752,1766,1790,1797,1812,1824,1838,1842],{"__ignoreMap":594},[598,1627,1628,1631,1633],{"class":600,"line":601},[598,1629,1630],{"class":604},"defibrillator ",[598,1632,936],{"class":617},[598,1634,939],{"class":604},[598,1636,1637,1639,1641,1643,1646,1648],{"class":600,"line":942},[598,1638,945],{"class":604},[598,1640,936],{"class":617},[598,1642,950],{"class":617},[598,1644,1645],{"class":953},"custom",[598,1647,957],{"class":617},[598,1649,960],{"class":604},[598,1651,1652,1654,1656,1659],{"class":600,"line":963},[598,1653,966],{"class":604},[598,1655,936],{"class":617},[598,1657,1658],{"class":621}," 8000",[598,1660,960],{"class":604},[598,1662,1663,1665,1667,1669],{"class":600,"line":976},[598,1664,979],{"class":604},[598,1666,936],{"class":617},[598,1668,1101],{"class":617},[598,1670,960],{"class":604},[598,1672,1673,1675,1677,1679,1681,1683,1685,1687],{"class":600,"line":989},[598,1674,992],{"class":604},[598,1676,936],{"class":617},[598,1678,1229],{"class":604},[598,1680,936],{"class":617},[598,1682,950],{"class":617},[598,1684,1009],{"class":953},[598,1686,957],{"class":617},[598,1688,960],{"class":604},[598,1690,1691,1694,1696,1698,1700,1702],{"class":600,"line":999},[598,1692,1693],{"class":604},"                    name ",[598,1695,936],{"class":617},[598,1697,950],{"class":617},[598,1699,1026],{"class":953},[598,1701,1253],{"class":617},[598,1703,1110],{"class":604},[598,1705,1706,1708,1710,1712,1715,1717],{"class":600,"line":1016},[598,1707,1041],{"class":604},[598,1709,936],{"class":617},[598,1711,950],{"class":617},[598,1713,1714],{"class":953},"Benutze Defibrillator...",[598,1716,957],{"class":617},[598,1718,960],{"class":604},[598,1720,1721,1723,1725,1727,1730,1732],{"class":600,"line":1032},[598,1722,1058],{"class":604},[598,1724,936],{"class":617},[598,1726,950],{"class":617},[598,1728,1729],{"class":953},"Defibrillator benutzt",[598,1731,957],{"class":617},[598,1733,960],{"class":604},[598,1735,1736,1738,1740,1742,1744,1746],{"class":600,"line":1038},[598,1737,1091],{"class":604},[598,1739,936],{"class":617},[598,1741,1096],{"class":604},[598,1743,936],{"class":617},[598,1745,984],{"class":617},[598,1747,1330],{"class":604},[598,1749,1750],{"class":600,"line":1055},[598,1751,1337],{"emptyLinePlaceholder":1336},[598,1753,1754,1756,1758,1760,1762,1764],{"class":600,"line":1072},[598,1755,1350],{"class":1349},[598,1757,618],{"class":617},[598,1759,1357],{"class":1356},[598,1761,1360],{"class":617},[598,1763,638],{"class":1363},[598,1765,1477],{"class":617},[598,1767,1768,1771,1774,1776,1778,1781,1783,1785,1788],{"class":600,"line":1088},[598,1769,1770],{"class":604},"        self:",[598,1772,1773],{"class":1349},"playSoundAt",[598,1775,1360],{"class":604},[598,1777,957],{"class":617},[598,1779,1780],{"class":953},"https://example.com/defib.mp3",[598,1782,957],{"class":617},[598,1784,55],{"class":604},[598,1786,1787],{"class":621},"1.0",[598,1789,1477],{"class":604},[598,1791,1792,1795],{"class":600,"line":1107},[598,1793,1794],{"class":1356},"    end",[598,1796,960],{"class":604},[598,1798,1799,1802,1804,1806,1808,1810],{"class":600,"line":1316},[598,1800,1801],{"class":1349},"    onUseServer",[598,1803,618],{"class":617},[598,1805,1357],{"class":1356},[598,1807,1360],{"class":617},[598,1809,638],{"class":1363},[598,1811,1477],{"class":617},[598,1813,1814,1817,1819,1822],{"class":600,"line":1333},[598,1815,1816],{"class":1349},"        Wait",[598,1818,1360],{"class":604},[598,1820,1821],{"class":621},"6000",[598,1823,1477],{"class":604},[598,1825,1826,1828,1831,1834,1836],{"class":600,"line":1340},[598,1827,1770],{"class":604},[598,1829,1830],{"class":1349},"revive",[598,1832,1833],{"class":604},"(self.",[598,1835,849],{"class":608},[598,1837,1477],{"class":604},[598,1839,1840],{"class":600,"line":1346},[598,1841,1601],{"class":1356},[598,1843,1844],{"class":600,"line":1388},[598,1845,1846],{"class":604},"}\n",[15,1848,1849,1850,1853],{},"Medic uses the defibrillator -> sound plays at the user's coords -> after a 6 second charge, the targeted player is revived -> item is ",[647,1851,1852],{},"not"," removed.",[85,1855],{},[10,1857,1859,1862],{"id":1858},"lockaccess-semantics",[18,1860,1861],{},"lockAccess"," semantics",[15,1864,1865,1868,1869,1872],{},[18,1866,1867],{},"access.lockAccess = true"," means the use is gated server-side as ",[647,1870,1871],{},"medic job + on duty",":",[1874,1875,1876,1890,1896],"ol",{},[566,1877,1878,1879,1882,1883,1886,1887,222],{},"The source's job (via ",[18,1880,1881],{},"Sky_Jobs.PlayerCache.GetJob",") must appear in ",[18,1884,1885],{},"Config.Jobs"," with ",[18,1888,1889],{},"countsAsMedic = true",[566,1891,1892,1895],{},[18,1893,1894],{},"Sky_Jobs.PlayerCache.GetDuty"," must return truthy.",[566,1897,1898],{},"Inventory item use targets the user themselves. The treatment menu passes the selected patient as an explicit target.",[15,1900,1901,1902,1905,1906,1909],{},"For self-use items (",[18,1903,1904],{},"access.lockAccess = false",", the default), ",[18,1907,1908],{},"self.target = self.source"," and the range check is skipped.",[85,1911],{},[10,1913,1915],{"id":1914},"cancellation-stacking-collisions","Cancellation, stacking, collisions",[96,1917,1918,1928],{},[99,1919,1920],{},[102,1921,1922,1925],{},[105,1923,1924],{},"Situation",[105,1926,1927],{},"Outcome",[112,1929,1930,1945,1953,1964,1979,1987,1995],{},[102,1931,1932,1935],{},[117,1933,1934],{},"User enters a vehicle",[117,1936,1937,1938,1941,1942,1944],{},"Auto-cancel. ",[18,1939,1940],{},"onCancel*"," fires. No declarative effects. Item is ",[647,1943,1852],{}," consumed.",[102,1946,1947,1950],{},[117,1948,1949],{},"User dies",[117,1951,1952],{},"Auto-cancel. Same as above.",[102,1954,1955,1958],{},[117,1956,1957],{},"Source disconnects",[117,1959,1960,1961,222],{},"Server clears the run on ",[18,1962,1963],{},"playerDropped",[102,1965,1966,1973],{},[117,1967,1968,1969,1972],{},"Cross-player infusion: medic walks > ",[18,1970,1971],{},"_maxTargetDistance + 0.5"," from the target",[117,1974,1975,1976,222],{},"Server cancels with ",[18,1977,1978],{},"reason = \"out_of_range\"",[102,1980,1981,1984],{},[117,1982,1983],{},"User tries to start a second custom medication while one is active",[117,1985,1986],{},"Refused.",[102,1988,1989,1992],{},[117,1990,1991],{},"User has a self-bandage in progress",[117,1993,1994],{},"Custom medication start is refused.",[102,1996,1997,2008],{},[117,1998,1999,2002,2003,2005,2006],{},[18,2000,2001],{},"itemName"," collides with ",[18,2004,24],{}," or ",[18,2007,28],{},[117,2009,2010,2011,2013],{},"Console prints a collision warning at start. The custom medication is ",[647,2012,1852],{}," registered. The original medication still works.",[15,2015,2016,2017,2020],{},"Callback runtime errors are caught by ",[18,2018,2019],{},"pcall"," on both sides — a typo in your config will log the offending item and side, and clean-cancel the run rather than crashing the player thread.",[85,2022],{},[10,2024,2026],{"id":2025},"common-pitfalls","Common pitfalls",[563,2028,2029,2042,2057,2068,2081],{},[566,2030,2031,2038,2039,2041],{},[647,2032,2033,2034,33,2036,222],{},"Don't mutate vitals from ",[18,2035,32],{},[18,2037,153],{}," The client ",[18,2040,638],{}," deliberately has no mutators. Put state changes in the server-side callback.",[566,2043,2044,2056],{},[647,2045,2046,2047,2050,2051,2053,2054],{},"Don't call ",[18,2048,2049],{},"Wait(...)"," longer than ",[18,2052,127],{}," in ",[18,2055,32],{}," for non-infusion types — the run finishes when the server timer expires regardless of the client callback's progress.",[566,2058,2059,2064,2065,2067],{},[647,2060,2061],{},[18,2062,2063],{},"requiresOpenWound = true"," validates against the ",[647,2066,849],{},", not the source. For inventory item use this is the user; for treatment-menu use it's the selected patient.",[566,2069,2070,2076,2077,2080],{},[647,2071,2072,2073,1366],{},"Reusable items (",[18,2074,2075],{},"removeItem = false"," still go through the cooldown of ",[18,2078,2079],{},"activeRuns[src]"," — a player can't trigger the same item twice in parallel.",[566,2082,2083,2088,2089,222],{},[647,2084,2085,2087],{},[18,2086,695],{}," is fixed at start."," If you want a callback to retarget mid-run, pass an explicit target into the mutator: ",[18,2090,2091],{},"self:heal(20, self:nearbyPlayer())",[2093,2094,2095],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":594,"searchDepth":601,"depth":942,"links":2097},[2098,2099,2101,2102,2109,2115,2117,2118],{"id":12,"depth":942,"text":13},{"id":89,"depth":942,"text":2100},"The three type values",{"id":180,"depth":942,"text":181},{"id":634,"depth":942,"text":2103,"children":2104},"The self helper",[2105,2107],{"id":657,"depth":963,"text":2106},"Client self",{"id":808,"depth":963,"text":2108},"Server self",{"id":918,"depth":942,"text":919,"children":2110},[2111,2112,2113],{"id":922,"depth":963,"text":923},{"id":1120,"depth":963,"text":1121},{"id":1616,"depth":963,"text":2114},"Pure callback (type = \"custom\")",{"id":1858,"depth":942,"text":2116},"lockAccess semantics",{"id":1914,"depth":942,"text":1915},{"id":2025,"depth":942,"text":2026},"Declare inventory items that mix declarative effects (pain, blood, heal) with optional per-tick callbacks running on the client and server.","md",null,{},"/docs/jobs/ambulancejob/features/custom-medications",{"title":5,"description":2119},{"loc":2123},"1.docs/0.jobs/0.ambulancejob/3.features/3.custom-medications","P3N-8lmnFnu9UEEQAzMpmx4bRiz4-ionbuwbddzvtrY",[2129,2134],{"title":2130,"path":2131,"stem":2132,"description":2133,"children":-1},"Health Insurance","/docs/jobs/ambulancejob/features/insurance","1.docs/0.jobs/0.ambulancejob/3.features/2.insurance","Configure insurance providers, billing cadence, and coverage expiration for Sky Ambulancejob.",{"title":2135,"path":2136,"stem":2137,"description":2138,"children":-1},"Inventory Items","/docs/jobs/ambulancejob/reference/inventories","1.docs/0.jobs/0.ambulancejob/4.reference/1.inventories","Use these configurations to prepare your inventory for the Sky Ambulance Job script.",[],1783080557634]