AdminVerbSystem.Tools.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. using System.Diagnostics.CodeAnalysis;
  2. using System.Linq;
  3. using System.Numerics;
  4. using Content.Server.Administration.Components;
  5. using Content.Server.Atmos;
  6. using Content.Server.Atmos.Components;
  7. using Content.Server.Cargo.Components;
  8. using Content.Server.Doors.Systems;
  9. using Content.Server.Hands.Systems;
  10. using Content.Server.Power.Components;
  11. using Content.Server.Power.EntitySystems;
  12. using Content.Server.Stack;
  13. using Content.Server.Station.Components;
  14. using Content.Server.Station.Systems;
  15. using Content.Server.Weapons.Ranged.Systems;
  16. using Content.Shared.Access;
  17. using Content.Shared.Access.Components;
  18. using Content.Shared.Access.Systems;
  19. using Content.Shared.Administration;
  20. using Content.Shared.Atmos;
  21. using Content.Shared.Construction.Components;
  22. using Content.Shared.Damage;
  23. using Content.Shared.Damage.Components;
  24. using Content.Shared.Database;
  25. using Content.Shared.Doors.Components;
  26. using Content.Shared.Hands.Components;
  27. using Content.Shared.Inventory;
  28. using Content.Shared.PDA;
  29. using Content.Shared.Stacks;
  30. using Content.Shared.Verbs;
  31. using Content.Shared.Weapons.Ranged.Components;
  32. using Robust.Server.Physics;
  33. using Robust.Shared.Map;
  34. using Robust.Shared.Map.Components;
  35. using Robust.Shared.Physics;
  36. using Robust.Shared.Physics.Components;
  37. using Robust.Shared.Player;
  38. using Robust.Shared.Prototypes;
  39. using Robust.Shared.Utility;
  40. namespace Content.Server.Administration.Systems;
  41. public sealed partial class AdminVerbSystem
  42. {
  43. [Dependency] private readonly DoorSystem _door = default!;
  44. [Dependency] private readonly AirlockSystem _airlockSystem = default!;
  45. [Dependency] private readonly StackSystem _stackSystem = default!;
  46. [Dependency] private readonly SharedAccessSystem _accessSystem = default!;
  47. [Dependency] private readonly HandsSystem _handsSystem = default!;
  48. [Dependency] private readonly QuickDialogSystem _quickDialog = default!;
  49. [Dependency] private readonly AdminTestArenaSystem _adminTestArenaSystem = default!;
  50. [Dependency] private readonly StationJobsSystem _stationJobsSystem = default!;
  51. [Dependency] private readonly JointSystem _jointSystem = default!;
  52. [Dependency] private readonly BatterySystem _batterySystem = default!;
  53. [Dependency] private readonly MetaDataSystem _metaSystem = default!;
  54. [Dependency] private readonly GunSystem _gun = default!;
  55. private void AddTricksVerbs(GetVerbsEvent<Verb> args)
  56. {
  57. if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
  58. return;
  59. var player = actor.PlayerSession;
  60. if (!_adminManager.HasAdminFlag(player, AdminFlags.Admin))
  61. return;
  62. if (_adminManager.HasAdminFlag(player, AdminFlags.Admin))
  63. {
  64. if (TryComp<DoorBoltComponent>(args.Target, out var bolts))
  65. {
  66. Verb bolt = new()
  67. {
  68. Text = bolts.BoltsDown ? "Unbolt" : "Bolt",
  69. Category = VerbCategory.Tricks,
  70. Icon = bolts.BoltsDown
  71. ? new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/unbolt.png"))
  72. : new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/bolt.png")),
  73. Act = () =>
  74. {
  75. _door.SetBoltsDown((args.Target, bolts), !bolts.BoltsDown);
  76. },
  77. Impact = LogImpact.Medium,
  78. Message = Loc.GetString(bolts.BoltsDown
  79. ? "admin-trick-unbolt-description"
  80. : "admin-trick-bolt-description"),
  81. Priority = (int) (bolts.BoltsDown ? TricksVerbPriorities.Unbolt : TricksVerbPriorities.Bolt),
  82. };
  83. args.Verbs.Add(bolt);
  84. }
  85. if (TryComp<AirlockComponent>(args.Target, out var airlockComp))
  86. {
  87. Verb emergencyAccess = new()
  88. {
  89. Text = airlockComp.EmergencyAccess ? "Emergency Access Off" : "Emergency Access On",
  90. Category = VerbCategory.Tricks,
  91. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/emergency_access.png")),
  92. Act = () =>
  93. {
  94. _airlockSystem.SetEmergencyAccess((args.Target, airlockComp), !airlockComp.EmergencyAccess);
  95. },
  96. Impact = LogImpact.Medium,
  97. Message = Loc.GetString(airlockComp.EmergencyAccess
  98. ? "admin-trick-emergency-access-off-description"
  99. : "admin-trick-emergency-access-on-description"),
  100. Priority = (int) (airlockComp.EmergencyAccess ? TricksVerbPriorities.EmergencyAccessOff : TricksVerbPriorities.EmergencyAccessOn),
  101. };
  102. args.Verbs.Add(emergencyAccess);
  103. }
  104. if (HasComp<DamageableComponent>(args.Target))
  105. {
  106. Verb rejuvenate = new()
  107. {
  108. Text = "Rejuvenate",
  109. Category = VerbCategory.Tricks,
  110. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rejuvenate.png")),
  111. Act = () =>
  112. {
  113. _rejuvenate.PerformRejuvenate(args.Target);
  114. },
  115. Impact = LogImpact.Extreme,
  116. Message = Loc.GetString("admin-trick-rejuvenate-description"),
  117. Priority = (int) TricksVerbPriorities.Rejuvenate,
  118. };
  119. args.Verbs.Add(rejuvenate);
  120. }
  121. if (!HasComp<GodmodeComponent>(args.Target))
  122. {
  123. Verb makeIndestructible = new()
  124. {
  125. Text = "Make Indestructible",
  126. Category = VerbCategory.Tricks,
  127. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")),
  128. Act = () =>
  129. {
  130. _sharedGodmodeSystem.EnableGodmode(args.Target);
  131. },
  132. Impact = LogImpact.Extreme,
  133. Message = Loc.GetString("admin-trick-make-indestructible-description"),
  134. Priority = (int) TricksVerbPriorities.MakeIndestructible,
  135. };
  136. args.Verbs.Add(makeIndestructible);
  137. }
  138. else
  139. {
  140. Verb makeVulnerable = new()
  141. {
  142. Text = "Make Vulnerable",
  143. Category = VerbCategory.Tricks,
  144. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/plus.svg.192dpi.png")),
  145. Act = () =>
  146. {
  147. _sharedGodmodeSystem.DisableGodmode(args.Target);
  148. },
  149. Impact = LogImpact.Extreme,
  150. Message = Loc.GetString("admin-trick-make-vulnerable-description"),
  151. Priority = (int) TricksVerbPriorities.MakeVulnerable,
  152. };
  153. args.Verbs.Add(makeVulnerable);
  154. }
  155. if (TryComp<BatteryComponent>(args.Target, out var battery))
  156. {
  157. Verb refillBattery = new()
  158. {
  159. Text = "Refill Battery",
  160. Category = VerbCategory.Tricks,
  161. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill_battery.png")),
  162. Act = () =>
  163. {
  164. _batterySystem.SetCharge(args.Target, battery.MaxCharge, battery);
  165. },
  166. Impact = LogImpact.Medium,
  167. Message = Loc.GetString("admin-trick-refill-battery-description"),
  168. Priority = (int) TricksVerbPriorities.RefillBattery,
  169. };
  170. args.Verbs.Add(refillBattery);
  171. Verb drainBattery = new()
  172. {
  173. Text = "Drain Battery",
  174. Category = VerbCategory.Tricks,
  175. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/drain_battery.png")),
  176. Act = () =>
  177. {
  178. _batterySystem.SetCharge(args.Target, 0, battery);
  179. },
  180. Impact = LogImpact.Medium,
  181. Message = Loc.GetString("admin-trick-drain-battery-description"),
  182. Priority = (int) TricksVerbPriorities.DrainBattery,
  183. };
  184. args.Verbs.Add(drainBattery);
  185. Verb infiniteBattery = new()
  186. {
  187. Text = "Infinite Battery",
  188. Category = VerbCategory.Tricks,
  189. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/infinite_battery.png")),
  190. Act = () =>
  191. {
  192. var recharger = EnsureComp<BatterySelfRechargerComponent>(args.Target);
  193. recharger.AutoRecharge = true;
  194. recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
  195. recharger.AutoRechargePause = false; // No delay.
  196. },
  197. Impact = LogImpact.Medium,
  198. Message = Loc.GetString("admin-trick-infinite-battery-object-description"),
  199. Priority = (int) TricksVerbPriorities.InfiniteBattery,
  200. };
  201. args.Verbs.Add(infiniteBattery);
  202. }
  203. if (TryComp<AnchorableComponent>(args.Target, out var anchor))
  204. {
  205. Verb blockUnanchor = new()
  206. {
  207. Text = "Block Unanchoring",
  208. Category = VerbCategory.Tricks,
  209. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/anchor.svg.192dpi.png")),
  210. Act = () =>
  211. {
  212. RemComp(args.Target, anchor);
  213. },
  214. Impact = LogImpact.Medium,
  215. Message = Loc.GetString("admin-trick-block-unanchoring-description"),
  216. Priority = (int) TricksVerbPriorities.BlockUnanchoring,
  217. };
  218. args.Verbs.Add(blockUnanchor);
  219. }
  220. if (TryComp<GasTankComponent>(args.Target, out var tank))
  221. {
  222. Verb refillInternalsO2 = new()
  223. {
  224. Text = "Refill Internals Oxygen",
  225. Category = VerbCategory.Tricks,
  226. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
  227. Act = () =>
  228. {
  229. RefillGasTank(args.Target, Gas.Oxygen, tank);
  230. },
  231. Impact = LogImpact.Extreme,
  232. Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
  233. Priority = (int) TricksVerbPriorities.RefillOxygen,
  234. };
  235. args.Verbs.Add(refillInternalsO2);
  236. Verb refillInternalsN2 = new()
  237. {
  238. Text = "Refill Internals Nitrogen",
  239. Category = VerbCategory.Tricks,
  240. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
  241. Act = () =>
  242. {
  243. RefillGasTank(args.Target, Gas.Nitrogen, tank);
  244. },
  245. Impact = LogImpact.Extreme,
  246. Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
  247. Priority = (int) TricksVerbPriorities.RefillNitrogen,
  248. };
  249. args.Verbs.Add(refillInternalsN2);
  250. Verb refillInternalsPlasma = new()
  251. {
  252. Text = "Refill Internals Plasma",
  253. Category = VerbCategory.Tricks,
  254. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
  255. Act = () =>
  256. {
  257. RefillGasTank(args.Target, Gas.Plasma, tank);
  258. },
  259. Impact = LogImpact.Extreme,
  260. Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
  261. Priority = (int) TricksVerbPriorities.RefillPlasma,
  262. };
  263. args.Verbs.Add(refillInternalsPlasma);
  264. }
  265. if (HasComp<InventoryComponent>(args.Target))
  266. {
  267. Verb refillInternalsO2 = new()
  268. {
  269. Text = "Refill Internals Oxygen",
  270. Category = VerbCategory.Tricks,
  271. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/oxygen.rsi"), "icon"),
  272. Act = () => RefillEquippedTanks(args.User, Gas.Oxygen),
  273. Impact = LogImpact.Extreme,
  274. Message = Loc.GetString("admin-trick-internals-refill-oxygen-description"),
  275. Priority = (int) TricksVerbPriorities.RefillOxygen,
  276. };
  277. args.Verbs.Add(refillInternalsO2);
  278. Verb refillInternalsN2 = new()
  279. {
  280. Text = "Refill Internals Nitrogen",
  281. Category = VerbCategory.Tricks,
  282. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/red.rsi"), "icon"),
  283. Act = () =>RefillEquippedTanks(args.User, Gas.Nitrogen),
  284. Impact = LogImpact.Extreme,
  285. Message = Loc.GetString("admin-trick-internals-refill-nitrogen-description"),
  286. Priority = (int) TricksVerbPriorities.RefillNitrogen,
  287. };
  288. args.Verbs.Add(refillInternalsN2);
  289. Verb refillInternalsPlasma = new()
  290. {
  291. Text = "Refill Internals Plasma",
  292. Category = VerbCategory.Tricks,
  293. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Tanks/plasma.rsi"), "icon"),
  294. Act = () => RefillEquippedTanks(args.User, Gas.Plasma),
  295. Impact = LogImpact.Extreme,
  296. Message = Loc.GetString("admin-trick-internals-refill-plasma-description"),
  297. Priority = (int) TricksVerbPriorities.RefillPlasma,
  298. };
  299. args.Verbs.Add(refillInternalsPlasma);
  300. }
  301. Verb sendToTestArena = new()
  302. {
  303. Text = "Send to test arena",
  304. Category = VerbCategory.Tricks,
  305. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")),
  306. Act = () =>
  307. {
  308. var (mapUid, gridUid) = _adminTestArenaSystem.AssertArenaLoaded(player);
  309. _transformSystem.SetCoordinates(args.Target, new EntityCoordinates(gridUid ?? mapUid, Vector2.One));
  310. },
  311. Impact = LogImpact.Medium,
  312. Message = Loc.GetString("admin-trick-send-to-test-arena-description"),
  313. Priority = (int) TricksVerbPriorities.SendToTestArena,
  314. };
  315. args.Verbs.Add(sendToTestArena);
  316. var activeId = FindActiveId(args.Target);
  317. if (activeId is not null)
  318. {
  319. Verb grantAllAccess = new()
  320. {
  321. Text = "Grant All Access",
  322. Category = VerbCategory.Tricks,
  323. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"),
  324. Act = () =>
  325. {
  326. GiveAllAccess(activeId.Value);
  327. },
  328. Impact = LogImpact.Extreme,
  329. Message = Loc.GetString("admin-trick-grant-all-access-description"),
  330. Priority = (int) TricksVerbPriorities.GrantAllAccess,
  331. };
  332. args.Verbs.Add(grantAllAccess);
  333. Verb revokeAllAccess = new()
  334. {
  335. Text = "Revoke All Access",
  336. Category = VerbCategory.Tricks,
  337. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"),
  338. Act = () =>
  339. {
  340. RevokeAllAccess(activeId.Value);
  341. },
  342. Impact = LogImpact.Extreme,
  343. Message = Loc.GetString("admin-trick-revoke-all-access-description"),
  344. Priority = (int) TricksVerbPriorities.RevokeAllAccess,
  345. };
  346. args.Verbs.Add(revokeAllAccess);
  347. }
  348. if (HasComp<AccessComponent>(args.Target))
  349. {
  350. Verb grantAllAccess = new()
  351. {
  352. Text = "Grant All Access",
  353. Category = VerbCategory.Tricks,
  354. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "centcom"),
  355. Act = () =>
  356. {
  357. GiveAllAccess(args.Target);
  358. },
  359. Impact = LogImpact.Extreme,
  360. Message = Loc.GetString("admin-trick-grant-all-access-description"),
  361. Priority = (int) TricksVerbPriorities.GrantAllAccess,
  362. };
  363. args.Verbs.Add(grantAllAccess);
  364. Verb revokeAllAccess = new()
  365. {
  366. Text = "Revoke All Access",
  367. Category = VerbCategory.Tricks,
  368. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Misc/id_cards.rsi"), "default"),
  369. Act = () =>
  370. {
  371. RevokeAllAccess(args.Target);
  372. },
  373. Impact = LogImpact.Extreme,
  374. Message = Loc.GetString("admin-trick-revoke-all-access-description"),
  375. Priority = (int) TricksVerbPriorities.RevokeAllAccess,
  376. };
  377. args.Verbs.Add(revokeAllAccess);
  378. }
  379. }
  380. if (TryComp<StackComponent>(args.Target, out var stack))
  381. {
  382. Verb adjustStack = new()
  383. {
  384. Text = "Adjust Stack",
  385. Category = VerbCategory.Tricks,
  386. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/adjust-stack.png")),
  387. Act = () =>
  388. {
  389. // Unbounded intentionally.
  390. _quickDialog.OpenDialog(player, "Adjust stack", $"Amount (max {_stackSystem.GetMaxCount(stack)})", (int newAmount) =>
  391. {
  392. _stackSystem.SetCount(args.Target, newAmount, stack);
  393. });
  394. },
  395. Impact = LogImpact.Medium,
  396. Message = Loc.GetString("admin-trick-adjust-stack-description"),
  397. Priority = (int) TricksVerbPriorities.AdjustStack,
  398. };
  399. args.Verbs.Add(adjustStack);
  400. Verb fillStack = new()
  401. {
  402. Text = "Fill Stack",
  403. Category = VerbCategory.Tricks,
  404. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill-stack.png")),
  405. Act = () =>
  406. {
  407. _stackSystem.SetCount(args.Target, _stackSystem.GetMaxCount(stack), stack);
  408. },
  409. Impact = LogImpact.Medium,
  410. Message = Loc.GetString("admin-trick-fill-stack-description"),
  411. Priority = (int) TricksVerbPriorities.FillStack,
  412. };
  413. args.Verbs.Add(fillStack);
  414. }
  415. Verb rename = new()
  416. {
  417. Text = "Rename",
  418. Category = VerbCategory.Tricks,
  419. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rename.png")),
  420. Act = () =>
  421. {
  422. _quickDialog.OpenDialog(player, "Rename", "Name", (string newName) =>
  423. {
  424. _metaSystem.SetEntityName(args.Target, newName);
  425. });
  426. },
  427. Impact = LogImpact.Medium,
  428. Message = Loc.GetString("admin-trick-rename-description"),
  429. Priority = (int) TricksVerbPriorities.Rename,
  430. };
  431. args.Verbs.Add(rename);
  432. Verb redescribe = new()
  433. {
  434. Text = "Redescribe",
  435. Category = VerbCategory.Tricks,
  436. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/redescribe.png")),
  437. Act = () =>
  438. {
  439. _quickDialog.OpenDialog(player, "Redescribe", "Description", (LongString newDescription) =>
  440. {
  441. _metaSystem.SetEntityDescription(args.Target, newDescription.String);
  442. });
  443. },
  444. Impact = LogImpact.Medium,
  445. Message = Loc.GetString("admin-trick-redescribe-description"),
  446. Priority = (int) TricksVerbPriorities.Redescribe,
  447. };
  448. args.Verbs.Add(redescribe);
  449. Verb renameAndRedescribe = new()
  450. {
  451. Text = "Redescribe",
  452. Category = VerbCategory.Tricks,
  453. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/rename_and_redescribe.png")),
  454. Act = () =>
  455. {
  456. _quickDialog.OpenDialog(player, "Rename & Redescribe", "Name", "Description",
  457. (string newName, LongString newDescription) =>
  458. {
  459. var meta = MetaData(args.Target);
  460. _metaSystem.SetEntityName(args.Target, newName, meta);
  461. _metaSystem.SetEntityDescription(args.Target, newDescription.String, meta);
  462. });
  463. },
  464. Impact = LogImpact.Medium,
  465. Message = Loc.GetString("admin-trick-rename-and-redescribe-description"),
  466. Priority = (int) TricksVerbPriorities.RenameAndRedescribe,
  467. };
  468. args.Verbs.Add(renameAndRedescribe);
  469. if (TryComp<StationDataComponent>(args.Target, out var stationData))
  470. {
  471. if (_adminManager.HasAdminFlag(player, AdminFlags.Round))
  472. {
  473. Verb barJobSlots = new()
  474. {
  475. Text = "Bar job slots",
  476. Category = VerbCategory.Tricks,
  477. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/bar_jobslots.png")),
  478. Act = () =>
  479. {
  480. foreach (var (job, _) in _stationJobsSystem.GetJobs(args.Target))
  481. {
  482. _stationJobsSystem.TrySetJobSlot(args.Target, job, 0, true);
  483. }
  484. },
  485. Impact = LogImpact.Extreme,
  486. Message = Loc.GetString("admin-trick-bar-job-slots-description"),
  487. Priority = (int) TricksVerbPriorities.BarJobSlots,
  488. };
  489. args.Verbs.Add(barJobSlots);
  490. }
  491. Verb locateCargoShuttle = new()
  492. {
  493. Text = "Locate Cargo Shuttle",
  494. Category = VerbCategory.Tricks,
  495. Icon = new SpriteSpecifier.Rsi(new("/Textures/Clothing/Head/Soft/cargosoft.rsi"), "icon"),
  496. Act = () =>
  497. {
  498. var shuttle = Comp<StationCargoOrderDatabaseComponent>(args.Target).Shuttle;
  499. if (shuttle is null)
  500. return;
  501. _transformSystem.SetCoordinates(args.User, new EntityCoordinates(shuttle.Value, Vector2.Zero));
  502. },
  503. Impact = LogImpact.Low,
  504. Message = Loc.GetString("admin-trick-locate-cargo-shuttle-description"),
  505. Priority = (int) TricksVerbPriorities.LocateCargoShuttle,
  506. };
  507. args.Verbs.Add(locateCargoShuttle);
  508. }
  509. if (TryGetGridChildren(args.Target, out var childEnum))
  510. {
  511. Verb refillBattery = new()
  512. {
  513. Text = "Refill Battery",
  514. Category = VerbCategory.Tricks,
  515. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/fill_battery.png")),
  516. Act = () =>
  517. {
  518. foreach (var ent in childEnum)
  519. {
  520. if (!HasComp<StationInfiniteBatteryTargetComponent>(ent))
  521. continue;
  522. var battery = EnsureComp<BatteryComponent>(ent);
  523. _batterySystem.SetCharge(ent, battery.MaxCharge, battery);
  524. }
  525. },
  526. Impact = LogImpact.Extreme,
  527. Message = Loc.GetString("admin-trick-refill-battery-description"),
  528. Priority = (int) TricksVerbPriorities.RefillBattery,
  529. };
  530. args.Verbs.Add(refillBattery);
  531. Verb drainBattery = new()
  532. {
  533. Text = "Drain Battery",
  534. Category = VerbCategory.Tricks,
  535. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/drain_battery.png")),
  536. Act = () =>
  537. {
  538. foreach (var ent in childEnum)
  539. {
  540. if (!HasComp<StationInfiniteBatteryTargetComponent>(ent))
  541. continue;
  542. var battery = EnsureComp<BatteryComponent>(ent);
  543. _batterySystem.SetCharge(ent, 0, battery);
  544. }
  545. },
  546. Impact = LogImpact.Extreme,
  547. Message = Loc.GetString("admin-trick-drain-battery-description"),
  548. Priority = (int) TricksVerbPriorities.DrainBattery,
  549. };
  550. args.Verbs.Add(drainBattery);
  551. Verb infiniteBattery = new()
  552. {
  553. Text = "Infinite Battery",
  554. Category = VerbCategory.Tricks,
  555. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/infinite_battery.png")),
  556. Act = () =>
  557. {
  558. // this kills the sloth
  559. foreach (var ent in childEnum)
  560. {
  561. if (!HasComp<StationInfiniteBatteryTargetComponent>(ent))
  562. continue;
  563. var recharger = EnsureComp<BatterySelfRechargerComponent>(ent);
  564. var battery = EnsureComp<BatteryComponent>(ent);
  565. recharger.AutoRecharge = true;
  566. recharger.AutoRechargeRate = battery.MaxCharge; // Instant refill.
  567. recharger.AutoRechargePause = false; // No delay.
  568. }
  569. },
  570. Impact = LogImpact.Extreme,
  571. Message = Loc.GetString("admin-trick-infinite-battery-description"),
  572. Priority = (int) TricksVerbPriorities.InfiniteBattery,
  573. };
  574. args.Verbs.Add(infiniteBattery);
  575. }
  576. if (TryComp<PhysicsComponent>(args.Target, out var physics))
  577. {
  578. Verb haltMovement = new()
  579. {
  580. Text = "Halt Movement",
  581. Category = VerbCategory.Tricks,
  582. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/halt.png")),
  583. Act = () =>
  584. {
  585. _physics.SetLinearVelocity(args.Target, Vector2.Zero, body: physics);
  586. _physics.SetAngularVelocity(args.Target, 0f, body: physics);
  587. },
  588. Impact = LogImpact.Medium,
  589. Message = Loc.GetString("admin-trick-halt-movement-description"),
  590. Priority = (int) TricksVerbPriorities.HaltMovement,
  591. };
  592. args.Verbs.Add(haltMovement);
  593. }
  594. if (TryComp<MapComponent>(args.Target, out var map))
  595. {
  596. if (_adminManager.HasAdminFlag(player, AdminFlags.Mapping))
  597. {
  598. if (_mapManager.IsMapPaused(map.MapId))
  599. {
  600. Verb unpauseMap = new()
  601. {
  602. Text = "Unpause Map",
  603. Category = VerbCategory.Tricks,
  604. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/play.png")),
  605. Act = () =>
  606. {
  607. _mapManager.SetMapPaused(map.MapId, false);
  608. },
  609. Impact = LogImpact.Extreme,
  610. Message = Loc.GetString("admin-trick-unpause-map-description"),
  611. Priority = (int) TricksVerbPriorities.Unpause,
  612. };
  613. args.Verbs.Add(unpauseMap);
  614. }
  615. else
  616. {
  617. Verb pauseMap = new()
  618. {
  619. Text = "Pause Map",
  620. Category = VerbCategory.Tricks,
  621. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/pause.png")),
  622. Act = () =>
  623. {
  624. _mapManager.SetMapPaused(map.MapId, true);
  625. },
  626. Impact = LogImpact.Extreme,
  627. Message = Loc.GetString("admin-trick-pause-map-description"),
  628. Priority = (int) TricksVerbPriorities.Pause,
  629. };
  630. args.Verbs.Add(pauseMap);
  631. }
  632. }
  633. }
  634. if (TryComp<JointComponent>(args.Target, out var joints))
  635. {
  636. Verb snapJoints = new()
  637. {
  638. Text = "Snap Joints",
  639. Category = VerbCategory.Tricks,
  640. Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/AdminActions/snap_joints.png")),
  641. Act = () =>
  642. {
  643. _jointSystem.ClearJoints(args.Target, joints);
  644. },
  645. Impact = LogImpact.Medium,
  646. Message = Loc.GetString("admin-trick-snap-joints-description"),
  647. Priority = (int) TricksVerbPriorities.SnapJoints,
  648. };
  649. args.Verbs.Add(snapJoints);
  650. }
  651. if (TryComp<GunComponent>(args.Target, out var gun))
  652. {
  653. Verb minigunFire = new()
  654. {
  655. Text = "Make Minigun",
  656. Category = VerbCategory.Tricks,
  657. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Weapons/Guns/HMGs/minigun.rsi"), "icon"),
  658. Act = () =>
  659. {
  660. EnsureComp<AdminMinigunComponent>(args.Target);
  661. _gun.RefreshModifiers((args.Target, gun));
  662. },
  663. Impact = LogImpact.Medium,
  664. Message = Loc.GetString("admin-trick-minigun-fire-description"),
  665. Priority = (int) TricksVerbPriorities.MakeMinigun,
  666. };
  667. args.Verbs.Add(minigunFire);
  668. }
  669. if (TryComp<BallisticAmmoProviderComponent>(args.Target, out var ballisticAmmo))
  670. {
  671. Verb setCapacity = new()
  672. {
  673. Text = "Set Bullet Amount",
  674. Category = VerbCategory.Tricks,
  675. Icon = new SpriteSpecifier.Rsi(new("/Textures/Objects/Fun/caps.rsi"), "mag-6"),
  676. Act = () =>
  677. {
  678. _quickDialog.OpenDialog(player, "Set Bullet Amount", $"Amount (standard {ballisticAmmo.Capacity}):", (string amount) =>
  679. {
  680. if (!int.TryParse(amount, out var result))
  681. return;
  682. _gun.SetBallisticUnspawned((args.Target, ballisticAmmo), result);
  683. _gun.UpdateBallisticAppearance(args.Target, ballisticAmmo);
  684. });
  685. },
  686. Impact = LogImpact.Medium,
  687. Message = Loc.GetString("admin-trick-set-bullet-amount-description"),
  688. Priority = (int) TricksVerbPriorities.SetBulletAmount,
  689. };
  690. args.Verbs.Add(setCapacity);
  691. }
  692. }
  693. private void RefillEquippedTanks(EntityUid target, Gas gasType)
  694. {
  695. foreach (var held in _inventorySystem.GetHandOrInventoryEntities(target))
  696. {
  697. RefillGasTank(held, gasType);
  698. }
  699. }
  700. private void RefillGasTank(EntityUid tank, Gas gasType, GasTankComponent? tankComponent = null)
  701. {
  702. if (!Resolve(tank, ref tankComponent, false))
  703. return;
  704. var mixSize = tankComponent.Air.Volume;
  705. var newMix = new GasMixture(mixSize);
  706. newMix.SetMoles(gasType, (1000.0f * mixSize) / (Atmospherics.R * Atmospherics.T20C)); // Fill the tank to 1000KPA.
  707. newMix.Temperature = Atmospherics.T20C;
  708. tankComponent.Air = newMix;
  709. }
  710. private bool TryGetGridChildren(EntityUid target, [NotNullWhen(true)] out IEnumerable<EntityUid>? enumerator)
  711. {
  712. if (!HasComp<MapComponent>(target) && !HasComp<MapGridComponent>(target) &&
  713. !HasComp<StationDataComponent>(target))
  714. {
  715. enumerator = null;
  716. return false;
  717. }
  718. enumerator = GetGridChildrenInner(target);
  719. return true;
  720. }
  721. // ew. This finds everything supposedly on a grid.
  722. private IEnumerable<EntityUid> GetGridChildrenInner(EntityUid target)
  723. {
  724. if (TryComp<StationDataComponent>(target, out var station))
  725. {
  726. foreach (var grid in station.Grids)
  727. {
  728. var enumerator = Transform(grid).ChildEnumerator;
  729. while (enumerator.MoveNext(out var ent))
  730. {
  731. yield return ent;
  732. }
  733. }
  734. }
  735. else if (HasComp<MapComponent>(target))
  736. {
  737. var enumerator = Transform(target).ChildEnumerator;
  738. while (enumerator.MoveNext(out var possibleGrid))
  739. {
  740. var enumerator2 = Transform(possibleGrid).ChildEnumerator;
  741. while (enumerator2.MoveNext(out var ent))
  742. {
  743. yield return ent;
  744. }
  745. }
  746. }
  747. else
  748. {
  749. var enumerator = Transform(target).ChildEnumerator;
  750. while (enumerator.MoveNext(out var ent))
  751. {
  752. yield return ent;
  753. }
  754. }
  755. }
  756. private EntityUid? FindActiveId(EntityUid target)
  757. {
  758. if (_inventorySystem.TryGetSlotEntity(target, "id", out var slotEntity))
  759. {
  760. if (HasComp<AccessComponent>(slotEntity))
  761. {
  762. return slotEntity.Value;
  763. }
  764. else if (TryComp<PdaComponent>(slotEntity, out var pda)
  765. && HasComp<IdCardComponent>(pda.ContainedId))
  766. {
  767. return pda.ContainedId;
  768. }
  769. }
  770. else if (TryComp<HandsComponent>(target, out var hands))
  771. {
  772. foreach (var held in _handsSystem.EnumerateHeld(target, hands))
  773. {
  774. if (HasComp<AccessComponent>(held))
  775. {
  776. return held;
  777. }
  778. }
  779. }
  780. return null;
  781. }
  782. private void GiveAllAccess(EntityUid entity)
  783. {
  784. var allAccess = _prototypeManager
  785. .EnumeratePrototypes<AccessLevelPrototype>()
  786. .Select(p => new ProtoId<AccessLevelPrototype>(p.ID)).ToArray();
  787. _accessSystem.TrySetTags(entity, allAccess);
  788. }
  789. private void RevokeAllAccess(EntityUid entity)
  790. {
  791. _accessSystem.TrySetTags(entity, new List<ProtoId<AccessLevelPrototype>>());
  792. }
  793. public enum TricksVerbPriorities
  794. {
  795. Bolt = 0,
  796. Unbolt = -1,
  797. EmergencyAccessOn = -2,
  798. EmergencyAccessOff = -3,
  799. MakeIndestructible = -4,
  800. MakeVulnerable = -5,
  801. BlockUnanchoring = -6,
  802. RefillBattery = -7,
  803. DrainBattery = -8,
  804. RefillOxygen = -9,
  805. RefillNitrogen = -10,
  806. RefillPlasma = -11,
  807. SendToTestArena = -12,
  808. GrantAllAccess = -13,
  809. RevokeAllAccess = -14,
  810. Rejuvenate = -15,
  811. AdjustStack = -16,
  812. FillStack = -17,
  813. Rename = -18,
  814. Redescribe = -19,
  815. RenameAndRedescribe = -20,
  816. BarJobSlots = -21,
  817. LocateCargoShuttle = -22,
  818. InfiniteBattery = -23,
  819. HaltMovement = -24,
  820. Unpause = -25,
  821. Pause = -26,
  822. SnapJoints = -27,
  823. MakeMinigun = -28,
  824. SetBulletAmount = -29,
  825. }
  826. }