C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Oxide.Plugins {
[Info("Pets", "Nogrod/k1lly0u", "0.6.5"), Description("Gives players the ability to tame and have pets")]
class Pets : RustPlugin {
#region Fields
private static Pets ins;
private BUTTON Main;
private BUTTON Secondary;
private Dictionary<ulong, PetData> npcSaveList = new Dictionary<ulong, PetData>();
private enum Action {
Move, Attack, Eat, Drink, Follow, Sleep, Idle
}
#endregion
#region Oxide Hooks
private void OnServerInitialized() {
ins = this;
lang.RegisterMessages(Messages, this);
RegisterPermissions();
LoadData();
Main = ConvertToButton(configData.UserControl.Main);
Secondary = ConvertToButton(configData.UserControl.Secondary);
foreach (BasePlayer player in BasePlayer.activePlayerList) OnPlayerConnected(player);
}
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo) {
if (entity == null || hitInfo == null) return;
if (entity is BaseNpc) entity.GetComponent<NpcAI>()?.OnAttacked(hitInfo);
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo hitInfo) {
if (entity == null || hitInfo == null) return;
if (entity is BaseNpc) entity.GetComponent<NpcAI>()?.OnDeath();
}
private void OnPlayerConnected(BasePlayer player) {
if (player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
timer.Once(2f, () => OnPlayerConnected(player));
return;
}
PetData info;
if (!npcSaveList.TryGetValue(player.userID, out info) || !info.NeedToSpawn) return;
Puts("Loading pet...");
BaseEntity pet = InstantiateEntity(StringPool.Get(info.prefabID), new Vector3(info.x, info.y, info.z), new Quaternion());
if (pet == null) return;
NPCController controller = player.gameObject.AddComponent<NPCController>();
pet.enableSaving = false;
pet.Spawn();
controller.npcAi = pet.gameObject.AddComponent<NpcAI>();
controller.npcAi.owner = controller;
controller.npcAi.inventory.Load(ProtoBuf.ItemContainer.Deserialize(info.inventory));
info.NeedToSpawn = false;
}
private object OnNpcAttack(BaseNpc entity, BaseEntity target) {
BasePlayer player = target?.ToPlayer();
if (entity == null || player == null) return null;
return CanAnimalAttack(entity, player);
}
private object OnNpcTarget(BaseNpc entity, BaseEntity target) {
BasePlayer player = target?.ToPlayer();
if (entity == null || player == null) return null;
return CanAnimalAttack(entity, player);
}
private object CanNpcEat(BaseNpc entity, BaseEntity target) {
BasePlayer player = target?.ToPlayer();
if (entity == null || player == null) return null;
return CanAnimalAttack(entity, player);
}
private void OnServerSave() {
var pets = UnityEngine.Object.FindObjectsOfType<NpcAI>();
if (pets == null) return;
foreach (var pet in pets) npcSaveList[pet.owner.player.userID] = new PetData(pet);
SaveData();
}
private void Unload() {
OnServerSave();
DestroyAll<NPCController>();
DestroyAll<NpcAI>();
ins = null;
}
#endregion
#region Functions
private object CanAnimalAttack(BaseNpc entity, BasePlayer player) {
NpcAI npcAi = entity.GetComponent<NpcAI>();
if (npcAi != null && npcAi.owner.player == player) return false;
return null;
}
private object CanNPCEat(BaseNpc entity, BaseEntity target) {
NpcAI npcAi = entity.GetComponent<NpcAI>();
if (npcAi != null) return npcAi.action == Action.Eat;
return null;
}
private void RegisterPermissions() {
string[] names = new string[] {
"bear", "boar", "chicken", "horse", "polarbear", "stag", "wolf"
}
;
foreach (var name in names) permission.RegisterPermission($"pets.{name}", this);
}
private BUTTON ConvertToButton(string button) {
try {
return (BUTTON)Enum.Parse(typeof(BUTTON), button);
}
catch (Exception) {
return BUTTON.USE;
}
}
private void DestroyAll<T>() {
var objects = UnityEngine.Object.FindObjectsOfType(typeof(T));
if (objects == null) return;
foreach (var gameObj in objects) UnityEngine.Object.Destroy(gameObj);
}
private string FormatTime(double time) {
TimeSpan dateDifference = TimeSpan.FromSeconds((float)time);
var days = dateDifference.Days;
var hours = dateDifference.Hours;
hours += (days * 24);
var mins = dateDifference.Minutes;
var secs = dateDifference.Seconds;
return string.Format("{0:00}:{1:00}:{2:00}", hours, mins, secs);
}
private BaseEntity InstantiateEntity(string type, Vector3 position, Quaternion rotation) {
var gameObject = Facepunch.Instantiate.GameObject(GameManager.server.FindPrefab(type), position, rotation);
gameObject.name = type;
SceneManager.MoveGameObjectToScene(gameObject, Rust.Server.EntityScene);
UnityEngine.Object.Destroy(gameObject.GetComponent<Spawnable>());
if (!gameObject.activeSelf) gameObject.SetActive(true);
BaseEntity component = gameObject.GetComponent<BaseEntity>();
return component;
}
#endregion
#region Components
private class NPCController : MonoBehaviour {
public BasePlayer player;
public NpcAI npcAi;
private float nextPressTime = 0;
private float nextDrawTime = 0;
private float nextControlTime = 0;
private float lootDistance;
private float tameTimer;
private float lastTpTime;
private bool usePermissions;
internal bool drawEnabled;
private void Awake() {
enabled = false;
player = GetComponent<BasePlayer>();
drawEnabled = ins.configData.Options.UseDrawSystem;
tameTimer = ins.configData.Options.TameTimer;
lootDistance = ins.configData.Options.LootDistance;
usePermissions = ins.configData.Options.UsePermissions;
}
private void Update() {
if (player == null || player.IsDead()) return;
float time = Time.realtimeSinceStartup;
if (player.serverInput.WasJustPressed(ins.Main)) {
if (nextPressTime < time) {
nextPressTime = time + 0.2f;
UpdateAction();
}
}
else if (player.serverInput.WasJustPressed(ins.Secondary)) {
if (npcAi != null && nextPressTime < time) {
nextPressTime = time + 0.2f;
ChangeFollowAction();
}
}
if (drawEnabled && npcAi != null && npcAi.action < Action.Follow && nextDrawTime < time) {
nextDrawTime = time + 0.05f;
UpdateDraw();
}
}
private void UpdateDraw() {
var drawpos = (npcAi.action == Action.Move || npcAi.action == Action.Drink ? npcAi.targetPos : (npcAi.targetEnt == null ? Vector3.zero : npcAi.targetEnt.transform.position));
if (drawpos != Vector3.zero) {
bool tempAdmin = false;
if (!player.IsAdmin) {
tempAdmin = true;
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
player.SendNetworkUpdateImmediate();
}
player.SendConsoleCommand("ddraw.arrow", 0.05f + 0.02f, npcAi.action == Action.Move ? Color.cyan : npcAi.action == Action.Attack ? Color.red : Color.yellow, drawpos + new Vector3(0, 5f, 0), drawpos, 1.5f);
if (tempAdmin) player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
}
}
private void UpdateAction() {
RaycastHit hit;
if (Physics.SphereCast(player.eyes.position, 0.5f, Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward, out hit) || hit.transform == transform) {
if (npcAi == null) {
BaseNpc npcPet = hit.GetEntity()?.GetComponent<BaseNpc>();
if (npcPet == null) return;
if (hit.distance >= 10) {
UserMessage(player, "tooFar");
return;
}
TryGetNewPet(npcPet);
return;
}
if (hit.collider?.gameObject.layer == 4) {
if (npcAi.entity.Hydration.Level < 1) {
UserMessage(player, "isDrinking");
npcAi.targetPos = hit.point;
npcAi.action = Action.Drink;
}
else UserMessage(player, "notThirsty");
return;
}
BaseCombatEntity targetEnt = hit.GetEntity()?.GetComponent<BaseCombatEntity>();
if (targetEnt == null) {
npcAi.targetPos = hit.point;
npcAi.action = Action.Move;
return;
}
if (targetEnt == npcAi.entity) {
if (hit.distance <= lootDistance) OpenPetInventory();
}
else if (targetEnt is BaseCorpse) {
UserMessage(player, "isEating");
npcAi.entity.FoodTarget = targetEnt;
npcAi.Attack(targetEnt, Action.Eat);
}
else {
UserMessage(player, "isAttacking");
npcAi.Attack(targetEnt);
}
}
}
private void OpenPetInventory() {
player.inventory.loot.Clear();
player.inventory.loot.entitySource = npcAi.entity;
player.inventory.loot.itemSource = null;
player.inventory.loot.AddContainer(npcAi.inventory);
player.inventory.loot.SendImmediate();
player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", "generic");
player.SendNetworkUpdate();
UserMessage(player, "openInv");
}
private void ChangeFollowAction() {
if (npcAi == null) return;
if (!npcAi.stopFollow) {
UserMessage(player, "stopFollow");
npcAi.action = Action.Idle;
npcAi.stopFollow = true;
}
else {
UserMessage(player, "startFollow");
npcAi.Attack(player, Action.Follow);
npcAi.stopFollow = false;
}
}
internal void TeleportToPlayer() {
float currentTime = Time.realtimeSinceStartup;
if (currentTime < lastTpTime) {
UserMessage(player, "tpcooldown", new string[] {
ins.FormatTime(lastTpTime - currentTime)
}
);
return;
}
if (npcAi == null || npcAi.entity == null) {
UserMessage(player, "nopet");
return;
}
lastTpTime = currentTime + ins.configData.Options.TpCooldown;
npcAi.entity.transform.position = player.transform.position + (player.eyes.BodyForward() * 2);
npcAi.entity.SendNetworkUpdate();
}
private void TryGetNewPet(BaseNpc npcPet) {
NpcAI ownedAi = npcPet.GetComponent<NpcAI>();
if (ownedAi != null) {
if (ownedAi.owner != this) UserMessage(player, "isPet");
else UserMessage(player, "isYourPet");
return;
}
if (nextControlTime >= Time.realtimeSinceStartup) {
UserMessage(player, "tooFast");
return;
}
if (usePermissions && !ins.permission.UserHasPermission(player.UserIDString, $"pets.{npcPet.ShortPrefabName}")) {
UserMessage(player, "noPerms");
return;
}
nextControlTime = Time.realtimeSinceStartup + tameTimer;
npcAi = npcPet.gameObject.AddComponent<NpcAI>();
npcAi.owner = this;
UserMessage(player, "petSet");
}
}
private class NpcAI : MonoBehaviour {
internal Action action;
internal Vector3 targetPos = Vector3.zero;
internal BaseCombatEntity targetEnt;
internal bool stopFollow = false;
public NPCController owner;
public ItemContainer inventory;
public BaseNpc entity;
private double attackRange;
private float targetIgnoreDistance;
private float healthModifier;
private float speedModifier;
private float attackModifier;
private float nextMessageTime;
private void Awake() {
entity = GetComponent<BaseNpc>();
action = Action.Idle;
targetIgnoreDistance = ins.configData.Options.AttackDistance;
healthModifier = ins.configData.NPCMods.Health;
speedModifier = ins.configData.NPCMods.Speed;
attackModifier = ins.configData.NPCMods.Attack;
nextMessageTime = Time.realtimeSinceStartup;
inventory = new ItemContainer();
inventory.ServerInitialize(null, 6);
if ((int)inventory.uid == 0) inventory.GiveUID();
entity.InitializeHealth(entity.Health() * healthModifier, entity.MaxHealth() * healthModifier);
entity.AttackDamage *= attackModifier;
entity.Stats.TurnSpeed *= speedModifier;
entity.Stats.Speed *= speedModifier;
}
private void OnDestroy() {
DropUtil.DropItems(inventory, transform.position);
owner.npcAi = null;
if (entity.health <= 0) return;
entity.InitializeHealth(entity.Health() / healthModifier, entity.MaxHealth() / healthModifier);
entity.AttackDamage /= attackModifier;
entity.Stats.TurnSpeed /= speedModifier;
entity.Stats.Speed /= speedModifier;
entity.Kill();
}
internal void OnAttacked(HitInfo info) {
if (entity == null || entity.IsDead()) return;
if (info.Initiator.GetComponent<BaseCombatEntity>() && info.Initiator != owner.player && action != Action.Attack) Attack(info.Initiator.GetComponent<BaseCombatEntity>(), Action.Attack);
}
internal void OnDeath() {
if (owner != null) {
owner.enabled = false;
owner.npcAi = null;
UserMessage(owner.player, "ondeath");
Destroy(owner);
}
Destroy(this);
}
private void Update() {
if (entity.Sleep < 0.01f) {
SetBehaviour(BaseNpc.Behaviour.Sleep);
action = Action.Sleep;
float time = Time.realtimeSinceStartup;
if (owner.player.enabled && nextMessageTime < time) {
UserMessage(owner.player, "isTired");
nextMessageTime = time + 60f;
}
return;
}
if (entity.Energy.Level < 0.01f) {
var time = Time.realtimeSinceStartup;
if (owner.player.enabled && nextMessageTime < time) {
UserMessage(owner.player, "isHungry");
nextMessageTime = time + 60f;
}
}
if (action == Action.Idle || action == Action.Follow) {
SetBehaviour(BaseNpc.Behaviour.Idle);
if (stopFollow) StopMoving();
else {
if (owner != null) {
float distance = Vector3.Distance(transform.position, owner.transform.position);
if (distance > 3) UpdateDestination(owner.transform.position + (-owner.player.eyes.HeadForward() * 2), distance > 10);
else StopMoving();
}
}
return;
}
if (action == Action.Move) {
float distance = Vector3.Distance(transform.position, targetPos);
if (distance < 1) action = Action.Idle;
else {
SetBehaviour(BaseNpc.Behaviour.Wander);
UpdateDestination(targetPos, distance > 5);
}
}
else if (action == Action.Drink) {
if (entity.Hydration.Level >= 1) {
SetBehaviour(BaseNpc.Behaviour.Idle);
action = Action.Idle;
return;
}
float distance = Vector3.Distance(transform.position, targetPos);
if (distance < 1) {
SetBehaviour(BaseNpc.Behaviour.Eat);
entity.Hydration.Level += 0.005f;
entity.Hydration.Level = Mathf.Clamp01(entity.Hydration.Level);
}
else UpdateDestination(targetPos, distance > 5);
}
else if (action == Action.Sleep) {
StopMoving();
SetBehaviour(BaseNpc.Behaviour.Sleep);
entity.health += 0.003f;
entity.health = Mathf.Clamp(entity.health, 0, entity.MaxHealth());
entity.Sleep += 0.003f;
entity.Sleep = Mathf.Clamp01(entity.Sleep);
}
else {
if (targetEnt == null) {
if (!stopFollow) targetEnt = owner.player;
action = Action.Idle;
}
else {
float distance = Vector3.Distance(transform.position, targetEnt.transform.position);
if (distance > targetIgnoreDistance) {
action = Action.Idle;
SetBehaviour(BaseNpc.Behaviour.Idle);
return;
}
if ((action == Action.Eat || entity.Energy.Level < 0.25f) && targetEnt != owner.player) {
SetBehaviour(BaseNpc.Behaviour.Eat);
if (distance <= attackRange) {
entity.FoodTarget = targetEnt;
if (distance <= 2) entity.Eat();
}
else UpdateDestination(targetEnt.transform.position, distance > 5);
}
if (action == Action.Attack && targetEnt != owner.player && distance < targetIgnoreDistance) {
if (entity.AttackTarget != targetEnt) entity.AttackTarget = targetEnt;
SetBehaviour(BaseNpc.Behaviour.Attack);
if (distance <= entity.AttackRange) entity.StartAttack();
else UpdateDestination(targetEnt.transform.position, true);
}
}
}
}
private void UpdateDestination(Vector3 position, bool run) {
entity.UpdateDestination(position);
entity.TargetSpeed = run ? entity.Stats.Speed : entity.Stats.Speed * 0.3f;
}
private void StopMoving() {
entity.IsStopped = true;
entity.ChaseTransform = null;
entity.SetFact(BaseNpc.Facts.PathToTargetStatus, 0, true, true);
}
private void SetBehaviour(BaseNpc.Behaviour behaviour) {
if (entity.CurrentBehaviour != behaviour) entity.CurrentBehaviour = behaviour;
}
internal void Attack(BaseCombatEntity targetEnt, Action action = Action.Attack) {
if (targetEnt == null) return;
this.targetEnt = targetEnt;
this.action = action;
entity.AttackTarget = targetEnt;
}
}
#endregion
#region Commands
[ChatCommand("pet")]
private void pet(BasePlayer player, string command, string[] args) {
NPCController component = player.GetComponent<NPCController>() ?? player.gameObject.AddComponent<NPCController>();
if (args.Length == 0) {
component.enabled = !component.enabled;
UserMessage(player, component.enabled ? "isEnabled" : "isDisabled");
return;
}
if (args[0].ToLower() == "help") {
UserMessage(player, "help0", new string[] {
Title, Version.ToString()
}
);
UserMessage(player, "help1");
UserMessage(player, "help2");
UserMessage(player, "help3");
UserMessage(player, "help4");
UserMessage(player, "help5");
UserMessage(player, "help7");
UserMessage(player, "help6");
return;
}
if (args[0] == "draw") {
if (configData.Options.UseDrawSystem) {
component.drawEnabled = !component.drawEnabled;
UserMessage(player, component.drawEnabled ? "drawEnabled" : "drawDisabled");
}
else UserMessage(player, "noDdraw");
}
if (component.npcAi != null) {
switch (args[0].ToLower()) {
case "free" : UnityEngine.Object.Destroy(component.npcAi);
component.npcAi = null;
UserMessage(player, "hasReleased");
return;
case "sleep" : if (component.npcAi.action == Action.Sleep) {
component.npcAi.action = Action.Idle;
UserMessage(player, "awoken");
}
else {
component.npcAi.action = Action.Sleep;
UserMessage(player, "sleeping");
}
return;
case "come" : component.TeleportToPlayer();
return;
case "info" : UserMessage(player, "statistics", new string[] {
Math.Round(component.npcAi.entity.health, 2).ToString(), Math.Round(component.npcAi.entity.Energy.Level * 100, 2).ToString(), Math.Round(component.npcAi.entity.Hydration.Level * 100, 2).ToString(), Math.Round(component.npcAi.entity.Stamina.Level * 100, 2).ToString(), Math.Round(component.npcAi.entity.Sleep * 100, 2).ToString()
}
);
return;
default : break;
}
}
else UserMessage(player, "nopet");
}
#endregion
#region Config
private ConfigData configData;
class ConfigData {
[JsonProperty(PropertyName = "Pet statistic modifiers")]
public Modifiers NPCMods {
get;
set;
}
[JsonProperty(PropertyName = "Control buttons")]
public Controls UserControl {
get;
set;
}
public OtherOptions Options {
get;
set;
}
public class Modifiers {
[JsonProperty(PropertyName = "Attack damage")]
public float Attack {
get;
set;
}
public float Health {
get;
set;
}
public float Speed {
get;
set;
}
}
public class Controls {
[JsonProperty(PropertyName = "Npc command control button")]
public string Main {
get;
set;
}
[JsonProperty(PropertyName = "Follow player toggle button")]
public string Secondary {
get;
set;
}
}
public class OtherOptions {
[JsonProperty(PropertyName = "Maximum distance to tame an pet")]
public float TameDistance {
get;
set;
}
[JsonProperty(PropertyName = "Teleport to player cooldown (seconds)")]
public int TpCooldown {
get;
set;
}
[JsonProperty(PropertyName = "Time between taming pets")]
public float TameTimer {
get;
set;
}
[JsonProperty(PropertyName = "Maximum distance to open your pets inventory")]
public float LootDistance {
get;
set;
}
[JsonProperty(PropertyName = "Maximum distance before your pet will ignore a target")]
public float AttackDistance {
get;
set;
}
[JsonProperty(PropertyName = "Use the permission system")]
public bool UsePermissions {
get;
set;
}
[JsonProperty(PropertyName = "Use the Ddraw system")]
public bool UseDrawSystem {
get;
set;
}
}
public Oxide.Core.VersionNumber Version {
get;
set;
}
}
protected override void LoadConfig() {
base.LoadConfig();
configData = Config.ReadObject<ConfigData>();
if (configData.Version < Version) UpdateConfigValues();
Config.WriteObject(configData, true);
}
protected override void LoadDefaultConfig() => configData = GetBaseConfig();
private ConfigData GetBaseConfig() {
return new ConfigData {
NPCMods = new ConfigData.Modifiers {
Attack = 2f, Health = 1.5f, Speed = 1f
}
, Options = new ConfigData.OtherOptions {
AttackDistance = 70, LootDistance = 1f, TameDistance = 10f, TameTimer = 60f, TpCooldown = 600, UsePermissions = false, UseDrawSystem = true
}
, UserControl = new ConfigData.Controls {
Main = "USE", Secondary = "RELOAD"
}
, Version = Version
}
;
}
protected override void SaveConfig() => Config.WriteObject(configData, true);
private void UpdateConfigValues() {
PrintWarning("Config update detected! Updating config values...");
ConfigData baseConfig = GetBaseConfig();
if (configData.Version < new VersionNumber(0, 6, 2)) configData = baseConfig;
configData.Version = Version;
PrintWarning("Config update completed!");
}
#endregion
#region Data Management
void SaveData() => Interface.Oxide.DataFileSystem.WriteObject("Pets_data", npcSaveList);
void LoadData() {
try {
npcSaveList = Interface.GetMod().DataFileSystem.ReadObject<Dictionary<ulong, PetData>>("Pets_data");
}
catch {
npcSaveList = new Dictionary<ulong, PetData>();
}
}
class PetData {
public uint prefabID;
public float x, y, z;
public byte[] inventory;
internal bool NeedToSpawn;
public PetData() {
NeedToSpawn = true;
}
public PetData(NpcAI pet) {
x = pet.transform.position.x;
y = pet.transform.position.y;
z = pet.transform.position.z;
prefabID = pet.entity.prefabID;
inventory = pet.inventory.Save().ToProtoBytes();
NeedToSpawn = false;
}
}
#endregion
#region Localization
static void UserMessage(BasePlayer player, string key, string[] args = null) => player.ChatMessage(args == null ? ins.lang.GetMessage(key, ins, player.UserIDString) : string.Format(ins.lang.GetMessage(key, ins, player.UserIDString), args));
Dictionary<string, string> Messages = new Dictionary<string, string> {
{
"tooFar", "<color=#939393>You are too far away</color>"
}
, {
"isTired", "<color=#939393>Your pet tired and needs to rest</color>"
}
, {
"isHungry", "<color=#939393>Your pet is hungry and needs to eat</color>"
}
, {
"isEating", "<color=#939393>Your pet is now eating</color>"
}
, {
"isDrinking", "<color=#939393>Your pet is going to get a drink</color>"
}
, {
"notThirsty", "<color=#939393>Your pet is not thirsty</color>"
}
, {
"isAttacking", "<color=#939393>Your pet is now attacking</color>"
}
, {
"openInv", "<color=#939393>Opening your pets inventory</color>"
}
, {
"stopFollow", "<color=#939393>Your pet has stopped following you</color>"
}
, {
"startFollow", "<color=#939393>Your pet is now following you</color>"
}
, {
"isPet", "<color=#939393>This animal is already someones a pet</color>"
}
, {
"isYourPet", "<color=#939393>This animal is already your pet</color>"
}
, {
"tooFast", "<color=#939393>You are trying to tame animals too fast</color>"
}
, {
"noPerms", "<color=#939393>You do not have the required permissions to tame this animal</color>"
}
, {
"petSet", "<color=#939393>You have set this animal as your pet</color>"
}
, {
"isEnabled", "<color=#939393>Pet control activated\nType </color><color=#ce422b>\"/pet help\" </color><color=#939393>to show the help menu!</color>"
}
, {
"isDisabled", "<color=#939393>Pet control deactivated</color>"
}
, {
"help0", "<color=#ce422b>{0} </color><color=#939393>v</color><color=#ce422b>{1}</color>"
}
, {
"help1", "<color=#ce422b>/pet </color><color=#939393>- Enable/disable pet control</color>"
}
, {
"help2", "<color=#ce422b>/pet help </color><color=#939393>- Show this menu</color>"
}
, {
"help3", "<color=#ce422b>/pet draw </color><color=#939393>- Enable/disable ddraw control markers</color>"
}
, {
"help4", "<color=#ce422b>/pet free </color><color=#939393>- Release your pet back into the wild</color>"
}
, {
"help5", "<color=#ce422b>/pet sleep </color><color=#939393>- Put your pet to sleep, or wake them up</color>"
}
, {
"help7", "<color=#ce422b>/pet come </color><color=#939393>- Teleport your pet to your position</color>"
}
, {
"help6", "<color=#ce422b>/pet info </color><color=#939393>- Display statistics for your pet</color>"
}
, {
"drawEnabled", "<color=#939393>Activated ddraw display</color>"
}
, {
"drawDisabled", "<color=#939393>Deactivated ddraw display</color>"
}
, {
"noDdraw", "<color=#939393>DDraw display is not enabled on this server</color>"
}
, {
"hasReleased", "<color=#939393>You released your pet back into the wild</color>"
}
, {
"awoken", "<color=#939393>Your pet has awoken</color>"
}
, {
"ondeath", "<color=#939393>Your pet has died!</color>"
}
, {
"sleeping", "<color=#939393>Your pet is sleeping</color>"
}
, {
"tpcooldown", "<color=#939393>You must wait another <color=#ce422b>{0}</color> to user this command!</color>"
}
, {
"nopet", "<color=#939393>You dont currently have a pet</color>"
}
, {
"statistics", "<color=#ce422b>Pet Statistics:</color><color=#939393>\nHealth :</color><color=#ce422b>{0}</color><color=#939393>\nEnergy :</color><color=#ce422b>{1}</color><color=#939393>\nHydration :</color><color=#ce422b>{2}</color><color=#939393>\nStamina :</color><color=#ce422b>{3}</color><color=#939393>\nSleep :</color><color=#ce422b>{4}</color>"
}
}
;
#endregion
}
}