/// <summary> /// This method is important, because players could fall through air /// if they are on the top of a keep when it is captured because /// the keep size will reset /// </summary> protected void ResetPlayersOfKeep() { ushort distance = 0; int id = 0; if (this is GameKeepTower) { distance = 750; id = 11; } else { distance = 1500; id = 10; } GameKeepComponent component = null; foreach (GameKeepComponent c in this.KeepComponents) { if (c.Skin == id) { component = c; break; } } if (component == null) { return; } if (!component.HookPoints.TryGetValue(97, out var hookpoint)) { return; } //predict Z DBKeepHookPoint hp = DOLDB <DBKeepHookPoint> .SelectObject(DB.Column("HookPointID").IsEqualTo(97).And(DB.Column("Height").IsEqualTo(Height))); if (hp == null) { return; } int z = component.Z + hp.Z; foreach (GamePlayer player in component.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { int d = hookpoint.GetDistance(player as IPoint2D); if (d > distance) { continue; } if (player.Z > z) { player.MoveTo(player.CurrentRegionID, player.X, player.Y, z, player.Heading); } } }
public static void RemoveHouseItems(House house) { house.RemoveConsignmentMerchant(); IList <DBHouseIndoorItem> iobjs = DOLDB <DBHouseIndoorItem> .SelectObjects(DB.Column(nameof(DBHouseIndoorItem.HouseNumber)).IsEqualTo(house.HouseNumber)); GameServer.Database.DeleteObject(iobjs); house.IndoorItems.Clear(); IList <DBHouseOutdoorItem> oobjs = DOLDB <DBHouseOutdoorItem> .SelectObjects(DB.Column(nameof(DBHouseOutdoorItem.HouseNumber)).IsEqualTo(house.HouseNumber)); GameServer.Database.DeleteObject(oobjs); house.OutdoorItems.Clear(); IList <DBHouseHookpointItem> hpobjs = DOLDB <DBHouseHookpointItem> .SelectObjects(DB.Column(nameof(DBHouseHookpointItem.HouseNumber)).IsEqualTo(house.HouseNumber)); GameServer.Database.DeleteObject(hpobjs); foreach (DBHouseHookpointItem item in house.HousepointItems.Values) { if (item.GameObject is GameObject) { (item.GameObject as GameObject).Delete(); } } house.HousepointItems.Clear(); }
public static void RemoveHousePermissions(House house) { // clear the house number for the guild if this is a guild house if (house.DatabaseItem.GuildHouse) { Guild guild = GuildMgr.GetGuildByName(house.DatabaseItem.GuildName); if (guild != null) { guild.GuildHouseNumber = 0; } } house.DatabaseItem.GuildHouse = false; house.DatabaseItem.GuildName = null; IList <DBHousePermissions> pobjs = DOLDB <DBHousePermissions> .SelectObjects(DB.Column(nameof(DBHousePermissions.HouseNumber)).IsEqualTo(house.HouseNumber)); GameServer.Database.DeleteObject(pobjs); house.PermissionLevels.Clear(); IList <DBHouseCharsXPerms> cpobjs = DOLDB <DBHouseCharsXPerms> .SelectObjects(DB.Column(nameof(DBHouseCharsXPerms.HouseNumber)).IsEqualTo(house.HouseNumber)); GameServer.Database.DeleteObject(cpobjs); house.CharXPermissions.Clear(); }
private void add(GameClient client, GameDoor targetDoor) { var DOOR = DOLDB <DBDoor> .SelectObject(DB.Column(nameof(DBDoor.InternalID)).IsEqualTo(DoorID)); if (DOOR != null) { client.Out.SendMessage("The door is already in the database", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (DOOR == null) { if (doorType != 7 && doorType != 9) { var door = new DBDoor(); door.ObjectId = null; door.InternalID = DoorID; door.Name = "door"; door.Type = DoorID / 100000000; door.Level = 20; door.Realm = 6; door.X = targetDoor.X; door.Y = targetDoor.Y; door.Z = targetDoor.Z; door.Heading = targetDoor.Heading; door.Health = 2545; GameServer.Database.AddObject(door); (targetDoor).AddToWorld(); client.Player.Out.SendMessage("Added door ID:" + DoorID + "to the database", eChatType.CT_Important, eChatLoc.CL_SystemWindow); //DoorMgr.Init( ); return; } } }
/// <summary> /// Method to save the Patrol Path using the Patrol ID and the Component /// </summary> /// <param name="pathID"></param> /// <param name="path"></param> /// <param name="component"></param> public static void SavePatrolPath(string pathID, PathPoint path, GameKeepComponent component) { if (path == null) { return; } pathID.Replace('\'', '/'); // we must replace the ', found no other way yet GameServer.Database.DeleteObject(DOLDB <DBPath> .SelectObjects(DB.Column(nameof(DBPath.PathID)).IsEqualTo(pathID))); PathPoint root = MovementMgr.FindFirstPathPoint(path); //Set the current pathpoint to the rootpoint! path = root; DBPath dbp = new DBPath(pathID, ePathType.Loop); GameServer.Database.AddObject(dbp); int i = 1; do { DBPathPoint dbpp = new DBPathPoint(path.X, path.Y, path.Z, path.MaxSpeed); int x, y; SaveXY(component, dbpp.X, dbpp.Y, out x, out y); dbpp.X = x; dbpp.Y = y; dbpp.Z = dbpp.Z - component.Z; dbpp.Step = i++; dbpp.PathID = pathID; dbpp.WaitTime = path.WaitTime; GameServer.Database.AddObject(dbpp); path = path.Next; } while (path != null && path != root); }
/// <summary> /// we need to make use of the new poison fields /// </summary> public void ConvertDatabase() { log.Info("Database Version 4 Convert Started"); if (GameServer.Instance.Configuration.DBType == DOL.Database.Connection.ConnectionType.DATABASE_XML) { log.Info("You have an XML database loaded, this converter will only work with MySQL, skipping"); return; } var mobs = DOLDB <Mob> .SelectObjects(DB.Column(nameof(Mob.ClassType)).IsEqualTo("DOL.GS.GameMob")); int count = 0; foreach (Mob mob in mobs) { mob.ClassType = "DOL.GS.GameNPC"; GameServer.Database.SaveObject(mob); count++; } log.Info("Converted " + count + " mobs"); log.Info("Database Version 4 Convert Finished"); }
public void HandlePacket(GameClient client, GSPacketIn packet) { string name; if (client.Version >= GameClient.eClientVersion.Version1126) { name = packet.ReadString(24); } else { name = packet.ReadString(30); } var character = DOLDB <DOLCharacters> .SelectObject(DB.Column("Name").IsEqualTo(name)); byte result = 0; // Bad Name check. if (character != null) { result = 0x02; } else if (GameServer.Instance.PlayerManager.InvalidNames[name]) { result = 0x01; } client.Out.SendDupNameCheckReply(name, result); }
public static void AreYouSure(GamePlayer player, byte response) { //here we get the zones new info. Zone zone = player.TempProperties.getProperty <Zone>("ZONE_BONUS_SAVE"); if (response != 0x01) { player.Out.SendCustomDialog(string.Format("{0}'s bonuses will not be saved to the database!", zone.Description), null); player.TempProperties.removeProperty("ZONE_BONUS_SAVE"); return; } //find the zone. var dbZone = DOLDB <Zones> .SelectObject(DB.Column(nameof(Zones.ZoneID)).IsEqualTo(zone.ID).And(DB.Column(nameof(Zones.RegionID)).IsEqualTo(zone.ZoneRegion.ID))); //update the zone bonuses. dbZone.Bountypoints = zone.BonusBountypoints; dbZone.Realmpoints = zone.BonusRealmpoints; dbZone.Coin = zone.BonusCoin; dbZone.Experience = zone.BonusExperience; GameServer.Database.SaveObject(dbZone); player.Out.SendCustomDialog(string.Format("{0}'s new zone bonuses have been updated to the database and changes have already taken effect!", zone.Description), null); //remove the property. player.TempProperties.removeProperty("ZONE_BONUS_SAVE"); }
/// <summary> /// Gets the position at the exact entry from the database /// </summary> /// <param name="guard">The guard object</param> /// <returns>The position object</returns> public static DBKeepPosition GetPosition(GameKeepGuard guard) { var filterTemplateID = DB.Column(nameof(DBKeepPosition.TemplateID)).IsEqualTo(guard.TemplateID); var filterComponentSkin = DB.Column(nameof(DBKeepPosition.ComponentSkin)).IsEqualTo(guard.Component.Skin); var filterHeight = DB.Column(nameof(DBKeepPosition.Height)).IsLessOrEqualTo(guard.Component.Height); return(DOLDB <DBKeepPosition> .SelectObject(filterTemplateID.And(filterComponentSkin).And(filterHeight))); }
/// <summary> /// Returns a given character /// </summary> /// <param name="charname">the charactername</param> /// <returns>the found character or null</returns> private DOLCharacters GetCharacter(string charname) { GameClient client = WorldMgr.GetClientByPlayerName(charname, true, false); if (client != null) { return(client.Player.DBCharacter); } return(DOLDB <DOLCharacters> .SelectObject(DB.Column("Name").IsEqualTo(charname))); }
/// <summary> /// Gets the most usuable position for a banner directly from the database /// </summary> /// <param name="b">The banner object</param> /// <returns>The position object</returns> public static DBKeepPosition GetUsablePosition(GameKeepBanner b) { var filterClassType = DB.Column(nameof(DBKeepPosition.ClassType)).IsNotEqualTo("DOL.GS.Keeps.Banner"); var filterTemplateID = DB.Column(nameof(DBKeepPosition.TemplateID)).IsEqualTo(b.TemplateID); var filterComponentSkin = DB.Column(nameof(DBKeepPosition.ComponentSkin)).IsEqualTo(b.Component.Skin); var filterHeight = DB.Column(nameof(DBKeepPosition.Height)).IsLessOrEqualTo(b.Component.Height); return(DOLDB <DBKeepPosition> .SelectObjects(filterClassType.And(filterTemplateID).And(filterComponentSkin).And(filterHeight)) .OrderByDescending(it => it.Height).FirstOrDefault()); }
public static void OnScriptsCompiled(DOLEvent e, object sender, EventArgs args) { // What npctemplate should we use for the zonepoint ? ushort model; NpcTemplate zp; try{ model = (ushort)ServerProperties.Properties.ZONEPOINT_NPCTEMPLATE; zp = new NpcTemplate(DOLDB <DBNpcTemplate> .SelectObjects(DB.Column(nameof(DBNpcTemplate.TemplateId)).IsEqualTo(model)).FirstOrDefault()); if (model <= 0 || zp == null) { throw new ArgumentNullException(); } } catch { return; } // processing all the ZP IList <ZonePoint> zonePoints = GameServer.Database.SelectAllObjects <ZonePoint>(); foreach (ZonePoint z in zonePoints) { if (z.SourceRegion == 0) { continue; } // find target region for the current zonepoint Region r = WorldMgr.GetRegion(z.TargetRegion); if (r == null) { log.Warn("Zonepoint Id (" + z.Id + ") references an inexistent target region " + z.TargetRegion + " - skipping, ZP not created"); continue; } GameNPC npc = new GameNPC(zp); npc.CurrentRegionID = z.SourceRegion; npc.X = z.SourceX; npc.Y = z.SourceY; npc.Z = z.SourceZ; npc.Name = r.Description; npc.GuildName = "ZonePoint (Open)"; if (r.IsDisabled) { npc.GuildName = "ZonePoint (Closed)"; } npc.AddToWorld(); } }
/// <summary> /// Method to retrieve the Patrol Path from the Patrol ID and Component /// /// We need this because we store this all using our offset system /// </summary> /// <param name="pathID">The path ID, which is the Patrol ID</param> /// <param name="component">The Component object</param> /// <returns>The Patrol path</returns> public static PathPoint LoadPatrolPath(string pathID, GameKeepComponent component) { SortedList sorted = new SortedList(); pathID.Replace('\'', '/'); // we must replace the ', found no other way yet var dbpath = DOLDB <DBPath> .SelectObject(DB.Column(nameof(DBPath.PathID)).IsEqualTo(pathID)); IList <DBPathPoint> pathpoints = null; ePathType pathType = ePathType.Once; if (dbpath != null) { pathType = (ePathType)dbpath.PathType; } if (pathpoints == null) { pathpoints = DOLDB <DBPathPoint> .SelectObjects(DB.Column(nameof(DBPathPoint.PathID)).IsEqualTo(pathID)); } foreach (DBPathPoint point in pathpoints) { sorted.Add(point.Step, point); } PathPoint prev = null; PathPoint first = null; for (int i = 0; i < sorted.Count; i++) { DBPathPoint pp = (DBPathPoint)sorted.GetByIndex(i); PathPoint p = new PathPoint(pp.X, pp.Y, pp.Z, pp.MaxSpeed, pathType); int x, y; LoadXY(component, pp.X, pp.Y, out x, out y); p.X = x; p.Y = y; p.Z = component.Keep.Z + p.Z; p.WaitTime = pp.WaitTime; if (first == null) { first = p; } p.Prev = prev; if (prev != null) { prev.Next = p; } prev = p; } return(first); }
/// <summary> /// Generate an Item random Named for NPC Drop /// </summary> /// <param name="player">Level of Generated Item</param> /// <returns>A Generated NPC Item</returns> public static ItemTemplate GenerateNPCItem(GamePlayer player) { int mediumCraftingLevel = player.GetCraftingSkillValue(player.CraftingPrimarySkill) + 20; int lowLevel = mediumCraftingLevel - 20; int highLevel = mediumCraftingLevel + 20; var craftitem = DOLDB <DBCraftedItem> .SelectObjects(DB.Column(nameof(DBCraftedItem.CraftingSkillType)).IsEqualTo((int)player.CraftingPrimarySkill) .And(DB.Column(nameof(DBCraftedItem.CraftingLevel)).IsGreatherThan(lowLevel).And(DB.Column(nameof(DBCraftedItem.CraftingLevel)).IsLessThan(highLevel)))); int craftrnd = Util.Random(craftitem.Count); ItemTemplate template = GameServer.Database.FindObjectByKey <ItemTemplate>(craftitem[craftrnd].Id_nb); return(template); }
private void delete(GameClient client, GameDoor targetDoor) { var DOOR = DOLDB <DBDoor> .SelectObject(DB.Column(nameof(DBDoor.InternalID)).IsEqualTo(DoorID)); if (DOOR != null) { GameServer.Database.DeleteObject(DOOR); client.Out.SendMessage("Door removed", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (DOOR == null) { client.Out.SendMessage("This door doesn't exist in the database", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } }
/// <summary> /// Searches for a GameLiving with the given id or name either in worldMgr or Database if lookukDB is true /// </summary> /// <param name="identifier"></param> /// <param name="defaultLiving"></param> /// <param name="lookupDB"></param> /// <returns></returns> public static GameLiving ResolveLiving(object identifier, GameLiving defaultLiving, bool lookupDB) { GameLiving living = null; if (identifier is string || identifier is int) { string tempID = Convert.ToString(identifier); // TODO: Dirty Hack this should be done better var mob = DOLDB <Mob> .SelectObject(DB.Column("Mob_ID").IsEqualTo(tempID).Or(DB.Column("Name").IsEqualTo(tempID))); GameNPC[] livings = WorldMgr.GetNPCsByName(mob.Name, (eRealm)mob.Realm); if (livings.Length == 1) { living = livings[0]; } else if (livings.Length > 1) { if (log.IsWarnEnabled) { log.Warn("Found more than one living with name :" + tempID + " in " + (lookupDB ? "Database" : "WorldMgr")); } } else { if (log.IsWarnEnabled) { log.Warn("Couldn't find GameLiving with id or name:" + tempID + " in " + (lookupDB ? "Database" : "WorldMgr")); } } } else if (identifier is GameLiving) { living = (GameLiving)identifier; } // use default otherwise if (living == null) { living = defaultLiving; } return(living); }
public ClimbingAbilityHandler() { // Graveen: crappy, but not hardcoded. if we except by the ability name ofc... // problems are: // - matching vs ability name / spell name needed // - spell name is not indexed // perhaps a basis to think about, but definitively not the design we want. if (spellid == -1) { spellid = 0; DBSpell climbSpell = DOLDB <DBSpell> .SelectObject(DB.Column(nameof(DBSpell.Name)).IsEqualTo(Abilities.ClimbSpikes)); if (climbSpell != null) { spellid = climbSpell.SpellID; } } }
/// <summary> /// Searches for a NPC with the given id or name either in worldMgr or Database if lookukDB is true /// </summary> /// <param name="identifier"></param> /// <param name="defaultNPC"></param> /// <param name="lookupDB"></param> /// <returns></returns> public static GameNPC ResolveNPC(object identifier, GameNPC defaultNPC, bool lookupDB) { GameNPC npc = null; if (identifier is string || identifier is int) { string tempID = Convert.ToString(identifier); var mob = DOLDB <Mob> .SelectObject(DB.Column("Mob_ID").IsEqualTo(tempID).Or(DB.Column("Name").IsEqualTo(tempID))); GameNPC[] npcs = WorldMgr.GetNPCsByName(mob.Name, (eRealm)mob.Realm); if (npcs.Length == 1) { npc = npcs[0]; } else if (npcs.Length > 1) { if (log.IsWarnEnabled) { log.Warn("Found more than one npc with id or name:" + tempID + " in WorldMgr"); } } else { if (log.IsWarnEnabled) { log.Warn("Couldn't find NPC with id or name:" + tempID + " in WorldMgr"); } } } else if (identifier is GameNPC) { npc = (GameNPC)identifier; } // use default otherwise if (npc == null) { npc = defaultNPC; } return(npc); }
/// <summary> /// Returns an account name with a given character name /// </summary> /// <param name="charname">the charactername</param> /// <returns>the account name or null</returns> private string GetAccountName(string charname) { GameClient client = WorldMgr.GetClientByPlayerName(charname, true, false); if (client != null) { return(client.Account.Name); } var ch = DOLDB <DOLCharacters> .SelectObject(DB.Column("Name").IsEqualTo(charname)); if (ch != null) { return(ch.AccountName); } else { return(null); } }
/// <summary> /// style icon field added this should copy the ID value /// realm 6 should be peace flag and realm changed /// </summary> public void ConvertDatabase() { log.Info("Database Version 2 Convert Started"); log.Info("Converting Styles"); var styles = GameServer.Database.SelectAllObjects <DBStyle>(); foreach (DBStyle style in styles) { style.Icon = style.ID; GameServer.Database.SaveObject(style); } log.Info(styles.Count + " Styles Processed"); log.Info("Converting Mobs"); var mobs = DOLDB <Mob> .SelectObjects(DB.Column("Realm").IsEqualTo(6)); foreach (Mob mob in mobs) { if ((mob.Flags & (uint)GameNPC.eFlags.PEACE) == 0) { mob.Flags ^= (uint)GameNPC.eFlags.PEACE; } Region region = WorldMgr.GetRegion(mob.Region); if (region != null) { Zone zone = region.GetZone(mob.X, mob.Y); if (zone != null) { mob.Realm = (byte)zone.Realm; } } GameServer.Database.SaveObject(mob); } log.Info(mobs.Count + " Mobs Processed"); log.Info("Database Version 2 Convert Finished"); }
public virtual void LoadPositions() { ushort region = CurrentRegionID; if (CurrentRegion is BaseInstance) { region = (CurrentRegion as BaseInstance).Skin; } Battleground bg = GameServer.KeepManager.GetBattleground(region); this.Positions.Clear(); var whereClause = DB.Column(nameof(DBKeepPosition.ComponentSkin)).IsEqualTo(Skin); if (Skin != (int)eComponentSkin.Keep && Skin != (int)eComponentSkin.Tower && Skin != (int)eComponentSkin.Gate) { whereClause = whereClause.And(DB.Column(nameof(DBKeepPosition.ComponentRotation)).IsEqualTo(ComponentHeading)); } if (bg != null && GameServer.Instance.Configuration.ServerType != eGameServerType.GST_PvE) { // Battlegrounds, ignore all but GameKeepDoor whereClause = whereClause.And(DB.Column(nameof(DBKeepPosition.ClassType)).IsEqualTo("DOL.GS.Keeps.GameKeepDoor")); } var DBPositions = DOLDB <DBKeepPosition> .SelectObjects(whereClause); foreach (DBKeepPosition position in DBPositions) { DBKeepPosition[] list = this.Positions[position.TemplateID] as DBKeepPosition[]; if (list == null) { list = new DBKeepPosition[4]; this.Positions[position.TemplateID] = list; } list[position.Height] = position; } }
/// <summary> /// door index which is unique /// </summary> public void HandlePacket(GameClient client, GSPacketIn packet) { var doorID = (int)packet.ReadInt(); m_handlerDoorID = doorID; var doorState = (byte)packet.ReadByte(); int doorType = doorID / 100000000; int radius = Properties.WORLD_PICKUP_DISTANCE * 2; int zoneDoor = doorID / 1000000; string debugText = ""; // For ToA the client always sends the same ID so we need to construct an id using the current zone if (client.Player.CurrentRegion.Expansion == (int)eClientExpansion.TrialsOfAtlantis) { debugText = $"ToA DoorID:{doorID} "; doorID -= zoneDoor * 1000000; zoneDoor = client.Player.CurrentZone.ID; doorID += zoneDoor * 1000000; m_handlerDoorID = doorID; // experimental to handle a few odd TOA door issues if (client.Player.CurrentRegion.IsDungeon) { radius *= 4; } } // debug text if (client.Account.PrivLevel > 1 || Properties.ENABLE_DEBUG) { if (doorType == 7) { int ownerKeepId = (doorID / 100000) % 1000; int towerNum = (doorID / 10000) % 10; int keepID = ownerKeepId + towerNum * 256; int componentID = (doorID / 100) % 100; int doorIndex = doorID % 10; client.Out.SendDebugMessage($"Keep Door ID:{doorID} state:{doorState} (Owner Keep:{ownerKeepId} KeepID:{keepID} ComponentID:{componentID} DoorIndex:{doorIndex} TowerNumber:{towerNum})"); if (keepID > 255 && ownerKeepId < 10) { ChatUtil.SendDebugMessage(client, "Warning: Towers with an Owner Keep ID < 10 will have untargetable doors!"); } } else if (doorType == 9) { int doorIndex = doorID - doorType * 10000000; client.Out.SendDebugMessage($"House DoorID:{doorID} state:{doorState} (doorType:{doorType} doorIndex:{doorIndex})"); } else { int fixture = (doorID - zoneDoor * 1000000); int fixturePiece = fixture; fixture /= 100; fixturePiece = fixturePiece - fixture * 100; client.Out.SendDebugMessage($"{debugText}DoorID:{doorID} state:{doorState} zone:{zoneDoor} fixture:{fixture} fixturePiece:{fixturePiece} Type:{doorType}"); } } if (client.Player.TargetObject is GameDoor target && !client.Player.IsWithinRadius(target, radius)) { client.Player.Out.SendMessage("You are too far to open this door", eChatType.CT_Important, eChatLoc.CL_SystemWindow); return; } var door = DOLDB <DBDoor> .SelectObject(DB.Column(nameof(DBDoor.InternalID)).IsEqualTo(doorID)); if (door != null) { if (doorType == 7 || doorType == 9) { new ChangeDoorAction(client.Player, doorID, doorState, radius).Start(1); return; } if (client.Account.PrivLevel == 1) { if (door.Locked == 0) { if (door.Health == 0) { new ChangeDoorAction(client.Player, doorID, doorState, radius).Start(1); return; } if (GameServer.Instance.Configuration.ServerType == eGameServerType.GST_PvP || GameServer.Instance.Configuration.ServerType == eGameServerType.GST_PvE) { if (door.Realm != 0) { new ChangeDoorAction(client.Player, doorID, doorState, radius).Start(1); return; } } else { if (client.Player.Realm == (eRealm)door.Realm || door.Realm == 6) { new ChangeDoorAction(client.Player, doorID, doorState, radius).Start(1); return; } } } } else if (client.Account.PrivLevel > 1) { client.Out.SendDebugMessage("GM: Forcing locked door open."); new ChangeDoorAction(client.Player, doorID, doorState, radius).Start(1); return; } } else // door == null { if (doorType != 9 && client.Account.PrivLevel > 1 && client.Player.CurrentRegion.IsInstance == false) { if (client.Player.TempProperties.getProperty(DoorMgr.WANT_TO_ADD_DOORS, false)) { client.Player.Out.SendCustomDialog( "This door is not in the database. Place yourself nearest to this door and click Accept to add it.", AddingDoor); } else { client.Player.Out.SendMessage( "This door is not in the database. Use '/door show' to enable the add door dialog when targeting doors.", eChatType.CT_Important, eChatLoc.CL_SystemWindow); } } new ChangeDoorAction(client.Player, doorID, doorState, radius).Start(1); return; } }