[SVN:r3246] RegionInstance to Implement Adventure Wings

A place to submit .patch fixes for the DOL SVN

Moderator: Developer Team

[SVN:r3246] RegionInstance to Implement Adventure Wings

Postby Leodagan » Sun Aug 04, 2013 9:23 am

HowTo use AdventureWingInstance's
Simply Edit "zonepoint" table where ID leads to a Instanced Dungeon or an area you want Instanced.
The Instance creation will happen when going through this JumpPoint !

Code: Select all
UPDATE `zonepoint` SET `ClassType` = 'DOL.GS.ServerRules.AdventureWingJumpPoint' WHERE `Id` IN('142', '142', '142', '295', '294', '296', '297', '289', '289', '289', '288', '288', '288', '397', '397', '397', '398', '398', '398', '252', '252', '252', '450', '450', '450', '451', '451', '451', '589', '589', '589', '321', '321', '321', '320', '320', '320', '594', '594', '594', '279', '279', '279', '455', '455', '455', '454', '454', '454', '579', '579', '579', '597', '597', '597', '439', '439', '439', '440', '440', '440', '449', '449', '449', '445', '445', '445', '583', '583', '583', '310', '310', '302', '302', '302', '317', '317', '317', '453', '453', '453', '452', '452', '452', '311', '311', '311', '300', '300', '300', '582', '582', '582', '301', '301', '301', '586', '586', '586', '403', '404', '431', '432', '406', '405', '421', '422', '437', '438', '372', '373', '369', '368', '376', '377', '375', '374', '370', '371', '291', '290', '293', '292', '298', '299');
Hello,

I wanted to implement fast Adventure Wings Instance dungeon to create area where people could PvE alone or in group...

I didn't wanted to use DungeonTaskMission because it use randomness for region instancing and need special element in instance table !

As some of my Catacombs area are already populated but not instanced, I Needed a way to copy an existing Area to a private Instance !

So I ended up making a class that create a new unique area (ID > 1000) and then make a LoadFromDatabase to get everything matching it's fake "Region ID" (Skin ID) and changing every object.Region ID to Current.Region ID (ID > 1000)

This end up as making an Instanced clone of an entire Region ! (I don't handle BindPoint or persistence, but a subclass could, thus making a server as instanced as official cluster servers with Multiples Homeland/Housing/etc...)

On top of this class I use a subclass to instantiate AdventureWings Dungeon that handle ownership, the special jumppoint is handling creation and cleaning so at most there could be 'n' Player Instance (this part of the code could be messy, but anyone is welcome to write is own jumppoint !)

The AdventureWingInstance also handle Aurulite loot generator to make it "livelike", it's implemented with absolutely no real value, and the item template is to be handled by yourself in the database ! (Model 541 I think)

A class could be written for aurulite so it could handle different stash size, but it's not really important, my "default" loot generator try to drop packsize of livelike sized stash, so it can be given right to an aurulite GameMerchant !

Main Drawbacks of AdventureWings :

- Can be very heavy on memory as dungeon are kept 30 min after every ppl left out
- No way to know an instance is empty of mobs and should be destroyed anyway
- Core doesn't handle connecting into an instance (it does a special check to port you to BindPoint even if Instance still exists !)
- Clean up are really lazy... (but anyway 30 min later everything is destroyed !)

Main Drawbacks of RegionInstance :

- To make sure everything happen as expected RegionInstance are build on a duplicated Database Object modifying each Region to Instance Region, so it's more heavy on memory that simply duplicating GameObjects (I had problem when working directly on GameObjects but maybe my workaround can improve other aspects i didn't thought of)
- Can't Handle Persistence ! If you want zone perma-instance it can't handle saving modification to database (it wouldn't know where or what to save as previous records exists) a subclass like hypothetical "WorldInstance" could maintain persistent unique Region ID and save object in database with it ! (using Region ClassType...)
- Previous Region "Skin ID" that is used as clone will stays in memory, only a GM could jump to the original instance or a JumpPoint not handling instance... This is a Drawback and also work as safety in case something went wrong when creating Instance !

How to use :

Simply put the JumpPoint handler for zonepoint that lead to instance zone, it will use TargetRegionID as a template.
To map instance, simply disable zonepoint class to jump to original region, or when in instance use /jump to region {SkinId}

This patch will have no effect until zonepoint are modified to use the JumpPoint handler, no way to break the core !
And you can use RegionInstance to create subclass for Demon's Breach Instance, or real Throne Room Instance ! (Maybe Even Celestius !)
Attachments
RegionInstance.cs.patch
DOL.GS.RegionInstance
(10.16 KiB) Downloaded 20 times
AdventureWingJumpPoint.cs.patch
DOL.GS.ServerRules.AdventureWingJumpPoint
(8.69 KiB) Downloaded 18 times
AdventureWingInstance.cs.patch
DOL.GS.AdventureWingInstance
DOL.GS.LootGeneratorAurulite
(7.15 KiB) Downloaded 19 times
Last edited by Leodagan on Fri Sep 20, 2013 9:19 am, edited 4 times in total.
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Website: https://daoc.freyad.net
Location: Lyon

Re: RegionInstance to Implement Adventure Wings

Postby Graveen » Fri Aug 09, 2013 12:22 pm

bookmarking your post to read it correctly now i'm at home :)
Image
* pm me to contribute in Dawn of Light: code, database *
User avatar
Graveen
Project Leader
 
Posts: 12660
Joined: Fri Oct 19, 2007 9:22 pm
Location: France

Re: RegionInstance to Implement Adventure Wings

Postby Leodagan » Thu Aug 29, 2013 9:29 am

Bump.

I'll need some comments on this work to know if it can be comitted to SVN.
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Website: https://daoc.freyad.net
Location: Lyon

Re: RegionInstance to Implement Adventure Wings

Postby Dinberg » Thu Aug 29, 2013 11:33 am

I'm afraid I dont have time to check your source right now, but I think you know what you are doing :D
So I ended up making a class that create a new unique area (ID > 1000) and then make a LoadFromDatabase to get everything matching it's fake "Region ID" (Skin ID) and changing every object.Region ID to Current.Region ID (ID > 1000)
I would say it might be better to directly subclass BaseInstance rather than adventure wing - when I wrote the instance system BaseInstance was intended as a class with only the bare minimum functionality to work, and may be more appropriate for you. I wrote something similar many years ago, and duplicated a region by selecting from the npc table entries with the instance's skin ID as region ID (as you do above) and creating GameNPCs for each one using new GameNPC(databaseNpcEntry). This did the job perfectly. I would also suggest ensuring that the created npcs have LoadFromDatabase set to false, so they do not create entries in the database during save. By default this *should* be the case if nothing has changed.
...make a LoadFromDatabase to get everything matching it's fake "Region ID" (Skin ID) and changing every object.Region ID to Current.Region ID (ID > 1000)
If you just change the regionID of the npcs, you'll be moving them to the instanced region, not creating copies of them! Might be a good idea to double check that :D

Hope all is well, keep up the good work.
The Marvelous Contraption begins to stir...
User avatar
Dinberg
Inactive Staff Member
 
Posts: 4695
Joined: Sat Mar 10, 2007 9:47 am
Yahoo Messenger: dinberg_darktouch
Location: Jordheim

Re: RegionInstance to Implement Adventure Wings

Postby Leodagan » Thu Aug 29, 2013 11:55 am

thanks for your comments, even if you didn't read the code, you have right on all points !

And those points are already handled :) It's just some of my explanations which induce you to errors I didn't make in the end ;)

RegionInstance is a subclass of BaseInstance, and AdventureWingInstance is a subclass of RegionInstance, so all code checking if object "is BaseInstance" will work correctly ;)

I'm making a new GameNPC() for all database Entries, but with a dataobject cloning first !

So I take a the Dataobject from NPC or WorldObjects, clone it, change its RegionID, set "AllowAdd" to false and make a new In-Game Object instance with the resulting dataobject !

You confirm all the choices I made during this development, thanks a lot !
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Website: https://daoc.freyad.net
Location: Lyon

Re: RegionInstance to Implement Adventure Wings

Postby Dinberg » Thu Aug 29, 2013 5:58 pm

Good luck with it all :D
The Marvelous Contraption begins to stir...
User avatar
Dinberg
Inactive Staff Member
 
Posts: 4695
Joined: Sat Mar 10, 2007 9:47 am
Yahoo Messenger: dinberg_darktouch
Location: Jordheim

Re: RegionInstance to Implement Adventure Wings

Postby Leodagan » Fri Aug 30, 2013 11:38 am

added to SVN revision 3233, after re-reading, correcting some code path or left-over workarounds (in my messy cleanup procedure), changed some readability of the code (spaces, linefeed, indent)

Aurulite loot generator extracted to his own file, const added to set loot chance in class.

PS : grabbed TaskDungeonJumpPoint in my update, it's a failure I made some testing change that shouldn't be committed, I'll try to revert it !
Rev 3234 : I commited it back from rev 3179, maybe not best solution, I'm not really good with SVN
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Website: https://daoc.freyad.net
Location: Lyon

Re: [SVN:r3234] RegionInstance to Implement Adventure Wings

Postby Tolakram » Sat Aug 31, 2013 7:52 pm

Loot GeneratorAurulite is missing from SVN, compile error when getting latest project. :) Removing it from the project file for now. Feel free to add it back one all files are included.
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: [SVN:r3234] RegionInstance to Implement Adventure Wings

Postby Leodagan » Sun Sep 01, 2013 7:24 am

Sorry for that miss ;)

I didn't add the file to the local repository so it wasn't updated to sourceforge SVN :(

rev 3237 : changed back gameproject, and added the loot generator file missing.

I'll be more careful for future updates !
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Website: https://daoc.freyad.net
Location: Lyon

Re: [SVN:r3237] RegionInstance to Implement Adventure Wings

Postby Tolakram » Sun Sep 01, 2013 5:10 pm

Thanks. :)
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: [SVN:r3237] RegionInstance to Implement Adventure Wings

Postby Leodagan » Tue Sep 17, 2013 1:25 pm

I made some updates to my Region Instance based on Dinberg work on Instance and BaseInstance...

What is the point here ? With the TeleportArea I added to SVN, I needed these to work inside RegionInstance, from which AdventureWingInstance is a subclass...

2 of these AdventureWings are in Veil Rift, and needs TeleportArea to get out of there (Pillars of light)

After looking around Area Code I noticed it was mostly using "Zone" to check for players being in or out...

I looked at BaseInstance for Zone / Area overrides but couldn't find anything, I launched a search in all projects and found that Dinberg "Instance", which is parent class of DungeonTask, have some methods dedicated to "Map" Zones in an Instance for Client "Skin mapping" (well in fact I still don't understand why it needs this to work...)

I made a dumb test and moved all Area related methods from Instance to BaseInstance which my RegionInstance inherits ! (Instance override LoadFromDatabase that don't suit to my RegionInstance) and...

All worked like expected ;)

So here I propose to move these methods from Instance to BaseInstance, as Instance inherits from BaseInstance it can still access those methods, and all class inheriting BaseInstance should have this default Zone/Area behavior (which seems good to me...)


There is also some code change to BaseInstance for a mob object counter (using Linq query to select an IEnumerable of object inside Instance) I use this for AdventureWings to iterate over Mobs and remove Respawn Rate of Mobs (Live Like) or to check there isn't any more alive mobs inside instance (finished instance, Destroy needed...), as I know TaskDungeon could need this type of query I tried to put this method in a class that all derived class can access.
Attachments
AdventureWingInstance.cs.patch
Added a Mob count checks, and a change Respawn Rate at instancing.
(5.26 KiB) Downloaded 18 times
RegionInstance.cs.patch
Added an Area Loading/Cloning code to LoadFromDatabase()
(5.27 KiB) Downloaded 20 times
Instance.cs.patch
Removed Area / Zone Mapping Handlers to BaseInstance
(3.08 KiB) Downloaded 21 times
BaseInstance.cs.patch
Added Area / Zone Mapping Handlers from Instance
(5.93 KiB) Downloaded 19 times
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Website: https://daoc.freyad.net
Location: Lyon

Re: [SVN:r3237] RegionInstance to Implement Adventure Wings

Postby Graveen » Tue Sep 17, 2013 4:22 pm

Seems legit.

Tola, would it breaks D2 ?
Image
* pm me to contribute in Dawn of Light: code, database *
User avatar
Graveen
Project Leader
 
Posts: 12660
Joined: Fri Oct 19, 2007 9:22 pm
Location: France

Re: [SVN:r3237] RegionInstance to Implement Adventure Wings

Postby Tolakram » Tue Sep 17, 2013 4:55 pm

Should not since it's moving code back to the base. StormRegion inherits from Instance, so it will all look the same based on my overview of the patch files.

Here, have at this stuff. :) These are persistent regions loaded on server start. I offer very little support, if any, but if this can be transformed into a more core worthy system that would be a good thing! There is a lot of crap in here that can be ignored, most of it specific to StormGames, a concept that was created when I made D2 but never used.

StormRegion
Code: Select all
using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using DOL.GS.ServerProperties; using System.Text; using DOL.Database; using DOL.Events; using DOL.GS; using DOL.GS.Housing; using DOL.GS.Keeps; using DOL.GS.PacketHandler; using log4net; namespace DOL.Storm { /// <summary> /// Storm Region is an instance regions that behaves like a normal region /// -- Tolakram, released 17-SEP-2013, unsupported /// </summary> public class StormRegion : Instance { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public StormRegion(ushort id, GameTimer.TimeManager time, RegionData data) : base(id, time, data) { } public const int TOA_DOOR_ZONE_ID = 999; public string StartupLog = ""; protected bool m_useWeatherManager = true; protected bool m_useTimeManager = true; protected uint m_dayIncrement = 72; protected struct Weather { public Weather(uint x, uint width, ushort speed, ushort fog, ushort intensity) { X = x; Width = width; Speed = speed; Fog = fog; Intensity = intensity; } public uint X; public uint Width; public ushort Speed; public ushort Fog; public ushort Intensity; } protected virtual bool UseWeatherManager { get { return true; } } public virtual void SetWeather(uint x, uint width, ushort speed, ushort fog, ushort intensity) { } public Hashtable m_instanceKeeps = new Hashtable(); protected Dictionary<int, List<IDoor>> m_instanceDoors = new Dictionary<int, List<IDoor>>(); public Dictionary<int, List<IDoor>> InstanceDoors { get { return m_instanceDoors; } } public void RegisterDoor(IDoor door, int convertedDoorID = 0) { if (convertedDoorID == 0) { convertedDoorID = door.DoorID; } if (!m_instanceDoors.ContainsKey(convertedDoorID)) { List<IDoor> createDoorList = new List<IDoor>(); m_instanceDoors.Add(convertedDoorID, createDoorList); } List<IDoor> addDoorList = m_instanceDoors[convertedDoorID] as List<IDoor>; addDoorList.Add(door); } public List<IDoor> GetDoorByID(int doorID) { if (m_instanceDoors != null && m_instanceDoors.ContainsKey(doorID)) { return m_instanceDoors[doorID]; } else { return new List<IDoor>(); } } /// <summary> /// Storm Regions are not considered instances /// </summary> public override bool IsInstance { get { return false; } } public override bool IsCustom { get { return true; } } protected bool m_isRvR = true; public override bool IsRvR { get { if (TeamType == StormGame.eTeamType.RvR) return true; return false; } } public override bool IsDisabled { get { return false; } } public bool NoAutoZone; /// <summary> /// Should this zone currently use StormGame rules? /// </summary> /// <returns></returns> public virtual bool UsingStormGameRules() { return true; } protected StormGame.eTeamType m_teamType = StormGame.eTeamType.Undefined; public virtual StormGame.eTeamType TeamType { get { return m_teamType; } set { m_teamType = value; } } private string m_name = ""; public override string Name { get { if (m_name == "") return ID.ToString(); return m_name; } } public void SetName(string name) { m_name = name; } public override string Description { get { return Name; } } protected string m_gameName = ""; public virtual string GameName { get { return m_gameName; } set { m_gameName = value; } } public virtual StormGame.eJoinType JoinType { get; set; } private string m_playerClass = ""; public virtual string PlayerClass { get { return m_playerClass; } set { m_playerClass = value; } } public virtual string ServerRules { get; set; } protected bool m_allowBuff = false; public virtual bool AllowBuff { get { return m_allowBuff; } set { m_allowBuff = value; } } protected string m_introText = ""; public virtual string IntroText { get { return m_introText; } set { m_introText = value; } } protected string m_allowedClasses = ""; public virtual string AllowedClasses { get { return m_allowedClasses; } set { m_allowedClasses = value; } } protected byte m_keepType = 0; public virtual byte KeepType { get { return m_keepType; } } protected bool m_housingEnabled = false; public override bool HousingEnabled { get { return m_housingEnabled; } } public override bool UseHousingManager { get { return false; } } protected int m_waterlevel = 0; public override int WaterLevel { get { if (m_waterlevel != 0) return m_waterlevel; return base.WaterLevel; } } protected bool m_isLava = false; public virtual bool IsLava { get { return m_isLava; } set { m_isLava = value; } } protected GameLocation m_albCoopEntrance = null; public virtual GameLocation AlbCoopEntrance { get { return m_albCoopEntrance; } } protected GameLocation m_midEntrance = null; public virtual GameLocation MidEntrance { get { return m_midEntrance; } } protected GameLocation m_hibEntrance = null; public virtual GameLocation HibEntrance { get { return m_hibEntrance; } } public bool IsClosed = false; public virtual void LoadStormRegion(StormRegions sr, bool forceLoad = false) { Persistent = true; SetName(sr.Name); m_isRvR = sr.IsRvR; IsClosed = sr.IsClosed; m_useWeatherManager = sr.UseWeatherManager; m_useTimeManager = sr.UseTimeManager; m_dayIncrement = sr.DayIncrement; log.DebugFormat("{0} - UseTimeManager: {1} UseWeatherManager: {2}", Name, m_useTimeManager, m_useWeatherManager); StartupLog += string.Format("\n{0} - UseTimeManager: {1} UseWeatherManager: {2}", Name, m_useTimeManager, m_useWeatherManager); m_allowedClasses = sr.AllowedClasses; if (sr.TeamType != 0) { TeamType = (StormGame.eTeamType)sr.TeamType; } else if (m_isRvR) { TeamType = StormGame.eTeamType.RvR; } GameName = sr.GameName; JoinType = (StormGame.eJoinType)sr.JoinType; if (sr.PlayerClass != null) PlayerClass = sr.PlayerClass; ServerRules = sr.ServerRules; AllowBuff = sr.AllowBuff; if (sr.IntroText != null) IntroText = sr.IntroText; m_waterlevel = sr.WaterLevel; if (JoinType == StormGame.eJoinType.Permanent && GameName != "") { foreach (Zone z in Zones) { z.Description = GameName + " " + z.Description.Replace("(Instance)", ""); if (sr.IsLava) { z.IsLava = true; } if (sr.WaterLevel < z.Waterlevel) { z.Waterlevel = sr.WaterLevel; } } log.DebugFormat("StormGame loaded with TeamType set to {0}", TeamType.ToString()); StartupLog += string.Format("\nStormGame loaded with TeamType set to {0}", TeamType.ToString()); } else { foreach (Zone z in Zones) { z.Description = Name; if (sr.IsLava) { z.IsLava = true; } if (sr.WaterLevel < z.Waterlevel) { z.Waterlevel = sr.WaterLevel; } } } if (sr.IsLava) m_isLava = true; m_keepType = sr.KeepType; m_housingEnabled = sr.HousingEnabled; NoAutoZone = sr.NoAutoZone; if (KeepType >= 0) { LoadKeeps(); } LoadDoors(); if (HousingEnabled) { StartupLog += "\n" + HouseMgr.LoadHousingForRegion(ID); } if (sr.NoLoad == false || forceLoad) { LoadFromDatabase(); } else { log.Warn("NoLoad == true : will not load mobs or world objects!"); } if (UseWeatherManager && IsDungeon == false) { WeatherMgr.AddRegion(ID); } m_entranceLocation = sr.GetEntrance(); m_albCoopEntrance = sr.GetEntrance(); m_midEntrance = sr.GetEntrance(eRealm.Midgard); m_hibEntrance = sr.GetEntrance(eRealm.Hibernia); } /// <summary> /// Close this region as soon as all players have left /// </summary> public virtual void Close() { DestroyWhenEmpty = true; } public override void OnCollapse() { WeatherMgr.RemoveRegion(ID); try { if (m_instanceKeeps.Count > 0) { foreach (AbstractGameKeep keep in m_instanceKeeps.Values) { if (keep is StormRegionGameKeep) { if (GameServer.KeepManager.Keeps.Contains(keep.KeepID)) { GameServer.KeepManager.Keeps.Remove(keep.KeepID); } (keep as StormRegionGameKeep).RemoveFromWorld(); } if (keep is StormRegionGameKeepTower) { if (GameServer.KeepManager.Keeps.Contains(keep.KeepID)) { GameServer.KeepManager.Keeps.Remove(keep.KeepID); } (keep as StormRegionGameKeepTower).RemoveFromWorld(); } } } m_instanceKeeps.Clear(); m_instanceKeeps = null; m_instanceDoors.Clear(); m_instanceDoors = null; if (HousingEnabled) HouseMgr.RemoveHousingForRegion(ID); DOL.Events.GameEventMgr.RemoveAllHandlersForObject(this); } catch (Exception ex) { log.Error("StormRegion:OnCollapse", ex); StormRegionManager.LastError = "Errors OnCollapse:\n\n" + ex.Message + "\n\n" + ex.StackTrace + "\n\n"; } base.OnCollapse(); } public void LoadFromDatabase() { log.Debug("StormRegion: Load from database."); Assembly gasm = Assembly.GetAssembly(typeof(GameServer)); var mobObjs = GameServer.Database.SelectObjects<Mob>( "Region = " + ID); var staticObjs = GameServer.Database.SelectObjects<WorldObject>( "Region = " + ID); var bindPoints = GameServer.Database.SelectObjects<BindPoint>( "Region = " + ID); int count = mobObjs.Count + staticObjs.Count; if (count > 0) PreAllocateRegionSpace(count + 100); int myItemCount = staticObjs.Count; int myMobCount = 0; int myMerchantCount = 0; int myBindCount = bindPoints.Count; string allErrors = string.Empty; if (mobObjs.Count > 0) { foreach (Mob dbMob in mobObjs) { GameNPC newMob = null; string error = string.Empty; if (dbMob.Guild.Length > 0 && dbMob.Realm >= 0 && dbMob.Realm <= (int)eRealm._Last) { Type type = ScriptMgr.FindNPCGuildScriptClass(dbMob.Guild, (eRealm)dbMob.Realm); if (type != null) { try { Type[] constructorParams; if (dbMob.NPCTemplateID != -1) { constructorParams = new Type[] { typeof(INpcTemplate) }; ConstructorInfo handlerConstructor = typeof(GameNPC).GetConstructor(constructorParams); INpcTemplate template = NpcTemplateMgr.GetTemplate(dbMob.NPCTemplateID); newMob = (GameNPC)handlerConstructor.Invoke(new object[] { template }); } else { newMob = (GameNPC)type.Assembly.CreateInstance(type.FullName); } } catch (Exception e) { if (log.IsErrorEnabled) log.Error("LoadFromDatabase", e); } } } if (newMob == null) { string classtype = Properties.GAMENPC_DEFAULT_CLASSTYPE; if (dbMob.ClassType != null && dbMob.ClassType.Length > 0 && dbMob.ClassType != Mob.DEFAULT_NPC_CLASSTYPE) { classtype = dbMob.ClassType; } try { // special code to correct housing consignment merchants if (classtype == "DOL.GS.GameConsignmentMerchant" && HousingEnabled) { House house = HouseMgr.GetHouse(ID, dbMob.HouseNumber); if (house != null) { newMob = GameServer.ServerRules.CreateHousingConsignmentMerchant(house); } } if (newMob == null) { newMob = (GameNPC)gasm.CreateInstance(classtype, false); } } catch { error = classtype; } if (newMob == null) { foreach (Assembly asm in ScriptMgr.Scripts) { try { newMob = (GameNPC)asm.CreateInstance(classtype, false); error = string.Empty; } catch { error = classtype; } if (newMob != null) break; } if (newMob == null) { newMob = new GameNPC(); error = classtype; } } } if (!allErrors.Contains(error)) allErrors += " " + error + ","; if (newMob != null) { try { newMob.LoadFromDatabase(dbMob); if (newMob is GameMerchant) { myMerchantCount++; } else { myMobCount++; } } catch (Exception e) { if (log.IsErrorEnabled) { log.Error("Failed: " + newMob.GetType().FullName + ":LoadFromDatabase(" + dbMob.GetType().FullName + ");", e); StartupLog += string.Format("\nFailed: " + newMob.GetType().FullName + ":LoadFromDatabase(" + dbMob.GetType().FullName + ");"); } throw e; } newMob.AddToWorld(); } } } if (staticObjs.Count > 0) { foreach (WorldObject item in staticObjs) { GameStaticItem myItem = null; if (item.ClassType != null && item.ClassType.Length > 0) { try { myItem = (GameStaticItem)gasm.CreateInstance(item.ClassType, false); } catch { } if (myItem == null) { foreach (Assembly asm in ScriptMgr.Scripts) { try { myItem = (GameStaticItem)asm.CreateInstance(item.ClassType, false); } catch { } if (myItem != null) break; } if (myItem == null) myItem = new GameStaticItem(); } } else { myItem = new GameStaticItem(); } if (myItem != null) { myItem.LoadFromDatabase(item); myItem.AddToWorld(); } } } foreach (BindPoint point in bindPoints) { AddArea(new Area.BindArea("bind point", point)); } if (myMobCount + myItemCount + myMerchantCount + myBindCount > 0) { if (log.IsInfoEnabled) { log.Info(String.Format("Region: {0} ({1}) loaded {2} mobs, {3} merchants, {4} items {5} bindpoints, from DB ({6})", Description, ID, myMobCount, myMerchantCount, myItemCount, myBindCount, TimeManager.Name)); StartupLog += string.Format("\nRegion: {0} ({1}) loaded {2} mobs, {3} merchants, {4} items {5} bindpoints, from DB ({6})", Description, ID, myMobCount, myMerchantCount, myItemCount, myBindCount, TimeManager.Name); } log.Debug("Used Memory: " + GC.GetTotalMemory(false) / 1024 + "KB"); if (allErrors != string.Empty) { log.Error("Error loading the following NPC ClassType(s), GameNPC used instead:" + allErrors.TrimEnd(',')); StartupLog += string.Format("\nError loading the following NPC ClassType(s), GameNPC used instead:" + allErrors.TrimEnd(',')); } } log.Debug("Region area count " + Areas.Count); } protected virtual void LoadKeeps() { var keeps = GameServer.Database.SelectObjects<DBKeep>( "region = " + ID); if (keeps != null) { log.DebugFormat("StormRegion: Found {0} keeps. Region Allowed KeepType = {1}", keeps.Count, KeepType); StartupLog += string.Format("\nFound {0} keeps. Region Allowed KeepType = {1}", keeps.Count, KeepType); } m_instanceKeeps.Clear(); foreach (DBKeep datakeep in keeps) { bool isOld = false; bool isNew = false; //I don't want to touch the loading order of hookpoints, as i think they may depend on the //assumption keeps and towers are linked before population. So we will settle for a second //query. It's on server start, so it wont impact running performance. var currentKeepComponents = GameServer.Database.SelectObjects<DBKeepComponent>( "`KeepID` = '" + datakeep.KeepID + "'"); //Pass through, and depending on the outcome of the components, determine the 'age' of the keep. foreach (DBKeepComponent comp in currentKeepComponents) { if (comp.Skin >= 0 && comp.Skin <= 20) //these are the min/max ids for old keeps. isOld = true; if (comp.Skin > 20) //any skinID greater than this are ids for new keeps. isNew = true; } if (datakeep.KeepSkinType != eKeepSkinType.Any) { if (datakeep.KeepSkinType == eKeepSkinType.New && isNew == false) { continue; } else if (datakeep.KeepSkinType == eKeepSkinType.Old && isOld == false) { continue; } } else { //Keeps to load. 0 for Old Keeps, 1 for new keeps, 2 for both.", 2 if (KeepType == 0 && isNew) continue; if (KeepType == 1 && isOld) continue; } //If we've got this far, we are permitted to load as per normal! AbstractGameKeep keep = null; if ((datakeep.KeepID >> 8) != 0) { keep = new StormRegionGameKeepTower(); log.DebugFormat("StormRegion: Loading Tower {0} ({1})", datakeep.Name, datakeep.KeepID); StartupLog += string.Format("\nLoading Tower {0} ({1})", datakeep.Name, datakeep.KeepID); } else { keep = new StormRegionGameKeep(); log.DebugFormat("StormRegion: Loading Keep {0} ({1})", datakeep.Name, datakeep.KeepID); StartupLog += string.Format("\nLoading Keep {0} ({1})", datakeep.Name, datakeep.KeepID); } keep.Load(datakeep); m_instanceKeeps.Add(datakeep.KeepID, keep); if (GameServer.KeepManager.Keeps.Contains(datakeep.KeepID) == false) { GameServer.KeepManager.Keeps.Add(datakeep.KeepID, keep); } } // This adds owner keeps to towers (including portal keeps) foreach (AbstractGameKeep keep in m_instanceKeeps.Values) { StormRegionGameKeepTower tower = keep as StormRegionGameKeepTower; if (tower != null) { int index = tower.KeepID & 0xFF; StormRegionGameKeep ownerKeep = m_instanceKeeps[index] as StormRegionGameKeep; if (ownerKeep != null) { ownerKeep.AddTower(tower); } tower.Keep = ownerKeep; tower.OwnerKeepID = index; if (tower.OwnerKeepID < 10) { log.WarnFormat("Tower.OwnerKeepID < 10 for KeepID {0}. Doors on this tower will not be targetable! ({0} & 0xFF < 10). Choose a different KeepID to correct this issue.", tower.KeepID); } } } var keepcomponents = GameServer.Database.SelectAllObjects<DBKeepComponent>(); foreach (DBKeepComponent component in keepcomponents) { AbstractGameKeep keep = m_instanceKeeps[component.KeepID] as AbstractGameKeep; if (keep == null) { // we're only worried about components for our instanced keeps continue; } if (keep.DBKeep.KeepSkinType != eKeepSkinType.Any) { if (keep.DBKeep.KeepSkinType == eKeepSkinType.New && GameServer.KeepManager.IsNewKeepComponent(component.Skin) == false) { continue; } else if (keep.DBKeep.KeepSkinType == eKeepSkinType.Old && GameServer.KeepManager.IsNewKeepComponent(component.Skin)) { continue; } } else { // if use old keeps don't try to load new components if (KeepType == 0 && GameServer.KeepManager.IsNewKeepComponent(component.Skin)) continue; // if use new keeps don't try and load old components if (KeepType == 1 && !GameServer.KeepManager.IsNewKeepComponent(component.Skin)) continue; } StormRegionGameKeepComponent gamecomponent = new StormRegionGameKeepComponent(this); gamecomponent.LoadFromDatabase(component, keep); keep.KeepComponents.Add(gamecomponent); } if (m_instanceKeeps.Count > 0) { foreach (AbstractGameKeep keep in m_instanceKeeps.Values) { if (keep.KeepComponents.Count != 0) { keep.KeepComponents.Sort(); } } } //LoadHookPoints(); log.Info("Loaded " + m_instanceKeeps.Count + " keeps."); StartupLog += "\nLoaded " + m_instanceKeeps.Count + " keeps."; } protected virtual void LoadHookPoints() { Hashtable hookPointList = new Hashtable(); var dbkeepHookPoints = GameServer.Database.SelectAllObjects<DBKeepHookPoint>(); foreach (DBKeepHookPoint dbhookPoint in dbkeepHookPoints) { ArrayList currentArray; string key = dbhookPoint.KeepComponentSkinID + "H:" + dbhookPoint.Height; if (!hookPointList.ContainsKey(key)) { hookPointList.Add(key, new ArrayList()); } currentArray = (ArrayList)hookPointList[key]; currentArray.Add(dbhookPoint); } foreach (AbstractGameKeep keep in m_instanceKeeps.Values) { foreach (GameKeepComponent component in keep.KeepComponents) { string key = component.Skin + "H:" + component.Height; if ((hookPointList.ContainsKey(key))) { ArrayList HPlist = hookPointList[key] as ArrayList; if ((HPlist != null) && (HPlist.Count != 0)) { foreach (DBKeepHookPoint dbhookPoint in (ArrayList)hookPointList[key]) { GameKeepHookPoint myhookPoint = new GameKeepHookPoint(dbhookPoint, component); component.HookPoints.Add(dbhookPoint.HookPointID, myhookPoint); } continue; } } //add this to keep hookpoint system until DB is not full for (int i = 0; i < 38; i++) component.HookPoints.Add(i, new GameKeepHookPoint(i, component)); component.HookPoints.Add(65, new GameKeepHookPoint(0x41, component)); component.HookPoints.Add(97, new GameKeepHookPoint(0x61, component)); component.HookPoints.Add(129, new GameKeepHookPoint(0x81, component)); } } log.Info("Loading HookPoint items"); //fill existing hookpoints with objects foreach (AbstractGameKeep keep in m_instanceKeeps.Values) { foreach (GameKeepComponent component in keep.KeepComponents) { foreach (GameKeepHookPoint hp in component.HookPoints.Values) { DBKeepHookPointItem item = GameServer.Database.SelectObject<DBKeepHookPointItem>("KeepID = '" + component.Keep.KeepID + "' AND ComponentID = '" + component.ID + "' AND HookPointID = '" + hp.ID + "'"); if (item != null) { HookPointItem.Invoke(component.HookPoints[hp.ID] as GameKeepHookPoint, item.ClassType); } } } } } protected virtual void LoadDoors() { ushort skinID = Skin; log.Debug("Loading doors using region skin ID " + skinID); StartupLog += "\nLoading doors using region skin ID " + skinID; var dbdoors = GameServer.Database.SelectAllObjects<DBDoor>(); int doorCount = 0; int keepDoorCount = 0; foreach (DBDoor door in dbdoors) { IDoor newDoor = null; ushort zone = (ushort)(door.InternalID / 1000000); Zone doorZone = WorldMgr.GetZone(zone); if (doorZone == null) continue; // Note: If you want doors to work in a storm region they need to be defined in the skin region if (doorZone.ZoneRegion.ID == skinID) { // check if the door is a keep door foreach (AbstractArea area in GetAreasOfSpot(door.X, door.Y, door.Z)) { if (area is KeepArea) { newDoor = CreateStormRegionKeepDoor(); newDoor.LoadFromDatabase(door); keepDoorCount++; RegisterDoor(newDoor); break; } } //if the door is not a keep door, create a standard door if (newDoor == null) { newDoor = CreateStormRegionDoor(); newDoor.LoadFromDatabase(door); doorCount++; // special handling for ToA doors Region skinRegion = WorldMgr.GetRegion(Skin); if (skinRegion != null && skinRegion.Expansion == (int)eClientExpansion.TrialsOfAtlantis) { // use 999 as the zone id int doorID = newDoor.DoorID; int origDoorZone = (int)(doorID / 1000000); doorID -= origDoorZone * 1000000; doorID += TOA_DOOR_ZONE_ID * 1000000; RegisterDoor(newDoor, doorID); } else { RegisterDoor(newDoor); } } } } log.Debug("Loaded " + doorCount + " doors for " + Name); StartupLog += "\nLoaded " + doorCount + " doors for " + Name; if (keepDoorCount > 0) { log.Debug("Loaded " + keepDoorCount + " keep doors for " + Name); StartupLog += "\nLoaded " + keepDoorCount + " keep doors for " + Name; } } public virtual IDoor CreateStormRegionDoor() { return new StormRegionDoor(this); } public virtual IDoor CreateStormRegionKeepDoor() { return new StormRegionGameKeepDoor(this); } public override IEnumerable GetDoorsInRadius(int x, int y, int z, ushort radius, bool withDistance) { IEnumerable ienumDoors = GetInRadius(Zone.eGameObjectType.DOOR, x, y, z, radius, withDistance, false); // at this point we have all the doors of the skinned zone in the radius requested // now we replace these doors with the doors in this instance ArrayList listDoors = new ArrayList(); foreach (IDoor door in ienumDoors) { if (m_instanceDoors.ContainsKey(door.DoorID)) { listDoors.AddRange(m_instanceDoors[door.DoorID]); } } if (withDistance) { return new DoorDistanceEnumerator(x, y, z, listDoors); } return listDoors; } public override void OnPlayerEnterInstance(GamePlayer player) { base.OnPlayerEnterInstance(player); SendWeather(player); player.Out.SendTime(); if (JoinType == StormGame.eJoinType.Permanent) { if (PlayerClass != "") { if (player.GetType().FullName != PlayerClass) { // The player may have just joined this region so relogging is required. player.Out.SendMessage("You need to logout to complete the character creation process.", eChatType.CT_Staff, eChatLoc.CL_SystemWindow); player.Out.SendMessage("You need to logout to complete the character creation process.", eChatType.CT_Important, eChatLoc.CL_SystemWindow); if (player.Group != null) { player.Group.RemoveMember(player); } } } if (player.Client.Account.PrivLevel == (int)ePrivLevel.Player) { int bindRegion = player.DBCharacter.BindRegion; if (StormRegionManager.GetGameName((ushort)bindRegion) != StormRegionManager.GetGameName(this) && StormRegionManager.GetGameName(this) != "") { player.DBCharacter.BindHouseRegion = 0; player.Bind(true); player.SaveIntoDatabase(); } } } if (AllowBuff) { StormRegionManager.BuffSelf(player); player.Out.SendMessage("You can use the /buff command to buff both yourself and a pet!", eChatType.CT_Staff, eChatLoc.CL_SystemWindow); } } public override void OnPlayerLeaveInstance(GamePlayer player) { if (AllowBuff) { StormRegionManager.UnbuffSelf(player); } base.OnPlayerLeaveInstance(player); } /// <summary> /// Give any custom starter equipment to this player /// </summary> /// <param name="player"></param> public virtual void GiveStarterEquipment(GamePlayer player) { } /// <summary> /// If this is a game then find an equivilent zonepoint to move the player too. /// </summary> /// <param name="player"></param> /// <param name="zonePoint"></param> /// <returns></returns> public override bool OnZonePoint(GamePlayer player, ZonePoint zonePoint) { if (IsClosed && player.Client.Account.PrivLevel == 1) { player.Out.SendMessage("Sorry, this region is closed at the moment!", eChatType.CT_Staff, eChatLoc.CL_SystemWindow); return false; } if (JoinType == StormGame.eJoinType.Permanent && GameName != null && GameName != "") { StormRegions sr = StormRegionManager.GetGameRegionForSkin(GameName, zonePoint.TargetRegion); if (sr != null) { player.MoveTo(sr.ID, zonePoint.TargetX, zonePoint.TargetY, zonePoint.TargetZ, zonePoint.TargetHeading); } else { player.Out.SendMessage("Sorry, this region is not available for this shard.", eChatType.CT_Staff, eChatLoc.CL_SystemWindow); } return false; // don't let default handler move this player } return base.OnZonePoint(player, zonePoint); } } }
StormRegionManager
Code: Select all
using System; using System.Collections; using System.Collections.Generic; using System.Text; using DOL.Database; using DOL.Database.Attributes; using DOL.Events; using DOL.GS; using DOL.GS.Keeps; using DOL.GS.Spells; using DOL.GS.Effects; using DOL.GS.PacketHandler; using DOL.Storm; using System.Reflection; using log4net; namespace DOL.Storm { public class StormGamePortal : GameNPC { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public override eQuestIndicator GetQuestIndicator(GamePlayer player) { if (player.Level == 1) return eQuestIndicator.Available; return eQuestIndicator.None; } public override bool Interact(GamePlayer player) { if (player.Level != 1 && player.Client.Account.PrivLevel == 1) { SayTo(player, "Hello! You must be level 1 to start playing on another shard. Please create a new level 1 character, log on, and talk to me again."); return false; } if (base.Interact(player)) { SayTo(player, "Hello! So you want to start life in one of our custom shards?"); SayTo(player, "Storm Shards are just like stand alone servers but hosted inside Storm. You can talk to other Storm players using /irc as well as sending them private messages. Keep in mind once this character enters a Storm Shard it will never leave it!"); SayTo(player, "Choose a shard name from the following list:"); List<StormRegions> gameList = StormRegionManager.GetPublicStormGames(); foreach (StormRegions game in gameList) { player.Out.SendMessage("[" + game.GameName + "] - " + game.ShortDescription, eChatType.CT_System, eChatLoc.CL_PopupWindow); } if (player.Client.Account.PrivLevel > 1) { List<StormRegions> privateList = StormRegionManager.GetPrivateStormGames(); if (privateList.Count > 0) { player.Out.SendMessage("Private (GM only) Servers:", eChatType.CT_System, eChatLoc.CL_PopupWindow); foreach (StormRegions game in privateList) { player.Out.SendMessage("[" + game.GameName + "] - " + game.ShortDescription, eChatType.CT_System, eChatLoc.CL_PopupWindow); } } } } return false; } public override bool WhisperReceive(GameLiving source, string text) { GamePlayer player = source as GamePlayer; if (player == null || (player.Level != 1 && player.Client.Account.PrivLevel == 1)) return false; if (base.WhisperReceive(source, text)) { if (text == "ready") { GameLocation startLoc = player.TempProperties.getProperty<GameLocation>("SGSTARTLOC", null); if (startLoc != null) { if (player.Guild != null) { player.Guild.RemovePlayer(player.Name, player); } player.LastUniqueLocations[player.LastUniqueLocations.Length - 1] = startLoc; player.Stuck = true; player.SaveIntoDatabase(); log.InfoFormat("Player {0} is moving to StormGame {1}", player.Name, StormRegionManager.GetGameName(startLoc.RegionID)); player.Out.SendPlayerQuit(false); player.Quit(true); return true; } return false; } StormRegions gameRegion = StormRegionManager.GetStormGameStartingRegion(text); if (gameRegion == null || (gameRegion.IsPrivate && player.Client.Account.PrivLevel == 1)) return false; if (gameRegion != null) { SayTo(player, "You have chosen Storm Shard " + gameRegion.GameName + "! If you are sure you want to enter this shard, just say [ready] and you will be on your way!"); SayTo(player, "Once I make the change you will be logged out and moved to your chosen shard. Log back in to play!"); player.TempProperties.setProperty("SGSTARTLOC", gameRegion.GetEntrance(player.Realm)); if (player.Client.Account.PrivLevel == 1) { player.Out.SendMessage("Warning, answering [ready] will remove ALL items from your inventory, move you to the shard, and provide you with new equipment.", eChatType.CT_System, eChatLoc.CL_PopupWindow); } return true; } } return false; } } public class StormRegionPortal : GameNPC { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public override bool ShowTeleporterIndicator { get { return true; } } public override bool Interact(GamePlayer player) { if (base.Interact(player)) { SayTo(player, "Hello " + player.Name + "! I can send you to the following Storm regions:"); IList<StormRegions> gameList = StormRegionManager.GetPublicRegions(); foreach (StormRegions game in gameList) { player.Out.SendMessage("[" + game.Name + "]: " + game.ShortDescription, eChatType.CT_System, eChatLoc.CL_PopupWindow); } } return false; } public override bool WhisperReceive(GameLiving source, string text) { GamePlayer player = source as GamePlayer; if (player == null) return false; if (base.WhisperReceive(source, text)) { IList<StormRegions> gameList = StormRegionManager.GetPublicRegions(); foreach (StormRegions game in gameList) { if (game.Name == text) { SpellLine spellLine = SkillBase.GetSpellLine(GlobalSpellsLines.Mob_Spells); List<Spell> spellList = SkillBase.GetSpellList(GlobalSpellsLines.Mob_Spells); Spell spell = SkillBase.GetSpellByID(5999); // UniPortal spell. if (spell != null) { TargetObject = player; GameLocation loc = game.GetEntrance(); Teleport teleport = new Teleport(); teleport.X = loc.X; teleport.Y = loc.Y; teleport.Z = loc.Z; teleport.RegionID = loc.RegionID; teleport.Heading = loc.Heading; UniPortal portalHandler = new UniPortal(this, spell, spellLine, teleport); m_runningSpellHandler = portalHandler; portalHandler.CastSpell(); } else { player.MoveTo(game.GetEntrance()); } return true; } } } return false; } } public class StormRegionManager { private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public const ushort STARTINGREGIONID = 10000; public const ushort MAXREGIONID = 15000; public static string LastError = ""; private static bool m_loaded = false; [ScriptLoadedEvent] public static void OnScriptCompiled(DOLEvent e, object sender, EventArgs args) { log.Info("Storm region system initializing."); GameServer.Database.RegisterDataObject(typeof(StormRegions)); } [GameServerStartedEvent] public static void LoadStormRegions(DOLEvent e, object sender, EventArgs args) { if (!m_loaded) { m_loaded = true; var stormRegions = GameServer.Database.SelectAllObjects<StormRegions>(); if (stormRegions.Count > 0) { log.Warn("Loading Storm regions ..."); } foreach (StormRegions start in stormRegions) { // Storm regions less than this can be used to map storm regions info to standard regions (like NF). if (start.ID >= STARTINGREGIONID) { string messages = ""; StartStormRegion(start, false, out messages); } } } } public static bool StartStormRegion(StormRegions start, bool force, out string messages) { messages = ""; try { if (start.Enabled || force) { Type t = typeof(StormRegion); if (string.IsNullOrEmpty(start.RegionClass) == false) { t = Type.GetType(start.RegionClass); if (t == null) { t = ScriptMgr.GetType(start.RegionClass); } } if (t != null) { StormRegion s = (StormRegion)WorldMgr.CreateInstance(start.ID, start.Skin, t); if (s == null) { log.ErrorFormat("Failed to start Storm region [{0}] - {1}", start.ID, start.Name); messages = string.Format("Failed to start Storm region [{0}] - {1}", start.ID, start.Name); } else { s.LoadStormRegion(start, force); log.InfoFormat("Started Storm region [{0}] - {1} -----", start.ID, start.Name); messages = string.Format("Started Storm region [{0}] - {1}, Type: {2}\n\n", start.ID, start.Name, start.RegionClass); messages += s.StartupLog; messages += "\n\nSuccess!"; return true; } } else { log.ErrorFormat("Failed to start Storm region [{0}] - {1}, Type {2} not found.", start.ID, start.Name, start.RegionClass); messages = string.Format("Failed to start Storm region [{0}] - {1}, Type {2} not found.", start.ID, start.Name, start.RegionClass); } } } catch (Exception ex) { log.Error("StormRegion: unable to load region: " + ex.Message + ", " + ex.StackTrace); messages = "StormRegion: unable to load region: " + ex.Message + ", " + ex.StackTrace; } return false; } public static StormRegions GetStormRegion(ushort regionID) { StormRegions sr = GameServer.Database.SelectObject<StormRegions>("ID = " + regionID); if (sr != null) { return sr; } return new StormRegions(); } public static StormRegions GetStormGameStartingRegion(string gameName) { StormRegions sr = GameServer.Database.SelectObject<StormRegions>("GameName = '" + GameServer.Database.Escape(gameName) + "' and StartHere = 1") as StormRegions; if (sr != null) { return sr; } return null; } public static List<StormRegions> GetPublicStormGames() { IList<StormRegions> list = GameServer.Database.SelectObjects<StormRegions>("JoinType = " + (int)StormGame.eJoinType.Permanent + " and GameName <> '' and StartHere = 1 and Enabled = 1 and IsPrivate = 0"); Dictionary<string, StormRegions> gameList = new Dictionary<string, StormRegions>(); if (list != null) { foreach (StormRegions sr in list) { if (gameList.ContainsKey(sr.GameName) == false) { gameList.Add(sr.GameName, sr); } } return new List<StormRegions>(gameList.Values); } return new List<StormRegions>(); } public static List<StormRegions> GetPrivateStormGames() { IList<StormRegions> list = GameServer.Database.SelectObjects<StormRegions>("JoinType = " + (int)StormGame.eJoinType.Permanent + " and GameName <> '' and StartHere = 1 and Enabled = 1 and IsPrivate = 1"); Dictionary<string, StormRegions> gameList = new Dictionary<string, StormRegions>(); if (list != null) { foreach (StormRegions sr in list) { if (gameList.ContainsKey(sr.GameName) == false) { gameList.Add(sr.GameName, sr); } } return new List<StormRegions>(gameList.Values); } return new List<StormRegions>(); } public static IList<StormRegions> GetPublicRegions() { IList<StormRegions> list = GameServer.Database.SelectObjects<StormRegions>("IsPrivate = 0 and Enabled = 1 and GameName = ''"); return list; } /// <summary> /// Find a StormRegion that matches the game and skin /// </summary> /// <param name="gameName"></param> /// <param name="skinID"></param> /// <returns></returns> public static StormRegions GetGameRegionForSkin(string gameName, ushort skinID) { StormRegions sr = GameServer.Database.SelectObject<StormRegions>("GameName = '" + GameServer.Database.Escape(gameName) + "' AND Skin = " + skinID) as StormRegions; if (sr != null && sr.NoAutoZone) return null; // we do not want to allow automatic zoning into this region return sr; } public static string GetGameName(Region region) { if (region != null && region is StormRegion) { return (region as StormRegion).GameName; } return ""; } public static string GetGameName(ushort regionID) { StormRegions sr = GameServer.Database.SelectObject<StormRegions>("ID = " + regionID) as StormRegions; if (sr != null) return sr.GameName; return ""; } #region Spells for buffs private static Spell m_dexQui; public static Spell DexQui { get { if (m_dexQui == null) { DBSpell spell = new DBSpell(); spell.AllowAdd = false; spell.Type = "DexterityQuicknessBuff"; spell.Target = "Realm"; spell.CastTime = 0; spell.Range = 2000; spell.Duration = 30000; spell.Name = "Speed of Storm"; spell.Power = 0; spell.SpellID = 9090901; spell.Value = 100; spell.ClientEffect = 1526; spell.Icon = 1526; m_dexQui = new Spell(spell, 1); m_dexQui.IsShearable = true; } return m_dexQui; } } private static Spell m_strCon; public static Spell StrCon { get { if (m_strCon == null) { DBSpell spell = new DBSpell(); spell.AllowAdd = false; spell.Type = "StrengthConstitutionBuff"; spell.Target = "Realm"; spell.CastTime = 0; spell.Range = 2000; spell.Duration = 30000; spell.Name = "Might of Storm"; spell.Power = 0; spell.Value = 100; spell.ClientEffect = 1517; spell.Icon = 1517; spell.SpellID = 9090902; m_strCon = new Spell(spell, 1); m_strCon.IsShearable = true; } return m_strCon; } } private static Spell m_Acuity; public static Spell Acuity { get { if (m_Acuity == null) { DBSpell spell = new DBSpell(); spell.AllowAdd = false; spell.Type = "AcuityBuff"; spell.Target = "Realm"; spell.CastTime = 0; spell.Range = 2000; spell.Duration = 30000; spell.Name = "Cunning of Storm"; spell.Power = 0; spell.Value = 75; spell.ClientEffect = 1538; spell.Icon = 1538; spell.SpellID = 9090903; m_Acuity = new Spell(spell, 1); m_Acuity.IsShearable = true; } return m_Acuity; } } private static Spell m_dex; public static Spell Dex { get { if (m_dex == null) { DBSpell spell = new DBSpell(); spell.AllowAdd = false; spell.Type = "DexterityBuff"; spell.Target = "Realm"; spell.CastTime = 0; spell.Range = 2000; spell.Duration = 30000; spell.Name = "Agility of Storm"; spell.Power = 0; spell.Value = 75; spell.ClientEffect = 1476; spell.Icon = 1476; spell.SpellID = 9090904; m_dex = new Spell(spell, 1); m_dex.IsShearable = true; } return m_dex; } } private static Spell m_str; public static Spell Str { get { if (m_str == null) { DBSpell spell = new DBSpell(); spell.AllowAdd = false; spell.Type = "StrengthBuff"; spell.Target = "Realm"; spell.CastTime = 0; spell.Range = 2000; spell.Duration = 30000; spell.Name = "Strength of Storm"; spell.Power = 0; spell.Value = 75; spell.ClientEffect = 1457; spell.Icon = 1457; spell.SpellID = 9090905; m_str = new Spell(spell, 1); m_str.IsShearable = true; } return m_str; } } private static Spell m_con; public static Spell Con { get { if (m_con == null) { DBSpell spell = new DBSpell(); spell.AllowAdd = false; spell.Type = "ConstitutionBuff"; spell.Target = "Realm"; spell.CastTime = 0; spell.Range = 2000; spell.Duration = 30000; spell.Name = "Fortitude of Storm"; spell.Power = 0; spell.Value = 75; spell.ClientEffect = 1486; spell.Icon = 1486; spell.SpellID = 9090906; m_con = new Spell(spell, 1); m_con.IsShearable = true; } return m_con; } } private static Spell m_af; public static Spell AF { get { if (m_af == null) { DBSpell spell = new DBSpell(); spell.AllowAdd = false; spell.Type = "ArmorFactorBuff"; spell.Target = "Realm"; spell.CastTime = 0; spell.Range = 2000; spell.Duration = 30000; spell.Name = "Skin of Storm"; spell.Power = 0; spell.Value = 75; spell.EffectGroup = 1; // baseline AF spell.ClientEffect = 1467; spell.Icon = 1467; spell.SpellID = 9090907; m_af = new Spell(spell, 1); m_af.IsShearable = true; } return m_af; } } /// <summary> /// Forces the player to FULLY buff themselves. /// </summary> /// <param name="player"></param> public static void BuffSelf(GamePlayer player) { if (player == null) return; //Dex; ISpellHandler handler = ScriptMgr.CreateSpellHandler(player, Dex, BuffSpellLine); handler.StartSpell(player); //Con handler = ScriptMgr.CreateSpellHandler(player, Con, BuffSpellLine); handler.StartSpell(player); //Str handler = ScriptMgr.CreateSpellHandler(player, Str, BuffSpellLine); handler.StartSpell(player); //StrCon handler = ScriptMgr.CreateSpellHandler(player, StrCon, BuffSpellLine); handler.StartSpell(player); //DexQui handler = ScriptMgr.CreateSpellHandler(player, DexQui, BuffSpellLine); handler.StartSpell(player); //Acuity handler = ScriptMgr.CreateSpellHandler(player, Acuity, BuffSpellLine); handler.StartSpell(player); //AF handler = ScriptMgr.CreateSpellHandler(player, AF, BuffSpellLine); handler.StartSpell(player); } public static void BuffPet(GamePlayer player) { if (player == null || player.ControlledBrain == null) return; GameLiving target = player.ControlledBrain.Body; //Dex; ISpellHandler handler = ScriptMgr.CreateSpellHandler(player, Dex, BuffSpellLine); handler.StartSpell(target); //Con handler = ScriptMgr.CreateSpellHandler(player, Con, BuffSpellLine); handler.StartSpell(target); //Str handler = ScriptMgr.CreateSpellHandler(player, Str, BuffSpellLine); handler.StartSpell(target); //StrCon handler = ScriptMgr.CreateSpellHandler(player, StrCon, BuffSpellLine); handler.StartSpell(target); //DexQui handler = ScriptMgr.CreateSpellHandler(player, DexQui, BuffSpellLine); handler.StartSpell(target); //Acuity handler = ScriptMgr.CreateSpellHandler(player, Acuity, BuffSpellLine); handler.StartSpell(target); //AF handler = ScriptMgr.CreateSpellHandler(player, AF, BuffSpellLine); handler.StartSpell(target); } private static SpellLine m_spellLine; public static SpellLine BuffSpellLine { get { if (m_spellLine == null) { m_spellLine = SkillBase.GetSpellLine(GlobalSpellsLines.Character_Abilities); if (m_spellLine == null) //if we are still null, have a reserve! m_spellLine = new SpellLine("Storm Buffs", "Storm Buffs", "Enhancement", true); } return m_spellLine; } } /// <summary> /// Strips buffs from the player. /// </summary> /// <param name="player"></param> public static void UnbuffSelf(GamePlayer player) { if (player == null) return; GameSpellEffect effect = SpellHandler.FindEffectOnTarget(player, "StrengthBuff"); if (effect != null) effect.Cancel(true); effect = SpellHandler.FindEffectOnTarget(player, "DexterityBuff"); if (effect != null) effect.Cancel(true); effect = SpellHandler.FindEffectOnTarget(player, "ConstitutionBuff"); if (effect != null) effect.Cancel(true); effect = SpellHandler.FindEffectOnTarget(player, "ArmorFactorBuff"); if (effect != null) effect.Cancel(true); effect = SpellHandler.FindEffectOnTarget(player, "DexterityQuicknessBuff"); if (effect != null) effect.Cancel(true); effect = SpellHandler.FindEffectOnTarget(player, "StrengthConstitutionBuff"); if (effect != null) effect.Cancel(true); effect = SpellHandler.FindEffectOnTarget(player, "AcuityBuff"); if (effect != null) effect.Cancel(true); } #endregion } } namespace DOL.GS.Commands { [CmdAttribute( "&buff", ePrivLevel.Player, "Apply Storm buffs to self and any pet", "/buff")] public class StormRegionBuffCommandHandler : DOL.GS.Commands.AbstractCommandHandler, DOL.GS.Commands.ICommandHandler { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public void OnCommand(GameClient client, string[] args) { bool ok = false; if (client.Player == null || client.Player.IsIncapacitated) { return; } if (client.Account.PrivLevel > (int)ePrivLevel.Player) { ok = true; } else if (client.Player.CurrentRegion is StormRegion) { if (client.Player.CurrentRegion is PvPInstanceRegion) { if ((client.Player.CurrentRegion as PvPInstanceRegion).Game.AutoBuffingMatch) { ok = true; } } else if ((client.Player.CurrentRegion as StormRegion).AllowBuff) { ok = true; } } if (ok && client.Player.InCombat) { DisplayMessage(client, "This command can not be used during combat."); return; } if (ok) { StormRegionManager.BuffSelf(client.Player); StormRegionManager.BuffPet(client.Player); } } } [CmdAttribute( "&stormregion", ePrivLevel.GM, "This command is used to create a Storm region, a permanent copy of another region.", "To use this command go to the region you want to copy and stand where you want the entrance to be.", "Once there do '/stormregion create <name>' and a new Storm region will be created with the name provided.", "Once created you can use the following commands:", "/stormregion list [all] - Lists all the enabled storm regions; [all] also shows disabled", "/stormregion info - Display information about your current region", "/stormregion goto <id> [realm #] - Jump to the entrance of the given storm region", "/stormregion name <id> <name> - Name or rename a Storm region", "/stormregion MakeGame <id> <GameName> <Start here? true or false> <TeamType> <GamePlayerClass> <allow /buff? true or false> - Make this region a game using the parameters provided, GameName should be brief as it will be added to each player name, Regions that share the same GameName are considered part of the same game and should have the same GamePlayerClass", "/stormregion PlayerClass <GameName> <GamePlayerClass> - Change all regions with this GameName to use the provided PlayerClass", "/stormregion RegionClass <GameName> <RegionClass> - Change all regions with this GameName to the type RegionClass", "/stormregion ServerRules <GameName> <ServerRules> - Change all regions with this GameName to use these ServerRules", "/stormregion shortdesc <ID> <desc> - Change the short description for this storm region", "/stormregion teamtype <id> <rvr | coop | pvp> - Set this regions team type", "/stormregion entrance <id> - Change the entry location of this Storm region to your current location", "/stormregion (re)start <id> - Start or re-start this Storm region", "/stormregion stop <id> - Unload this Storm region", "/stormregion enable <id> - This Storm region will auto-start when the server starts", "/stormregion disable <id> - Stop this Storm region from loading on startup. You can still start this region manually using start.", "/stormregion allowedclasses <id> <string> - Sets the AllowedClasses field for this storm region.", "/stormregion private <id> - Toggles the private flag for this storm region.", "/stormregion autobuff <id> - Toggles the autobuff flag for this storm region.", "/stormregion [mid|hib|alb]entrance <id> - Set the entrance location", "/stormregion adddoor [update] - adds [or updates] the targeted door to the list of StormRegion doors" )] public class StormRegionCommandHandler : AbstractCommandHandler, ICommandHandler { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public void OnCommand(GameClient client, string[] args) { try { if (client.Player == null && args[1].ToLower() != "restart") { return; } if (args.Length < 2) { DisplaySyntax(client); return; } GamePlayer player = client.Player; switch (args[1].ToLower()) { case "create": { Region currentRegion = player.CurrentRegion; if (currentRegion == null || currentRegion.IsInstance || currentRegion.IsCustom) { DisplayMessage(client, "You cannot create a storm region from an instance or another storm region!"); return; } string name = String.Join(" ", args, 2, args.Length - 2); GameLocation loc = new GameLocation(name, player.CurrentRegionID, player.X, player.Y, player.Z, player.Heading); ushort startingID = 0; var stormRegions = GameServer.Database.SelectAllObjects<StormRegions>(); List<ushort> listStormRegions = new List<ushort>(); foreach (StormRegions stormRegion in stormRegions) { listStormRegions.Add(stormRegion.ID); } for (ushort count = DOL.Storm.StormRegionManager.STARTINGREGIONID; count <= DOL.Storm.StormRegionManager.MAXREGIONID; count++) { if (!listStormRegions.Contains(count)) { startingID = count; break; } } if (startingID == 0) { DisplayMessage(client, "Error: No empty regions available! Hard to believe!"); log.ErrorFormat("StormRegion create could not find an empty ID for {0}!", name); return; } if (WorldMgr.GetRegion(startingID) != null) { DisplayMessage(client, "Error: Region " + startingID + " is already in use!"); log.ErrorFormat("StormRegion create found ID {0} already in use for {1}!", startingID, name); return; } StormRegions stormregion = new StormRegions(startingID, name, "", name, player.CurrentRegionID, loc, player.CurrentZone.IsDivingEnabled, player.CurrentRegion.WaterLevel, true, player.CurrentRegion.IsRvR, false, StormGame.eTeamType.RvR, StormGame.eJoinType.Open); GameServer.Database.AddObject(stormregion); StormRegion s = (StormRegion)WorldMgr.CreateInstance(startingID, loc.RegionID, typeof(StormRegion)); if (s != null) { s.LoadStormRegion(stormregion); DisplayMessage(client, "New Storm region created! New region ID = " + startingID); } else { DisplayMessage(client, "Storm region created and added to the DB, but instance failed to start. New region ID = " + startingID); } break; } case "list": { List<StormRegions>stormRegions = new List<StormRegions>(GameServer.Database.SelectAllObjects<StormRegions>()); if (stormRegions != null) { bool showDisabled = false; if (args.Length > 2 && args[2].ToLower() == "all") showDisabled = true; stormRegions.Sort(delegate(StormRegions s1, StormRegions s2) { return s1.ID.CompareTo(s2.ID); }); foreach (StormRegions stormRegion in stormRegions) { bool isRunning = (WorldMgr.Regions[stormRegion.ID] == null) == false; if (showDisabled || stormRegion.Enabled || isRunning) { DisplayMessage(client, string.Format("[{0}] {1} {2} {3} {4}", stormRegion.ID, stormRegion.Name, (stormRegion.TeamType == 0 ? (stormRegion.IsRvR ? "[RvR]" : "") : "[" + ((StormGame.eTeamType)stormRegion.TeamType).ToString() + "]"), (stormRegion.Enabled ? (stormRegion.GameName == "" ? "" : "[" + stormRegion.GameName + "]") : (isRunning ? (stormRegion.GameName == "" ? "started/disabled" : "[" + stormRegion.GameName + "] started/disabled") : "disabled")), (stormRegion.IsPrivate ? "private" : ""))); } } } } break; case "goto": { ushort ID = Convert.ToUInt16((args[2])); eRealm realm = eRealm.Albion; if (args.Length > 3) realm = (eRealm)Convert.ToByte(args[3]); StormRegions sr = GetStormRegion(client, ID); if (sr != null && WorldMgr.GetRegion(sr.ID) != null) { if (!player.MoveTo(sr.GetEntrance(realm))) { DisplayMessage(client, "Error moving to Storm region. Has it been started?"); } } else { DisplayMessage(client, "Can't find Storm region. Has it been started?"); } break; } case "name": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } if (args.Length > 3) { string newName = String.Join(" ", args, 3, args.Length - 3); sr.Name = newName; sr.Description = newName; GameServer.Database.SaveObject(sr); Region region = WorldMgr.GetRegion(sr.ID); if (region != null) { StormRegion stormRegion = region as StormRegion; if (stormRegion != null) { stormRegion.SetName(newName); } } DisplayMessage(client, "Storm Region " + ID + " name changed to " + newName); } } break; case "info": { StormRegion sr = player.CurrentRegion as StormRegion; List<string> info = new List<string>(); info.Add("RegionID: " + player.CurrentRegionID); info.Add("IsRvR: " + player.CurrentRegion.IsRvR); info.Add("IsInstance: " + player.CurrentRegion.IsInstance); info.Add("IsCustom: " + player.CurrentRegion.IsCustom); if (sr != null) { info.Add(" "); info.Add("Storm Region - - - - - - -"); info.Add(" "); if (string.IsNullOrEmpty(sr.AllowedClasses) == false) { info.Add("AllowedClasses: " + sr.AllowedClasses); } info.Add("TeamType: " + sr.TeamType); info.Add("Skin: " + sr.Skin); } else { info.Add(" "); info.Add("Not a Storm Region"); } player.Out.SendCustomTextWindow("Storm Region Information", info); } break; case "shortdesc": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } if (args.Length > 3) { string shortDesc = String.Join(" ", args, 3, args.Length - 3); sr.ShortDescription = shortDesc; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " short description changed to " + shortDesc); } } break; case "private": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } sr.IsPrivate = !sr.IsPrivate; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " Private flag set to " + sr.IsPrivate); } break; case "autobuff": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } sr.AllowBuff = !sr.AllowBuff; GameServer.Database.SaveObject(sr); Region region = WorldMgr.GetRegion(sr.ID); if (region != null) { StormRegion stormRegion = region as StormRegion; if (stormRegion != null) { stormRegion.AllowBuff = sr.AllowBuff; } } DisplayMessage(client, "Storm Region " + ID + " AllowBuff (AutoBuff) flag set to " + sr.AllowBuff); } break; case "playerclass": { string gameName = args[2]; string playerClass = args[3]; if (playerClass != "") { GamePlayer tempPlayer = null; foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { tempPlayer = assembly.CreateInstance(playerClass, false, BindingFlags.CreateInstance, null, new object[] { this }, null, null) as GamePlayer; } catch (Exception) { } if (tempPlayer != null) break; } if (tempPlayer == null) { DisplayMessage(client, "Cannot create a GamePlayer of class " + playerClass); break; } } List<StormRegions> stormRegions = new List<StormRegions>(GameServer.Database.SelectObjects<StormRegions>("GameName = '" + GameServer.Database.Escape(gameName) + "'")); if (stormRegions != null) { foreach (StormRegions sr in stormRegions) { sr.PlayerClass = playerClass; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + sr.ID + " GamePlayerClass set to " + sr.PlayerClass); } } } break; case "regionclass": { string gameName = args[2]; string regionClass = args[3]; List<StormRegions> stormRegions = new List<StormRegions>(GameServer.Database.SelectObjects<StormRegions>("GameName = '" + GameServer.Database.Escape(gameName) + "'")); if (stormRegions != null) { foreach (StormRegions sr in stormRegions) { sr.RegionClass = regionClass; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + sr.ID + " RegionClass set to " + sr.RegionClass); } } } break; case "serverrules": { string gameName = args[2]; string serverRules = args[3]; List<StormRegions> stormRegions = new List<StormRegions>(GameServer.Database.SelectObjects<StormRegions>("GameName = '" + GameServer.Database.Escape(gameName) + "'")); if (stormRegions != null) { foreach (StormRegions sr in stormRegions) { sr.ServerRules = serverRules; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + sr.ID + " ServerRules set to " + sr.ServerRules); } } } break; case "gameinfo": { string gameName = args[2]; string desc = String.Join(" ", args, 3, args.Length - 3); List<StormRegions> stormRegions = new List<StormRegions>(GameServer.Database.SelectObjects<StormRegions>("GameName = '" + GameServer.Database.Escape(gameName) + "'")); if (stormRegions != null) { foreach (StormRegions sr in stormRegions) { sr.ShortDescription = desc; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + sr.ID + " short description set."); } } } break; case "allowedclasses": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) break; string desc = String.Join(" ", args, 3, args.Length - 3); sr.AllowedClasses = desc; GameServer.Database.SaveObject(sr); Region region = WorldMgr.GetRegion(sr.ID); if (region != null) { StormRegion stormRegion = region as StormRegion; if (stormRegion != null) { stormRegion.AllowedClasses = sr.AllowedClasses; } } DisplayMessage(client, "Storm Region " + sr.ID + " allowed classed set to " + sr.AllowedClasses); } break; case "makegame": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } if (args.Length > 5) { string newName = args[3]; bool startHere = Convert.ToBoolean(args[4]); sr.GameName = newName; string playerClass = args[6]; bool allowBuff = Convert.ToBoolean(args[7]); sr.PlayerClass = playerClass; List<StormRegions> stormRegions = new List<StormRegions>(GameServer.Database.SelectAllObjects<StormRegions>()); if (stormRegions != null) { foreach (StormRegions stormRegion in stormRegions) { if (stormRegion.GameName == newName && stormRegion.PlayerClass != playerClass) { DisplayMessage(client, "Player class changed to " + stormRegion.PlayerClass + " to match other regions of the same GameName"); sr.PlayerClass = stormRegion.PlayerClass; break; } } } try { StormGame.eTeamType teamType = (StormGame.eTeamType)Enum.Parse(typeof(StormGame.eTeamType), args[5], true); sr.TeamType = (ushort)teamType; if (teamType == StormGame.eTeamType.RvR || teamType == StormGame.eTeamType.Undefined) { sr.IsRvR = true; } } catch { DisplayMessage(client, "TeamType " + args[5] + " not valid."); break; } if (sr.TeamType == (ushort)StormGame.eTeamType.Undefined) { sr.TeamType = (ushort)StormGame.eTeamType.Coop; } sr.JoinType = (ushort)StormGame.eJoinType.Permanent; sr.StartHere = startHere; sr.AllowBuff = allowBuff; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " game name set to " + newName); DisplayMessage(client, "Storm Region " + ID + " start here is " + startHere); DisplayMessage(client, "Storm Region " + ID + " TeamType set to " + (StormGame.eTeamType)sr.TeamType); DisplayMessage(client, "Storm Region " + ID + " JoinType set to " + (StormGame.eJoinType)sr.JoinType); DisplayMessage(client, "Storm Region " + ID + " GamePlayerClass set to " + sr.PlayerClass); DisplayMessage(client, "Storm Region " + ID + " Allow /buff command set to " + sr.AllowBuff); } } break; case "teamtype": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } if (args.Length > 3) { switch (args[3].ToLower()) { case "rvr": sr.TeamType = (ushort)StormGame.eTeamType.RvR; sr.IsRvR = true; break; case "coop": sr.TeamType = (ushort)StormGame.eTeamType.Coop; sr.IsRvR = false; break; case "pvp": sr.TeamType = (ushort)StormGame.eTeamType.PvP; sr.IsRvR = true; break; default: DisplayMessage(client, "Unknown TeamType!"); return; } GameServer.Database.SaveObject(sr); Region region = WorldMgr.GetRegion(sr.ID); if (region != null) { StormRegion stormRegion = region as StormRegion; if (stormRegion != null) { stormRegion.TeamType = (StormGame.eTeamType)sr.TeamType; } } DisplayMessage(client, "Storm Region " + ID + " TeamType set to " + ((StormGame.eTeamType)sr.TeamType).ToString()); } } break; case "entrance": case "albentrance": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null || player.CurrentRegionID != sr.ID) { DisplayMessage(client, "You must be in the storm region to set an entrance!"); break; } GameLocation loc = new GameLocation(sr.Name, player.CurrentRegionID, player.X, player.Y, player.Z, player.Heading); sr.SetEntrance(loc); GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " Albion / Coop entrance set to your location"); } break; case "midentrance": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null || player.CurrentRegionID != sr.ID) { DisplayMessage(client, "You must be in the storm region to set an entrance!"); break; } GameLocation loc = new GameLocation(sr.Name, player.CurrentRegionID, player.X, player.Y, player.Z, player.Heading); sr.SetMidEntrance(loc); GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " Midgard entrance set to your location"); } break; case "hibentrance": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null || player.CurrentRegionID != sr.ID) { DisplayMessage(client, "You must be in the storm region to set an entrance!"); break; } GameLocation loc = new GameLocation(sr.Name, player.CurrentRegionID, player.X, player.Y, player.Z, player.Heading); sr.SetHibEntrance(loc); GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " Hibernia entrance set to your location"); } break; case "stop": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } if (WorldMgr.GetRegion(sr.ID) != null) { StormRegion stormRegion = WorldMgr.GetRegion(sr.ID) as StormRegion; if (stormRegion != null) { stormRegion.Close(); } } // check to see if region is closed if (WorldMgr.GetRegion(sr.ID) != null) { DisplayMessage(client, "Storm region stopped and will be unloaded when empty."); } else { DisplayMessage(client, "Storm region stopped and unloaded."); } } break; case "start": case "restart": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } if (WorldMgr.GetRegion(sr.ID) != null) { StormRegion stormRegion = WorldMgr.GetRegion(sr.ID) as StormRegion; if (stormRegion != null) { stormRegion.Close(); if (stormRegion.NumPlayers > 0) { DisplayMessage(client, "Players still in region. Region will close when last player zones out."); } } } string messages = ""; if (StormRegionManager.StartStormRegion(sr, true, out messages)) { DisplayMessage(client, "Storm region instance (re)started."); } else { DisplayMessage(client, "Storm region instance failed to start."); } if (StormRegionManager.LastError != "") { messages = StormRegionManager.LastError + "\n\n" + messages; StormRegionManager.LastError = ""; } if (messages != "" && client.Player != null) { client.Out.SendMessage(messages, eChatType.CT_System, eChatLoc.CL_PopupWindow); } } break; case "enable": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } sr.Enabled = true; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " will start when server starts."); } break; case "disable": { ushort ID = Convert.ToUInt16((args[2])); StormRegions sr = GetStormRegion(client, ID); if (sr == null) { break; } sr.Enabled = false; GameServer.Database.SaveObject(sr); DisplayMessage(client, "Storm Region " + ID + " will no longer start when the server starts."); } break; case "adddoor": { if ((client.Player.CurrentRegion is StormRegion) == false) { DisplayMessage(client, "You must be inside a storm region!."); break; } if (client.Player.TargetObject is GameDoor) { GameDoor door = client.Player.TargetObject as GameDoor; StormRegionDoors srDoor = new StormRegionDoors(); srDoor.StormRegionID = client.Player.CurrentRegionID; srDoor.DoorID = door.DoorID; srDoor.Name = door.Name; srDoor.DoorType = (byte)door.Type; srDoor.Guild = door.GuildName; srDoor.Health = door.Health; srDoor.MaxHealth = door.MaxHealth; srDoor.Level = door.Level; srDoor.Flags = door.Flag; srDoor.Realm = (byte)door.Realm; GameServer.Database.AddObject(srDoor); DisplayMessage(client, "Door Added!"); } else { DisplayMessage(client, "You must have a target door."); } } break; } } catch (Exception ex) { //DisplaySyntax(client); DisplayMessage(client.Player, ex.Message + ": " + ex.StackTrace); } } StormRegions GetStormRegion(GameClient client, ushort ID) { StormRegions sr = GameServer.Database.SelectObject<StormRegions>("ID = " + ID) as StormRegions; if (sr == null) { DisplayMessage(client, "Can't find StormRegions entry in database for ID " + ID); } return sr; } } [CmdAttribute( "&gameweather", ePrivLevel.Admin, "/gameweather <x> <width> <speed> <fog> <intensity> - set the weather of a storm region, if supported" )] public class GameWeatherCommandHandler : AbstractCommandHandler, ICommandHandler { public void OnCommand(GameClient client, string[] args) { try { if (client.Player.CurrentRegion is StormRegion) { (client.Player.CurrentRegion as StormRegion).SetWeather(Convert.ToUInt32(args[1]), Convert.ToUInt32(args[2]), Convert.ToUInt16(args[3]), Convert.ToUInt16(args[4]), Convert.ToUInt16(args[5])); } } catch { DisplaySyntax(client); } } } [CmdAttribute( "&gametime", ePrivLevel.Admin, "/gametime <time> - set the game time for this region, if supported." )] public class GameTimeCommandHandler : AbstractCommandHandler, ICommandHandler { public void OnCommand(GameClient client, string[] args) { try { client.Player.CurrentRegion.GameTime = Convert.ToUInt32(args[1]); foreach (GameClient c in WorldMgr.GetClientsOfRegion(client.Player.CurrentRegionID)) c.Out.SendTime(); } catch { DisplaySyntax(client); } } } [CmdAttribute( "&refreshkeep", ePrivLevel.GM, "re-send keep info", "/refreshkeep")] public class RefreshKeepCommandHandler : DOL.GS.Commands.AbstractCommandHandler, DOL.GS.Commands.ICommandHandler { /// <summary> /// Defines a logger for this class. /// </summary> private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public void OnCommand(GameClient client, string[] args) { try { if (client.Player != null) { GameKeepComponent component = client.Player.TargetObject as DOL.GS.Keeps.GameKeepComponent; AbstractGameKeep keep = null; if (component == null) { keep = GameServer.KeepManager.GetKeepCloseToSpot(client.Player.CurrentRegionID, client.Player, 10000); if (keep == null) { DisplayMessage(client, "Keep component not targeted and no keeps found in area."); return; } } else { keep = component.Keep; } if (keep == null) { DisplayMessage(client, "Component found but Keep is null!"); return; } client.Player.Out.SendKeepInfo(keep); foreach (DOL.GS.Keeps.GameKeepComponent keepComponent in keep.KeepComponents) { client.Player.Out.SendKeepComponentInfo(keepComponent); client.Out.SendKeepComponentDetailUpdate(keepComponent); } DisplayMessage(client, "Refreshed Keep ID " + keep.KeepID); } } catch (Exception ex) { if (client.Player != null) { client.Player.Out.SendMessage(ex.Message, eChatType.CT_Staff, eChatLoc.CL_PopupWindow); } log.Error(ex); } } } } namespace DOL.Database { [DataTable(TableName = "StormRegions")] public class StormRegions : DataObject { private ushort m_ID; private string m_name; private string m_gameName; private string m_description; private ushort m_skin; private string m_entrance; private string m_midEntrance; private string m_hibEntrance; private bool m_isDivingEnabled = true; private bool m_isRvR = false; private int m_waterLevel; private ushort m_teamType = (ushort)StormGame.eTeamType.RvR; private ushort m_joinType = (ushort)StormGame.eJoinType.Open; private string m_playerClass; private string m_serverRules; private bool m_isPrivate = true; private bool m_enabled = true; private string m_regionClass = ""; private bool m_startHere = false; private bool m_allowBuff = false; private string m_allowedClasses; private string m_shortDescription; private string m_introText; private bool m_useWeatherManager; private bool m_useTimeManager; private uint m_dayIncrement; private byte m_keepType; private bool m_housingEnabled; private bool m_isLava = false; private bool m_noLoad = false; private bool m_noAutoZone = false; private bool m_isClosed = false; private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public StormRegions() : base() { m_ID = 0; m_name = "Invalid"; m_gameName = ""; m_description = ""; m_skin = 0; m_entrance = ""; m_waterLevel = 0; m_playerClass = ""; m_serverRules = ""; m_regionClass = ""; m_enabled = true; m_startHere = false; m_allowBuff = false; m_allowedClasses = ""; m_introText = ""; m_shortDescription = ""; m_keepType = 0; m_housingEnabled = false; m_isLava = false; m_noLoad = false; m_noAutoZone = false; } public StormRegions(ushort ID, string name, string gameName, string description, ushort skin, GameLocation entrance, bool isDivingEnabled, int waterLevel, bool isPrivate, bool isRvR, bool isGame, StormGame.eTeamType teamType, StormGame.eJoinType joinType) : base() { m_ID = ID; m_name = name; m_gameName = gameName; m_description = description; m_skin = skin; SetEntrance(entrance); m_isDivingEnabled = isDivingEnabled; m_waterLevel = waterLevel; m_isPrivate = isPrivate; m_isRvR = isRvR; m_playerClass = ""; m_serverRules = ""; m_regionClass = ""; m_teamType = (ushort)teamType; m_joinType = (ushort)joinType; m_enabled = true; m_startHere = false; m_allowedClasses = ""; m_introText = ""; m_shortDescription = ""; m_useWeatherManager = true; m_useTimeManager = true; m_dayIncrement = 72; m_keepType = 0; m_housingEnabled = false; m_isLava = false; m_noLoad = false; m_noAutoZone = false; } [DataElement(AllowDbNull = false, Unique = true)] public ushort ID { get { return m_ID; } set { m_ID = value; } } [DataElement(AllowDbNull = false, Index = true, Varchar = 255)] public string Name { get { return m_name; } set { Dirty = true; m_name = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string GameName { get { return m_gameName; } set { Dirty = true; m_gameName = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string Description { get { return m_description; } set { Dirty = true; m_description = value; } } [DataElement(AllowDbNull = false)] public ushort Skin { get { return m_skin; } set { Dirty = true; m_skin = value; } } public void SetEntrance(GameLocation loc) { Entrance = loc.X + ";" + loc.Y + ";" + loc.Z + ";" + loc.Heading; } public void SetMidEntrance(GameLocation loc) { MidEntrance = loc.X + ";" + loc.Y + ";" + loc.Z + ";" + loc.Heading; } public void SetHibEntrance(GameLocation loc) { HibEntrance = loc.X + ";" + loc.Y + ";" + loc.Z + ";" + loc.Heading; } public GameLocation GetEntrance(eRealm realm = eRealm.Albion) { try { string[] entrance = Entrance.Split(';'); if (realm == eRealm.Midgard && string.IsNullOrEmpty(MidEntrance) == false) { entrance = MidEntrance.Split(';'); } else if (realm == eRealm.Hibernia && string.IsNullOrEmpty(HibEntrance) == false) { entrance = HibEntrance.Split(';'); } if (entrance.Length == 4) { return new GameLocation(Name, (ushort)ID, Convert.ToInt32(entrance[0]), Convert.ToInt32(entrance[1]), Convert.ToInt32(entrance[2]), Convert.ToUInt16(entrance[3])); } } catch { // do nothing, return null } return null; } [DataElement(AllowDbNull = false, Varchar = 255)] public string Entrance { get { return m_entrance; } set { Dirty = true; m_entrance = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string MidEntrance { get { return m_midEntrance; } set { Dirty = true; m_midEntrance = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string HibEntrance { get { return m_hibEntrance; } set { Dirty = true; m_hibEntrance = value; } } [DataElement(AllowDbNull = false)] public bool IsDivingEnabled { get { return m_isDivingEnabled; } set { Dirty = true; m_isDivingEnabled = value; } } [DataElement(AllowDbNull = false)] public bool IsRvR { get { return m_isRvR; } set { Dirty = true; m_isRvR = value; } } [DataElement(AllowDbNull = false)] public int WaterLevel { get { return m_waterLevel; } set { Dirty = true; m_waterLevel = value; } } [DataElement(AllowDbNull = false)] public bool IsPrivate { get { return m_isPrivate; } set { Dirty = true; m_isPrivate = value; } } [DataElement(AllowDbNull = false)] public ushort TeamType { get { try { return m_teamType; } catch { log.ErrorFormat("StormRegion: DB TeamType {0} not found, returning team type as undefined.", m_teamType); return (ushort)StormGame.eTeamType.Undefined; } } set { Dirty = true; m_teamType = (ushort)value; } } [DataElement(AllowDbNull = false)] public ushort JoinType { get { try { return m_joinType; } catch { log.ErrorFormat("StormRegion: DB JoinType {0} not found, returning join type as Open.", m_joinType); return (ushort)StormGame.eJoinType.Open; } } set { Dirty = true; m_joinType = (ushort)value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string PlayerClass { get { return m_playerClass; } set { Dirty = true; m_playerClass = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string ServerRules { get { return m_serverRules; } set { Dirty = true; m_serverRules = value; } } [DataElement(AllowDbNull = false)] public bool Enabled { get { return m_enabled; } set { Dirty = true; m_enabled = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string RegionClass { get { return m_regionClass; } set { Dirty = true; m_regionClass = value; } } [DataElement(AllowDbNull = false)] public bool StartHere { get { return m_startHere; } set { Dirty = true; m_startHere = value; } } [DataElement(AllowDbNull = false)] public bool AllowBuff { get { return m_allowBuff; } set { Dirty = true; m_allowBuff = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string AllowedClasses { get { return m_allowedClasses; } set { Dirty = true; m_allowedClasses = value; } } [DataElement(AllowDbNull = false, Varchar = 255)] public string ShortDescription { get { return m_shortDescription; } set { Dirty = true; m_shortDescription = value; } } [DataElement(AllowDbNull = false)] public string IntroText { get { return m_introText; } set { Dirty = true; m_introText = value; } } [DataElement(AllowDbNull = false)] public bool UseWeatherManager { get { return m_useWeatherManager; } set { Dirty = true; m_useWeatherManager = value; } } [DataElement(AllowDbNull = false)] public bool UseTimeManager { get { return m_useTimeManager; } set { Dirty = true; m_useTimeManager = value; } } [DataElement(AllowDbNull = false)] public uint DayIncrement { get { return m_dayIncrement; } set { Dirty = true; m_dayIncrement = value; } } [DataElement(AllowDbNull = false)] public byte KeepType { get { return m_keepType; } set { Dirty = true; m_keepType = value; } } [DataElement(AllowDbNull = false)] public bool HousingEnabled { get { return m_housingEnabled; } set { Dirty = true; m_housingEnabled = value; } } [DataElement(AllowDbNull = false)] public bool IsLava { get { return m_isLava; } set { Dirty = true; m_isLava = value; } } [DataElement(AllowDbNull = false)] public bool NoLoad { get { return m_noLoad; } set { Dirty = true; m_noLoad = value; } } [DataElement(AllowDbNull = false)] public bool NoAutoZone { get { return m_noAutoZone; } set { Dirty = true; m_noAutoZone= value; } } [DataElement(AllowDbNull = false)] public bool IsClosed { get { return m_isClosed; } set { Dirty = true; m_isClosed = value; } } } }
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA

Re: [SVN:r3237] RegionInstance to Implement Adventure Wings

Postby Leodagan » Thu Sep 19, 2013 7:00 am

I'm sorry I tried to take a look at stormRegion but I realized it's too far from what I was doing :)

I've put aside all "Persistence" matters from my RegionInstance class to keep it easy to code ;) (It's Region Instanced, as Region means an area without going through a jumppoint)

I didn't know there was already some work to implement real Instance persistence...
In my first post I've told that anyone needing persistence could easily inherit RegionInstance to make an hypothetic "WorldInstance".
As for the Manager honestly I was expecting persistent instances to go in Database using a specific Region Classtype and being loaded by standard Manager ;)


And to get back to this update, moving these methods to Base Class shouldn't impact any existing developments ;)
User avatar
Leodagan
Developer
 
Posts: 1350
Joined: Tue May 01, 2012 9:30 am
Website: https://daoc.freyad.net
Location: Lyon

Re: [SVN:r3237] RegionInstance to Implement Adventure Wings

Postby Tolakram » Thu Sep 19, 2013 12:00 pm

I think you are correct about persistent instances, I just wanted to get the code out there in case someone wanted to run with it. I put them in another table, and it's obviously not core worth code ... lots of crap.

My script coding style differs from my core coding style. For scripts I do whatever it takes to get something working quickly. That's the only way a custom server can ever see the light of day. :)
- Mark
User avatar
Tolakram
Storm / Storm-D2 Admin
 
Posts: 9189
Joined: Tue Jun 13, 2006 1:49 am
Location: Kentucky, USA


Return to “%s” DOL Code Contributions

Who is online

Users browsing this forum: No registered users and 1 guest