AdminVerbSystem.Smites.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. using System.Threading;
  2. using Content.Server.Administration.Commands;
  3. using Content.Server.Administration.Components;
  4. using Content.Server.Atmos.Components;
  5. using Content.Server.Atmos.EntitySystems;
  6. using Content.Server.Body.Components;
  7. using Content.Server.Body.Systems;
  8. using Content.Server.Electrocution;
  9. using Content.Server.Explosion.EntitySystems;
  10. using Content.Server.GhostKick;
  11. using Content.Server.Medical;
  12. using Content.Server.Nutrition.EntitySystems;
  13. using Content.Server.Pointing.Components;
  14. using Content.Server.Polymorph.Systems;
  15. using Content.Server.Popups;
  16. using Content.Server.Speech.Components;
  17. using Content.Server.Storage.Components;
  18. using Content.Server.Storage.EntitySystems;
  19. using Content.Server.Tabletop;
  20. using Content.Server.Tabletop.Components;
  21. using Content.Shared.Administration;
  22. using Content.Shared.Administration.Components;
  23. using Content.Shared.Body.Components;
  24. using Content.Shared.Body.Part;
  25. using Content.Shared.Clumsy;
  26. using Content.Shared.Clothing.Components;
  27. using Content.Shared.Cluwne;
  28. using Content.Shared.Damage;
  29. using Content.Shared.Damage.Systems;
  30. using Content.Shared.Database;
  31. using Content.Shared.Electrocution;
  32. using Content.Shared.Interaction.Components;
  33. using Content.Shared.Inventory;
  34. using Content.Shared.Mobs;
  35. using Content.Shared.Mobs.Components;
  36. using Content.Shared.Mobs.Systems;
  37. using Content.Shared.Movement.Components;
  38. using Content.Shared.Movement.Systems;
  39. using Content.Shared.Nutrition.Components;
  40. using Content.Shared.Popups;
  41. using Content.Shared.Slippery;
  42. using Content.Shared.Tabletop.Components;
  43. using Content.Shared.Tools.Systems;
  44. using Content.Shared.Verbs;
  45. using Robust.Shared.Map;
  46. using Robust.Shared.Map.Components;
  47. using Robust.Shared.Physics;
  48. using Robust.Shared.Physics.Components;
  49. using Robust.Shared.Physics.Systems;
  50. using Robust.Shared.Player;
  51. using Robust.Shared.Random;
  52. using Robust.Shared.Utility;
  53. using Timer = Robust.Shared.Timing.Timer;
  54. namespace Content.Server.Administration.Systems;
  55. public sealed partial class AdminVerbSystem
  56. {
  57. [Dependency] private readonly IRobustRandom _random = default!;
  58. [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
  59. [Dependency] private readonly BodySystem _bodySystem = default!;
  60. [Dependency] private readonly CreamPieSystem _creamPieSystem = default!;
  61. [Dependency] private readonly ElectrocutionSystem _electrocutionSystem = default!;
  62. [Dependency] private readonly EntityStorageSystem _entityStorageSystem = default!;
  63. [Dependency] private readonly ExplosionSystem _explosionSystem = default!;
  64. [Dependency] private readonly FixtureSystem _fixtures = default!;
  65. [Dependency] private readonly FlammableSystem _flammableSystem = default!;
  66. [Dependency] private readonly GhostKickManager _ghostKickManager = default!;
  67. [Dependency] private readonly SharedGodmodeSystem _sharedGodmodeSystem = default!;
  68. [Dependency] private readonly InventorySystem _inventorySystem = default!;
  69. [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!;
  70. [Dependency] private readonly PolymorphSystem _polymorphSystem = default!;
  71. [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!;
  72. [Dependency] private readonly PopupSystem _popupSystem = default!;
  73. [Dependency] private readonly SharedPhysicsSystem _physics = default!;
  74. [Dependency] private readonly TabletopSystem _tabletopSystem = default!;
  75. [Dependency] private readonly VomitSystem _vomitSystem = default!;
  76. [Dependency] private readonly WeldableSystem _weldableSystem = default!;
  77. [Dependency] private readonly SharedContentEyeSystem _eyeSystem = default!;
  78. [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
  79. [Dependency] private readonly SuperBonkSystem _superBonkSystem = default!;
  80. [Dependency] private readonly SlipperySystem _slipperySystem = default!;
  81. // All smite verbs have names so invokeverb works.
  82. private void AddSmiteVerbs(GetVerbsEvent<Verb> args)
  83. {
  84. if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
  85. return;
  86. var player = actor.PlayerSession;
  87. if (!_adminManager.HasAdminFlag(player, AdminFlags.Fun))
  88. return;
  89. // 1984.
  90. if (HasComp<MapComponent>(args.Target) || HasComp<MapGridComponent>(args.Target))
  91. return;
  92. var explodeName = Loc.GetString("admin-smite-explode-name").ToLowerInvariant();
  93. Verb explode = new()
  94. {
  95. Text = explodeName,
  96. Category = VerbCategory.Smite,
  97. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")),
  98. Act = () =>
  99. {
  100. var coords = _transformSystem.GetMapCoordinates(args.Target);
  101. Timer.Spawn(_gameTiming.TickPeriod,
  102. () => _explosionSystem.QueueExplosion(coords, ExplosionSystem.DefaultExplosionPrototypeId,
  103. 4, 1, 2, args.Target, maxTileBreak: 0), // it gibs, damage doesn't need to be high.
  104. CancellationToken.None);
  105. _bodySystem.GibBody(args.Target);
  106. },
  107. Impact = LogImpact.Extreme,
  108. Message = string.Join(": ", explodeName, Loc.GetString("admin-smite-explode-description")) // we do this so the description tells admins the Text to run it via console.
  109. };
  110. args.Verbs.Add(explode);
  111. var chessName = Loc.GetString("admin-smite-chess-dimension-name").ToLowerInvariant();
  112. Verb chess = new()
  113. {
  114. Text = chessName,
  115. Category = VerbCategory.Smite,
  116. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/Tabletop/chessboard.rsi"), "chessboard"),
  117. Act = () =>
  118. {
  119. _sharedGodmodeSystem.EnableGodmode(args.Target); // So they don't suffocate.
  120. EnsureComp<TabletopDraggableComponent>(args.Target);
  121. RemComp<PhysicsComponent>(args.Target); // So they can be dragged around.
  122. var xform = Transform(args.Target);
  123. _popupSystem.PopupEntity(Loc.GetString("admin-smite-chess-self"), args.Target,
  124. args.Target, PopupType.LargeCaution);
  125. _popupSystem.PopupCoordinates(
  126. Loc.GetString("admin-smite-chess-others", ("name", args.Target)), xform.Coordinates,
  127. Filter.PvsExcept(args.Target), true, PopupType.MediumCaution);
  128. var board = Spawn("ChessBoard", xform.Coordinates);
  129. var session = _tabletopSystem.EnsureSession(Comp<TabletopGameComponent>(board));
  130. xform.Coordinates = _transformSystem.ToCoordinates(session.Position);
  131. _transformSystem.SetWorldRotationNoLerp((args.Target, xform), Angle.Zero);
  132. },
  133. Impact = LogImpact.Extreme,
  134. Message = string.Join(": ", chessName, Loc.GetString("admin-smite-chess-dimension-description"))
  135. };
  136. args.Verbs.Add(chess);
  137. if (TryComp<FlammableComponent>(args.Target, out var flammable))
  138. {
  139. var flamesName = Loc.GetString("admin-smite-set-alight-name").ToLowerInvariant();
  140. Verb flames = new()
  141. {
  142. Text = flamesName,
  143. Category = VerbCategory.Smite,
  144. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/Alerts/Fire/fire.png")),
  145. Act = () =>
  146. {
  147. // Fuck you. Burn Forever.
  148. flammable.FireStacks = flammable.MaximumFireStacks;
  149. _flammableSystem.Ignite(args.Target, args.User);
  150. var xform = Transform(args.Target);
  151. _popupSystem.PopupEntity(Loc.GetString("admin-smite-set-alight-self"), args.Target,
  152. args.Target, PopupType.LargeCaution);
  153. _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-set-alight-others", ("name", args.Target)), xform.Coordinates,
  154. Filter.PvsExcept(args.Target), true, PopupType.MediumCaution);
  155. },
  156. Impact = LogImpact.Extreme,
  157. Message = string.Join(": ", flamesName, Loc.GetString("admin-smite-set-alight-description"))
  158. };
  159. args.Verbs.Add(flames);
  160. }
  161. var monkeyName = Loc.GetString("admin-smite-monkeyify-name").ToLowerInvariant();
  162. Verb monkey = new()
  163. {
  164. Text = monkeyName,
  165. Category = VerbCategory.Smite,
  166. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Animals/monkey.rsi"), "monkey"),
  167. Act = () =>
  168. {
  169. _polymorphSystem.PolymorphEntity(args.Target, "AdminMonkeySmite");
  170. },
  171. Impact = LogImpact.Extreme,
  172. Message = string.Join(": ", monkeyName, Loc.GetString("admin-smite-monkeyify-description"))
  173. };
  174. args.Verbs.Add(monkey);
  175. var disposalBinName = Loc.GetString("admin-smite-garbage-can-name").ToLowerInvariant();
  176. Verb disposalBin = new()
  177. {
  178. Text = disposalBinName,
  179. Category = VerbCategory.Smite,
  180. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Structures/Piping/disposal.rsi"), "disposal"),
  181. Act = () =>
  182. {
  183. _polymorphSystem.PolymorphEntity(args.Target, "AdminDisposalsSmite");
  184. },
  185. Impact = LogImpact.Extreme,
  186. Message = string.Join(": ", disposalBinName, Loc.GetString("admin-smite-garbage-can-description"))
  187. };
  188. args.Verbs.Add(disposalBin);
  189. if (TryComp<DamageableComponent>(args.Target, out var damageable) &&
  190. HasComp<MobStateComponent>(args.Target))
  191. {
  192. var hardElectrocuteName = Loc.GetString("admin-smite-electrocute-name").ToLowerInvariant();
  193. Verb hardElectrocute = new()
  194. {
  195. Text = hardElectrocuteName,
  196. Category = VerbCategory.Smite,
  197. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Hands/Gloves/Color/yellow.rsi"), "icon"),
  198. Act = () =>
  199. {
  200. int damageToDeal;
  201. if (!_mobThresholdSystem.TryGetThresholdForState(args.Target, MobState.Critical, out var criticalThreshold)) {
  202. // We can't crit them so try killing them.
  203. if (!_mobThresholdSystem.TryGetThresholdForState(args.Target, MobState.Dead,
  204. out var deadThreshold))
  205. return;// whelp.
  206. damageToDeal = deadThreshold.Value.Int() - (int) damageable.TotalDamage;
  207. }
  208. else
  209. {
  210. damageToDeal = criticalThreshold.Value.Int() - (int) damageable.TotalDamage;
  211. }
  212. if (damageToDeal <= 0)
  213. damageToDeal = 100; // murder time.
  214. if (_inventorySystem.TryGetSlots(args.Target, out var slotDefinitions))
  215. {
  216. foreach (var slot in slotDefinitions)
  217. {
  218. if (!_inventorySystem.TryGetSlotEntity(args.Target, slot.Name, out var slotEnt))
  219. continue;
  220. RemComp<InsulatedComponent>(slotEnt.Value); // Fry the gloves.
  221. }
  222. }
  223. _electrocutionSystem.TryDoElectrocution(args.Target, null, damageToDeal,
  224. TimeSpan.FromSeconds(30), refresh: true, ignoreInsulation: true);
  225. },
  226. Impact = LogImpact.Extreme,
  227. Message = string.Join(": ", hardElectrocuteName, Loc.GetString("admin-smite-electrocute-description"))
  228. };
  229. args.Verbs.Add(hardElectrocute);
  230. }
  231. if (TryComp<CreamPiedComponent>(args.Target, out var creamPied))
  232. {
  233. var creamPieName = Loc.GetString("admin-smite-creampie-name").ToLowerInvariant();
  234. Verb creamPie = new()
  235. {
  236. Text = creamPieName,
  237. Category = VerbCategory.Smite,
  238. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Consumable/Food/Baked/pie.rsi"), "plain-slice"),
  239. Act = () =>
  240. {
  241. _creamPieSystem.SetCreamPied(args.Target, creamPied, true);
  242. },
  243. Impact = LogImpact.Extreme,
  244. Message = string.Join(": ", creamPieName, Loc.GetString("admin-smite-creampie-description"))
  245. };
  246. args.Verbs.Add(creamPie);
  247. }
  248. if (TryComp<BloodstreamComponent>(args.Target, out var bloodstream))
  249. {
  250. var bloodRemovalName = Loc.GetString("admin-smite-remove-blood-name").ToLowerInvariant();
  251. Verb bloodRemoval = new()
  252. {
  253. Text = bloodRemovalName,
  254. Category = VerbCategory.Smite,
  255. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Fluids/tomato_splat.rsi"), "puddle-1"),
  256. Act = () =>
  257. {
  258. _bloodstreamSystem.SpillAllSolutions(args.Target, bloodstream);
  259. var xform = Transform(args.Target);
  260. _popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-blood-self"), args.Target,
  261. args.Target, PopupType.LargeCaution);
  262. _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-remove-blood-others", ("name", args.Target)), xform.Coordinates,
  263. Filter.PvsExcept(args.Target), true, PopupType.MediumCaution);
  264. },
  265. Impact = LogImpact.Extreme,
  266. Message = string.Join(": ", bloodRemovalName, Loc.GetString("admin-smite-remove-blood-description"))
  267. };
  268. args.Verbs.Add(bloodRemoval);
  269. }
  270. // bobby...
  271. if (TryComp<BodyComponent>(args.Target, out var body))
  272. {
  273. var vomitOrgansName = Loc.GetString("admin-smite-vomit-organs-name").ToLowerInvariant();
  274. Verb vomitOrgans = new()
  275. {
  276. Text = vomitOrgansName,
  277. Category = VerbCategory.Smite,
  278. Icon = new SpriteSpecifier.Rsi(new("/Textures/Fluids/vomit_toxin.rsi"), "vomit_toxin-1"),
  279. Act = () =>
  280. {
  281. _vomitSystem.Vomit(args.Target, -1000, -1000); // You feel hollow!
  282. var organs = _bodySystem.GetBodyOrganEntityComps<TransformComponent>((args.Target, body));
  283. var baseXform = Transform(args.Target);
  284. foreach (var organ in organs)
  285. {
  286. if (HasComp<BrainComponent>(organ.Owner) || HasComp<EyeComponent>(organ.Owner))
  287. continue;
  288. _transformSystem.PlaceNextTo((organ.Owner, organ.Comp1), (args.Target, baseXform));
  289. }
  290. _popupSystem.PopupEntity(Loc.GetString("admin-smite-vomit-organs-self"), args.Target,
  291. args.Target, PopupType.LargeCaution);
  292. _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-vomit-organs-others", ("name", args.Target)), baseXform.Coordinates,
  293. Filter.PvsExcept(args.Target), true, PopupType.MediumCaution);
  294. },
  295. Impact = LogImpact.Extreme,
  296. Message = string.Join(": ", vomitOrgansName, Loc.GetString("admin-smite-vomit-organs-description"))
  297. };
  298. args.Verbs.Add(vomitOrgans);
  299. var handsRemovalName = Loc.GetString("admin-smite-remove-hands-name").ToLowerInvariant();
  300. Verb handsRemoval = new()
  301. {
  302. Text = handsRemovalName,
  303. Category = VerbCategory.Smite,
  304. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/remove-hands.png")),
  305. Act = () =>
  306. {
  307. var baseXform = Transform(args.Target);
  308. foreach (var part in _bodySystem.GetBodyChildrenOfType(args.Target, BodyPartType.Hand))
  309. {
  310. _transformSystem.AttachToGridOrMap(part.Id);
  311. }
  312. _popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-hands-self"), args.Target,
  313. args.Target, PopupType.LargeCaution);
  314. _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-remove-hands-other", ("name", args.Target)), baseXform.Coordinates,
  315. Filter.PvsExcept(args.Target), true, PopupType.Medium);
  316. },
  317. Impact = LogImpact.Extreme,
  318. Message = string.Join(": ", handsRemovalName, Loc.GetString("admin-smite-remove-hands-description"))
  319. };
  320. args.Verbs.Add(handsRemoval);
  321. var handRemovalName = Loc.GetString("admin-smite-remove-hand-name").ToLowerInvariant();
  322. Verb handRemoval = new()
  323. {
  324. Text = handRemovalName,
  325. Category = VerbCategory.Smite,
  326. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/remove-hand.png")),
  327. Act = () =>
  328. {
  329. var baseXform = Transform(args.Target);
  330. foreach (var part in _bodySystem.GetBodyChildrenOfType(args.Target, BodyPartType.Hand, body))
  331. {
  332. _transformSystem.AttachToGridOrMap(part.Id);
  333. break;
  334. }
  335. _popupSystem.PopupEntity(Loc.GetString("admin-smite-remove-hands-self"), args.Target,
  336. args.Target, PopupType.LargeCaution);
  337. _popupSystem.PopupCoordinates(Loc.GetString("admin-smite-remove-hands-other", ("name", args.Target)), baseXform.Coordinates,
  338. Filter.PvsExcept(args.Target), true, PopupType.Medium);
  339. },
  340. Impact = LogImpact.Extreme,
  341. Message = string.Join(": ", handRemovalName, Loc.GetString("admin-smite-remove-hand-description"))
  342. };
  343. args.Verbs.Add(handRemoval);
  344. var stomachRemovalName = Loc.GetString("admin-smite-stomach-removal-name").ToLowerInvariant();
  345. Verb stomachRemoval = new()
  346. {
  347. Text = stomachRemovalName,
  348. Category = VerbCategory.Smite,
  349. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Species/Human/organs.rsi"), "stomach"),
  350. Act = () =>
  351. {
  352. foreach (var entity in _bodySystem.GetBodyOrganEntityComps<StomachComponent>((args.Target, body)))
  353. {
  354. QueueDel(entity.Owner);
  355. }
  356. _popupSystem.PopupEntity(Loc.GetString("admin-smite-stomach-removal-self"), args.Target,
  357. args.Target, PopupType.LargeCaution);
  358. },
  359. Impact = LogImpact.Extreme,
  360. Message = string.Join(": ", stomachRemovalName, Loc.GetString("admin-smite-stomach-removal-description"))
  361. };
  362. args.Verbs.Add(stomachRemoval);
  363. var lungRemovalName = Loc.GetString("admin-smite-lung-removal-name").ToLowerInvariant();
  364. Verb lungRemoval = new()
  365. {
  366. Text = lungRemovalName,
  367. Category = VerbCategory.Smite,
  368. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Species/Human/organs.rsi"), "lung-r"),
  369. Act = () =>
  370. {
  371. foreach (var entity in _bodySystem.GetBodyOrganEntityComps<LungComponent>((args.Target, body)))
  372. {
  373. QueueDel(entity.Owner);
  374. }
  375. _popupSystem.PopupEntity(Loc.GetString("admin-smite-lung-removal-self"), args.Target,
  376. args.Target, PopupType.LargeCaution);
  377. },
  378. Impact = LogImpact.Extreme,
  379. Message = string.Join(": ", lungRemovalName, Loc.GetString("admin-smite-lung-removal-description"))
  380. };
  381. args.Verbs.Add(lungRemoval);
  382. }
  383. if (TryComp<PhysicsComponent>(args.Target, out var physics))
  384. {
  385. var pinballName = Loc.GetString("admin-smite-pinball-name").ToLowerInvariant();
  386. Verb pinball = new()
  387. {
  388. Text = pinballName,
  389. Category = VerbCategory.Smite,
  390. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/toys.rsi"), "basketball"),
  391. Act = () =>
  392. {
  393. var xform = Transform(args.Target);
  394. var fixtures = Comp<FixturesComponent>(args.Target);
  395. xform.Anchored = false; // Just in case.
  396. _physics.SetBodyType(args.Target, BodyType.Dynamic, manager: fixtures, body: physics);
  397. _physics.SetBodyStatus(args.Target, physics, BodyStatus.InAir);
  398. _physics.WakeBody(args.Target, manager: fixtures, body: physics);
  399. foreach (var fixture in fixtures.Fixtures.Values)
  400. {
  401. if (!fixture.Hard)
  402. continue;
  403. _physics.SetRestitution(args.Target, fixture, 1.1f, false, fixtures);
  404. }
  405. _fixtures.FixtureUpdate(args.Target, manager: fixtures, body: physics);
  406. _physics.SetLinearVelocity(args.Target, _random.NextVector2(1.5f, 1.5f), manager: fixtures, body: physics);
  407. _physics.SetAngularVelocity(args.Target, MathF.PI * 12, manager: fixtures, body: physics);
  408. _physics.SetLinearDamping(args.Target, physics, 0f);
  409. _physics.SetAngularDamping(args.Target, physics, 0f);
  410. },
  411. Impact = LogImpact.Extreme,
  412. Message = string.Join(": ", pinballName, Loc.GetString("admin-smite-pinball-description"))
  413. };
  414. args.Verbs.Add(pinball);
  415. var yeetName = Loc.GetString("admin-smite-yeet-name").ToLowerInvariant();
  416. Verb yeet = new()
  417. {
  418. Text = yeetName,
  419. Category = VerbCategory.Smite,
  420. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/eject.svg.192dpi.png")),
  421. Act = () =>
  422. {
  423. var xform = Transform(args.Target);
  424. var fixtures = Comp<FixturesComponent>(args.Target);
  425. xform.Anchored = false; // Just in case.
  426. _physics.SetBodyType(args.Target, BodyType.Dynamic, body: physics);
  427. _physics.SetBodyStatus(args.Target, physics, BodyStatus.InAir);
  428. _physics.WakeBody(args.Target, manager: fixtures, body: physics);
  429. foreach (var fixture in fixtures.Fixtures.Values)
  430. {
  431. _physics.SetHard(args.Target, fixture, false, manager: fixtures);
  432. }
  433. _physics.SetLinearVelocity(args.Target, _random.NextVector2(8.0f, 8.0f), manager: fixtures, body: physics);
  434. _physics.SetAngularVelocity(args.Target, MathF.PI * 12, manager: fixtures, body: physics);
  435. _physics.SetLinearDamping(args.Target, physics, 0f);
  436. _physics.SetAngularDamping(args.Target, physics, 0f);
  437. },
  438. Impact = LogImpact.Extreme,
  439. Message = string.Join(": ", yeetName, Loc.GetString("admin-smite-yeet-description"))
  440. };
  441. args.Verbs.Add(yeet);
  442. }
  443. var breadName = Loc.GetString("admin-smite-become-bread-name").ToLowerInvariant(); // Will I get cancelled for breadName-ing you?
  444. Verb bread = new()
  445. {
  446. Text = breadName,
  447. Category = VerbCategory.Smite,
  448. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Consumable/Food/Baked/bread.rsi"), "plain"),
  449. Act = () =>
  450. {
  451. _polymorphSystem.PolymorphEntity(args.Target, "AdminBreadSmite");
  452. },
  453. Impact = LogImpact.Extreme,
  454. Message = string.Join(": ", breadName, Loc.GetString("admin-smite-become-bread-description"))
  455. };
  456. args.Verbs.Add(bread);
  457. var mouseName = Loc.GetString("admin-smite-become-mouse-name").ToLowerInvariant();
  458. Verb mouse = new()
  459. {
  460. Text = mouseName,
  461. Category = VerbCategory.Smite,
  462. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Mobs/Animals/mouse.rsi"), "icon-0"),
  463. Act = () =>
  464. {
  465. _polymorphSystem.PolymorphEntity(args.Target, "AdminMouseSmite");
  466. },
  467. Impact = LogImpact.Extreme,
  468. Message = string.Join(": ", mouseName, Loc.GetString("admin-smite-become-mouse-description"))
  469. };
  470. args.Verbs.Add(mouse);
  471. if (TryComp<ActorComponent>(args.Target, out var actorComponent))
  472. {
  473. var ghostKickName = Loc.GetString("admin-smite-ghostkick-name").ToLowerInvariant();
  474. Verb ghostKick = new()
  475. {
  476. Text = ghostKickName,
  477. Category = VerbCategory.Smite,
  478. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/gavel.svg.192dpi.png")),
  479. Act = () =>
  480. {
  481. _ghostKickManager.DoDisconnect(actorComponent.PlayerSession.Channel, "Smitten.");
  482. },
  483. Impact = LogImpact.Extreme,
  484. Message = string.Join(": ", ghostKickName, Loc.GetString("admin-smite-ghostkick-description"))
  485. };
  486. args.Verbs.Add(ghostKick);
  487. }
  488. if (TryComp<InventoryComponent>(args.Target, out var inventory))
  489. {
  490. var nyanifyName = Loc.GetString("admin-smite-nyanify-name").ToLowerInvariant();
  491. Verb nyanify = new()
  492. {
  493. Text = nyanifyName,
  494. Category = VerbCategory.Smite,
  495. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Head/Hats/catears.rsi"), "icon"),
  496. Act = () =>
  497. {
  498. var ears = Spawn("ClothingHeadHatCatEars", Transform(args.Target).Coordinates);
  499. EnsureComp<UnremoveableComponent>(ears);
  500. _inventorySystem.TryUnequip(args.Target, "head", true, true, false, inventory);
  501. _inventorySystem.TryEquip(args.Target, ears, "head", true, true, false, inventory);
  502. },
  503. Impact = LogImpact.Extreme,
  504. Message = string.Join(": ", nyanifyName, Loc.GetString("admin-smite-nyanify-description"))
  505. };
  506. args.Verbs.Add(nyanify);
  507. var killSignName = Loc.GetString("admin-smite-kill-sign-name").ToLowerInvariant();
  508. Verb killSign = new()
  509. {
  510. Text = killSignName,
  511. Category = VerbCategory.Smite,
  512. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Misc/killsign.rsi"), "icon"),
  513. Act = () =>
  514. {
  515. EnsureComp<KillSignComponent>(args.Target);
  516. },
  517. Impact = LogImpact.Extreme,
  518. Message = string.Join(": ", killSignName, Loc.GetString("admin-smite-kill-sign-description"))
  519. };
  520. args.Verbs.Add(killSign);
  521. var cluwneName = Loc.GetString("admin-smite-cluwne-name").ToLowerInvariant();
  522. Verb cluwne = new()
  523. {
  524. Text = cluwneName,
  525. Category = VerbCategory.Smite,
  526. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Mask/cluwne.rsi"), "icon"),
  527. Act = () =>
  528. {
  529. EnsureComp<CluwneComponent>(args.Target);
  530. },
  531. Impact = LogImpact.Extreme,
  532. Message = string.Join(": ", cluwneName, Loc.GetString("admin-smite-cluwne-description"))
  533. };
  534. args.Verbs.Add(cluwne);
  535. var maidenName = Loc.GetString("admin-smite-maid-name").ToLowerInvariant();
  536. Verb maiden = new()
  537. {
  538. Text = maidenName,
  539. Category = VerbCategory.Smite,
  540. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Clothing/Uniforms/Jumpskirt/janimaid.rsi"), "icon"),
  541. Act = () =>
  542. {
  543. SetOutfitCommand.SetOutfit(args.Target, "JanitorMaidGear", EntityManager, (_, clothing) =>
  544. {
  545. if (HasComp<ClothingComponent>(clothing))
  546. EnsureComp<UnremoveableComponent>(clothing);
  547. EnsureComp<ClumsyComponent>(args.Target);
  548. });
  549. },
  550. Impact = LogImpact.Extreme,
  551. Message = string.Join(": ", maidenName, Loc.GetString("admin-smite-maid-description"))
  552. };
  553. args.Verbs.Add(maiden);
  554. }
  555. var angerPointingArrowsName = Loc.GetString("admin-smite-anger-pointing-arrows-name").ToLowerInvariant();
  556. Verb angerPointingArrows = new()
  557. {
  558. Text = angerPointingArrowsName,
  559. Category = VerbCategory.Smite,
  560. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Interface/Misc/pointing.rsi"), "pointing"),
  561. Act = () =>
  562. {
  563. EnsureComp<PointingArrowAngeringComponent>(args.Target);
  564. },
  565. Impact = LogImpact.Extreme,
  566. Message = string.Join(": ", angerPointingArrowsName, Loc.GetString("admin-smite-anger-pointing-arrows-description"))
  567. };
  568. args.Verbs.Add(angerPointingArrows);
  569. var dustName = Loc.GetString("admin-smite-dust-name").ToLowerInvariant();
  570. Verb dust = new()
  571. {
  572. Text = dustName,
  573. Category = VerbCategory.Smite,
  574. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Materials/materials.rsi"), "ash"),
  575. Act = () =>
  576. {
  577. EntityManager.QueueDeleteEntity(args.Target);
  578. Spawn("Ash", Transform(args.Target).Coordinates);
  579. _popupSystem.PopupEntity(Loc.GetString("admin-smite-turned-ash-other", ("name", args.Target)), args.Target, PopupType.LargeCaution);
  580. },
  581. Impact = LogImpact.Extreme,
  582. Message = string.Join(": ", dustName, Loc.GetString("admin-smite-dust-description"))
  583. };
  584. args.Verbs.Add(dust);
  585. var youtubeVideoSimulationName = Loc.GetString("admin-smite-buffering-name").ToLowerInvariant();
  586. Verb youtubeVideoSimulation = new()
  587. {
  588. Text = youtubeVideoSimulationName,
  589. Category = VerbCategory.Smite,
  590. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/Misc/buffering_smite_icon.png")),
  591. Act = () =>
  592. {
  593. EnsureComp<BufferingComponent>(args.Target);
  594. },
  595. Impact = LogImpact.Extreme,
  596. Message = string.Join(": ", youtubeVideoSimulationName, Loc.GetString("admin-smite-buffering-description"))
  597. };
  598. args.Verbs.Add(youtubeVideoSimulation);
  599. var instrumentationName = Loc.GetString("admin-smite-become-instrument-name").ToLowerInvariant();
  600. Verb instrumentation = new()
  601. {
  602. Text = instrumentationName,
  603. Category = VerbCategory.Smite,
  604. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/Instruments/h_synthesizer.rsi"), "supersynth"),
  605. Act = () =>
  606. {
  607. _polymorphSystem.PolymorphEntity(args.Target, "AdminInstrumentSmite");
  608. },
  609. Impact = LogImpact.Extreme,
  610. Message = string.Join(": ", instrumentationName, Loc.GetString("admin-smite-become-instrument-description"))
  611. };
  612. args.Verbs.Add(instrumentation);
  613. var noGravityName = Loc.GetString("admin-smite-remove-gravity-name").ToLowerInvariant();
  614. Verb noGravity = new()
  615. {
  616. Text = noGravityName,
  617. Category = VerbCategory.Smite,
  618. Icon = new SpriteSpecifier.Rsi(new("/Textures/Structures/Machines/gravity_generator.rsi"), "off"),
  619. Act = () =>
  620. {
  621. var grav = EnsureComp<MovementIgnoreGravityComponent>(args.Target);
  622. grav.Weightless = true;
  623. Dirty(args.Target, grav);
  624. },
  625. Impact = LogImpact.Extreme,
  626. Message = string.Join(": ", noGravityName, Loc.GetString("admin-smite-remove-gravity-description"))
  627. };
  628. args.Verbs.Add(noGravity);
  629. var reptilianName = Loc.GetString("admin-smite-reptilian-species-swap-name").ToLowerInvariant();
  630. Verb reptilian = new()
  631. {
  632. Text = reptilianName,
  633. Category = VerbCategory.Smite,
  634. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Objects/Fun/toys.rsi"), "plushie_lizard"),
  635. Act = () =>
  636. {
  637. _polymorphSystem.PolymorphEntity(args.Target, "AdminLizardSmite");
  638. },
  639. Impact = LogImpact.Extreme,
  640. Message = string.Join(": ", reptilianName, Loc.GetString("admin-smite-reptilian-species-swap-description"))
  641. };
  642. args.Verbs.Add(reptilian);
  643. var lockerName = Loc.GetString("admin-smite-locker-stuff-name").ToLowerInvariant();
  644. Verb locker = new()
  645. {
  646. Text = lockerName,
  647. Category = VerbCategory.Smite,
  648. Icon = new SpriteSpecifier.Rsi(new ("/Textures/Structures/Storage/closet.rsi"), "generic"),
  649. Act = () =>
  650. {
  651. var xform = Transform(args.Target);
  652. var locker = Spawn("ClosetMaintenance", xform.Coordinates);
  653. if (TryComp<EntityStorageComponent>(locker, out var storage))
  654. {
  655. _entityStorageSystem.ToggleOpen(args.Target, locker, storage);
  656. _entityStorageSystem.Insert(args.Target, locker, storage);
  657. _entityStorageSystem.ToggleOpen(args.Target, locker, storage);
  658. }
  659. _weldableSystem.SetWeldedState(locker, true);
  660. },
  661. Impact = LogImpact.Extreme,
  662. Message = string.Join(": ", lockerName, Loc.GetString("admin-smite-locker-stuff-description"))
  663. };
  664. args.Verbs.Add(locker);
  665. var headstandName = Loc.GetString("admin-smite-headstand-name").ToLowerInvariant();
  666. Verb headstand = new()
  667. {
  668. Text = headstandName,
  669. Category = VerbCategory.Smite,
  670. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/refresh.svg.192dpi.png")),
  671. Act = () =>
  672. {
  673. EnsureComp<HeadstandComponent>(args.Target);
  674. },
  675. Impact = LogImpact.Extreme,
  676. Message = string.Join(": ", headstandName, Loc.GetString("admin-smite-headstand-description"))
  677. };
  678. args.Verbs.Add(headstand);
  679. var zoomInName = Loc.GetString("admin-smite-zoom-in-name").ToLowerInvariant();
  680. Verb zoomIn = new()
  681. {
  682. Text = zoomInName,
  683. Category = VerbCategory.Smite,
  684. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/zoom.png")),
  685. Act = () =>
  686. {
  687. var eye = EnsureComp<ContentEyeComponent>(args.Target);
  688. _eyeSystem.SetZoom(args.Target, eye.TargetZoom * 0.2f, ignoreLimits: true);
  689. },
  690. Impact = LogImpact.Extreme,
  691. Message = string.Join(": ", zoomInName, Loc.GetString("admin-smite-zoom-in-description"))
  692. };
  693. args.Verbs.Add(zoomIn);
  694. var flipEyeName = Loc.GetString("admin-smite-flip-eye-name").ToLowerInvariant();
  695. Verb flipEye = new()
  696. {
  697. Text = flipEyeName,
  698. Category = VerbCategory.Smite,
  699. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/flip.png")),
  700. Act = () =>
  701. {
  702. var eye = EnsureComp<ContentEyeComponent>(args.Target);
  703. _eyeSystem.SetZoom(args.Target, eye.TargetZoom * -1, ignoreLimits: true);
  704. },
  705. Impact = LogImpact.Extreme,
  706. Message = string.Join(": ", flipEyeName, Loc.GetString("admin-smite-flip-eye-description"))
  707. };
  708. args.Verbs.Add(flipEye);
  709. var runWalkSwapName = Loc.GetString("admin-smite-run-walk-swap-name").ToLowerInvariant();
  710. Verb runWalkSwap = new()
  711. {
  712. Text = runWalkSwapName,
  713. Category = VerbCategory.Smite,
  714. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/run-walk-swap.png")),
  715. Act = () =>
  716. {
  717. var movementSpeed = EnsureComp<MovementSpeedModifierComponent>(args.Target);
  718. (movementSpeed.BaseSprintSpeed, movementSpeed.BaseWalkSpeed) = (movementSpeed.BaseWalkSpeed, movementSpeed.BaseSprintSpeed);
  719. Dirty(args.Target, movementSpeed);
  720. _popupSystem.PopupEntity(Loc.GetString("admin-smite-run-walk-swap-prompt"), args.Target,
  721. args.Target, PopupType.LargeCaution);
  722. },
  723. Impact = LogImpact.Extreme,
  724. Message = string.Join(": ", runWalkSwapName, Loc.GetString("admin-smite-run-walk-swap-description"))
  725. };
  726. args.Verbs.Add(runWalkSwap);
  727. var backwardsAccentName = Loc.GetString("admin-smite-speak-backwards-name").ToLowerInvariant();
  728. Verb backwardsAccent = new()
  729. {
  730. Text = backwardsAccentName,
  731. Category = VerbCategory.Smite,
  732. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/help-backwards.png")),
  733. Act = () =>
  734. {
  735. EnsureComp<BackwardsAccentComponent>(args.Target);
  736. },
  737. Impact = LogImpact.Extreme,
  738. Message = string.Join(": ", backwardsAccentName, Loc.GetString("admin-smite-speak-backwards-description"))
  739. };
  740. args.Verbs.Add(backwardsAccent);
  741. var disarmProneName = Loc.GetString("admin-smite-disarm-prone-name").ToLowerInvariant();
  742. Verb disarmProne = new()
  743. {
  744. Text = disarmProneName,
  745. Category = VerbCategory.Smite,
  746. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/Actions/disarm.png")),
  747. Act = () =>
  748. {
  749. EnsureComp<DisarmProneComponent>(args.Target);
  750. },
  751. Impact = LogImpact.Extreme,
  752. Message = string.Join(": ", disarmProneName, Loc.GetString("admin-smite-disarm-prone-description"))
  753. };
  754. args.Verbs.Add(disarmProne);
  755. var superSpeedName = Loc.GetString("admin-smite-super-speed-name").ToLowerInvariant();
  756. Verb superSpeed = new()
  757. {
  758. Text = superSpeedName,
  759. Category = VerbCategory.Smite,
  760. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/AdminActions/super_speed.png")),
  761. Act = () =>
  762. {
  763. var movementSpeed = EnsureComp<MovementSpeedModifierComponent>(args.Target);
  764. _movementSpeedModifierSystem?.ChangeBaseSpeed(args.Target, 400, 8000, 40, movementSpeed);
  765. _popupSystem.PopupEntity(Loc.GetString("admin-smite-super-speed-prompt"), args.Target,
  766. args.Target, PopupType.LargeCaution);
  767. },
  768. Impact = LogImpact.Extreme,
  769. Message = string.Join(": ", superSpeedName, Loc.GetString("admin-smite-super-speed-description"))
  770. };
  771. args.Verbs.Add(superSpeed);
  772. //Bonk
  773. var superBonkLiteName = Loc.GetString("admin-smite-super-bonk-lite-name").ToLowerInvariant();
  774. Verb superBonkLite = new()
  775. {
  776. Text = superBonkLiteName,
  777. Category = VerbCategory.Smite,
  778. Icon = new SpriteSpecifier.Rsi(new("Structures/Furniture/Tables/glass.rsi"), "full"),
  779. Act = () =>
  780. {
  781. _superBonkSystem.StartSuperBonk(args.Target, stopWhenDead: true);
  782. },
  783. Impact = LogImpact.Extreme,
  784. Message = string.Join(": ", superBonkLiteName, Loc.GetString("admin-smite-super-bonk-lite-description"))
  785. };
  786. args.Verbs.Add(superBonkLite);
  787. var superBonkName = Loc.GetString("admin-smite-super-bonk-name").ToLowerInvariant();
  788. Verb superBonk = new()
  789. {
  790. Text = superBonkName,
  791. Category = VerbCategory.Smite,
  792. Icon = new SpriteSpecifier.Rsi(new("Structures/Furniture/Tables/generic.rsi"), "full"),
  793. Act = () =>
  794. {
  795. _superBonkSystem.StartSuperBonk(args.Target);
  796. },
  797. Impact = LogImpact.Extreme,
  798. Message = string.Join(": ", superBonkName, Loc.GetString("admin-smite-super-bonk-description"))
  799. };
  800. args.Verbs.Add(superBonk);
  801. var superslipName = Loc.GetString("admin-smite-super-slip-name").ToLowerInvariant();
  802. Verb superslip = new()
  803. {
  804. Text = superslipName,
  805. Category = VerbCategory.Smite,
  806. Icon = new SpriteSpecifier.Rsi(new("Objects/Specific/Janitorial/soap.rsi"), "omega-4"),
  807. Act = () =>
  808. {
  809. var hadSlipComponent = EnsureComp(args.Target, out SlipperyComponent slipComponent);
  810. if (!hadSlipComponent)
  811. {
  812. slipComponent.SuperSlippery = true;
  813. slipComponent.ParalyzeTime = 5;
  814. slipComponent.LaunchForwardsMultiplier = 20;
  815. }
  816. _slipperySystem.TrySlip(args.Target, slipComponent, args.Target, requiresContact: false);
  817. if (!hadSlipComponent)
  818. {
  819. RemComp(args.Target, slipComponent);
  820. }
  821. },
  822. Impact = LogImpact.Extreme,
  823. Message = string.Join(": ", superslipName, Loc.GetString("admin-smite-super-slip-description"))
  824. };
  825. args.Verbs.Add(superslip);
  826. var omniaccentName = Loc.GetString("admin-smite-omni-accent-name").ToLowerInvariant();
  827. Verb omniaccent = new()
  828. {
  829. Text = omniaccentName,
  830. Category = VerbCategory.Smite,
  831. Icon = new SpriteSpecifier.Rsi(new("Interface/Actions/voice-mask.rsi"), "icon"),
  832. Act = () =>
  833. {
  834. EnsureComp<BarkAccentComponent>(args.Target);
  835. EnsureComp<BleatingAccentComponent>(args.Target);
  836. EnsureComp<FrenchAccentComponent>(args.Target);
  837. EnsureComp<GermanAccentComponent>(args.Target);
  838. EnsureComp<LizardAccentComponent>(args.Target);
  839. EnsureComp<MobsterAccentComponent>(args.Target);
  840. EnsureComp<MothAccentComponent>(args.Target);
  841. EnsureComp<OwOAccentComponent>(args.Target);
  842. EnsureComp<SkeletonAccentComponent>(args.Target);
  843. EnsureComp<SouthernAccentComponent>(args.Target);
  844. EnsureComp<SpanishAccentComponent>(args.Target);
  845. EnsureComp<StutteringAccentComponent>(args.Target);
  846. if (_random.Next(0, 8) == 0)
  847. {
  848. EnsureComp<BackwardsAccentComponent>(args.Target); // was asked to make this at a low chance idk
  849. }
  850. },
  851. Impact = LogImpact.Extreme,
  852. Message = string.Join(": ", omniaccentName, Loc.GetString("admin-smite-omni-accent-description"))
  853. };
  854. args.Verbs.Add(omniaccent);
  855. }
  856. }