2019-06-18 22:55:32 -04:00
/ *
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Copyright ( C ) 2015 - 2019 Project Meteor Dev Team
This file is part of Project Meteor Server .
Project Meteor Server is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Project Meteor Server is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server . If not , see < https : www . gnu . org / licenses / > .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* /
2019-06-19 00:05:18 -04:00
using Meteor.Common ;
2019-06-19 01:10:15 -04:00
using Meteor.Map.actors.area ;
using Meteor.Map.actors.chara.npc ;
using Meteor.Map.Actors ;
using Meteor.Map.dataobjects ;
using Meteor.Map.lua ;
using Meteor.Map.packets.send ;
using Meteor.Map.packets.send.actor ;
2016-01-17 23:36:34 -05:00
using MySql.Data.MySqlClient ;
using System ;
using System.Collections.Generic ;
using System.Linq ;
2019-06-19 01:10:15 -04:00
using Meteor.Map.actors.group ;
using Meteor.Map.packets.WorldPackets.Receive ;
using Meteor.Map.packets.WorldPackets.Send.Group ;
2017-01-16 19:14:13 -05:00
using System.Threading ;
2019-06-19 01:10:15 -04:00
using Meteor.Map.actors.director ;
using Meteor.Map.actors.chara.ai ;
using Meteor.Map.actors.chara ;
using Meteor.Map.actors.chara.player ;
using Meteor.Map.packets.send.actor.inventory ;
2016-01-17 23:36:34 -05:00
2019-06-19 01:10:15 -04:00
namespace Meteor.Map
2016-01-17 23:36:34 -05:00
{
class WorldManager
{
private DebugProg debug = new DebugProg ( ) ;
private WorldMaster worldMaster = new WorldMaster ( ) ;
private Dictionary < uint , Zone > zoneList ;
2016-07-31 22:30:54 -04:00
private Dictionary < uint , List < SeamlessBoundry > > seamlessBoundryList ;
2016-05-29 15:14:09 -04:00
private Dictionary < uint , ActorClass > actorClasses = new Dictionary < uint , ActorClass > ( ) ;
2016-12-21 09:27:51 -05:00
private Dictionary < ulong , Party > currentPlayerParties = new Dictionary < ulong , Party > ( ) ; //GroupId, Party object
2017-08-29 01:15:12 +01:00
private Dictionary < uint , StatusEffect > statusEffectList = new Dictionary < uint , StatusEffect > ( ) ;
private Dictionary < ushort , BattleCommand > battleCommandList = new Dictionary < ushort , BattleCommand > ( ) ;
2019-06-08 21:11:51 -07:00
private Dictionary < Tuple < byte , short > , List < ushort > > battleCommandIdByLevel = new Dictionary < Tuple < byte , short > , List < ushort > > ( ) ; //Holds battle command ids keyed by class id and level (in that order)
2018-04-18 16:06:41 -05:00
private Dictionary < ushort , BattleTrait > battleTraitList = new Dictionary < ushort , BattleTrait > ( ) ;
private Dictionary < byte , List < ushort > > battleTraitIdsForClass = new Dictionary < byte , List < ushort > > ( ) ;
2017-09-12 01:24:02 +01:00
private Dictionary < uint , ModifierList > battleNpcGenusMods = new Dictionary < uint , ModifierList > ( ) ;
private Dictionary < uint , ModifierList > battleNpcPoolMods = new Dictionary < uint , ModifierList > ( ) ;
private Dictionary < uint , ModifierList > battleNpcSpawnMods = new Dictionary < uint , ModifierList > ( ) ;
2016-01-17 23:36:34 -05:00
2016-01-19 21:06:41 -05:00
private Server mServer ;
2017-08-26 04:08:26 +01:00
private const int MILIS_LOOPTIME = 333 ;
2017-01-16 19:14:13 -05:00
private Timer mZoneTimer ;
2017-09-17 15:04:29 -04:00
//Zone Server Groups
2017-04-15 16:33:56 -04:00
public Dictionary < ulong , Group > mContentGroups = new Dictionary < ulong , Group > ( ) ;
2017-09-17 15:04:29 -04:00
public Dictionary < ulong , RelationGroup > mRelationGroups = new Dictionary < ulong , RelationGroup > ( ) ;
public Dictionary < ulong , TradeGroup > mTradeGroups = new Dictionary < ulong , TradeGroup > ( ) ;
2017-04-15 16:33:56 -04:00
private Object groupLock = new Object ( ) ;
2017-10-08 12:26:22 -04:00
private Object tradeLock = new Object ( ) ;
2017-04-15 16:33:56 -04:00
public ulong groupIndexId = 1 ;
2016-01-19 21:06:41 -05:00
public WorldManager ( Server server )
{
mServer = server ;
}
2016-01-17 23:36:34 -05:00
public void LoadZoneList ( )
{
zoneList = new Dictionary < uint , Zone > ( ) ;
2016-03-20 19:29:38 -04:00
int count1 = 0 ;
int count2 = 0 ;
2017-03-25 04:36:19 +00:00
2016-01-17 23:36:34 -05:00
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
string query = @ "
SELECT
id ,
zoneName ,
2016-02-07 13:05:54 -05:00
regionId ,
2017-04-29 20:30:54 -04:00
classPath ,
2016-01-17 23:36:34 -05:00
dayMusic ,
nightMusic ,
battleMusic ,
2016-02-07 13:05:54 -05:00
isIsolated ,
2016-01-17 23:36:34 -05:00
isInn ,
canRideChocobo ,
canStealth ,
2017-06-09 04:17:08 +01:00
isInstanceRaid ,
loadNavMesh
2016-08-29 13:39:50 -04:00
FROM server_zones
WHERE zoneName IS NOT NULL and serverIp = @ip and serverPort = @port ";
2016-01-17 23:36:34 -05:00
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
2016-08-29 13:39:50 -04:00
cmd . Parameters . AddWithValue ( "@ip" , ConfigConstants . OPTIONS_BINDIP ) ;
cmd . Parameters . AddWithValue ( "@port" , ConfigConstants . OPTIONS_PORT ) ;
2016-01-17 23:36:34 -05:00
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
2017-06-09 04:17:08 +01:00
Zone zone = new Zone ( reader . GetUInt32 ( 0 ) , reader . GetString ( 1 ) , reader . GetUInt16 ( 2 ) , reader . GetString ( 3 ) , reader . GetUInt16 ( 4 ) , reader . GetUInt16 ( 5 ) ,
reader . GetUInt16 ( 6 ) , reader . GetBoolean ( 7 ) , reader . GetBoolean ( 8 ) , reader . GetBoolean ( 9 ) , reader . GetBoolean ( 10 ) , reader . GetBoolean ( 11 ) , reader . GetBoolean ( 12 ) ) ;
2022-02-05 14:05:32 -05:00
zoneList [ zone . ZoneId ] = zone ;
2016-03-20 19:29:38 -04:00
count1 + + ;
}
}
}
catch ( MySqlException e )
{ Console . WriteLine ( e ) ; }
finally
{
conn . Dispose ( ) ;
}
}
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
string query = @ "
2022-02-05 12:15:22 -05:00
SELECT
2016-03-20 19:29:38 -04:00
parentZoneId ,
privateAreaName ,
2017-03-07 00:09:37 -05:00
privateAreaType ,
2016-03-20 19:29:38 -04:00
className ,
dayMusic ,
nightMusic ,
battleMusic
FROM server_zones_privateareas
WHERE privateAreaName IS NOT NULL ";
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
uint parentZoneId = reader . GetUInt32 ( "parentZoneId" ) ;
if ( zoneList . ContainsKey ( parentZoneId ) )
{
Zone parent = zoneList [ parentZoneId ] ;
2022-02-05 14:05:32 -05:00
PrivateArea privArea = new PrivateArea ( parent , reader . GetString ( "className" ) , reader . GetString ( "privateAreaName" ) , reader . GetInt32 ( "privateAreaType" ) , reader . GetUInt16 ( "dayMusic" ) , reader . GetUInt16 ( "nightMusic" ) , reader . GetUInt16 ( "battleMusic" ) ) ;
2016-06-14 21:29:10 +01:00
parent . AddPrivateArea ( privArea ) ;
2016-03-20 19:29:38 -04:00
}
else
continue ;
count2 + + ;
2016-01-17 23:36:34 -05:00
}
}
}
catch ( MySqlException e )
{ Console . WriteLine ( e ) ; }
finally
{
conn . Dispose ( ) ;
}
}
2016-06-14 22:54:02 +01:00
Program . Log . Info ( String . Format ( "Loaded {0} zones and {1} private areas." , count1 , count2 ) ) ;
2016-01-17 23:36:34 -05:00
}
2016-07-31 22:30:54 -04:00
public void LoadSeamlessBoundryList ( )
{
2016-07-31 23:00:38 -04:00
seamlessBoundryList = new Dictionary < uint , List < SeamlessBoundry > > ( ) ;
2016-07-31 22:30:54 -04:00
int count = 0 ;
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
string query = @ "
SELECT
*
FROM server_seamless_zonechange_bounds ";
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
uint id = reader . GetUInt32 ( "id" ) ;
uint regionId = reader . GetUInt32 ( "regionId" ) ;
uint zoneId1 = reader . GetUInt32 ( "zoneId1" ) ;
uint zoneId2 = reader . GetUInt32 ( "zoneId2" ) ;
float z1_x1 = reader . GetFloat ( "zone1_boundingbox_x1" ) ;
float z1_y1 = reader . GetFloat ( "zone1_boundingbox_y1" ) ;
float z1_x2 = reader . GetFloat ( "zone1_boundingbox_x2" ) ;
float z1_y2 = reader . GetFloat ( "zone1_boundingbox_y2" ) ;
float z2_x1 = reader . GetFloat ( "zone2_boundingbox_x1" ) ;
float z2_y1 = reader . GetFloat ( "zone2_boundingbox_y1" ) ;
float z2_x2 = reader . GetFloat ( "zone2_boundingbox_x2" ) ;
float z2_y2 = reader . GetFloat ( "zone2_boundingbox_y2" ) ;
float m_x1 = reader . GetFloat ( "merge_boundingbox_x1" ) ;
float m_y1 = reader . GetFloat ( "merge_boundingbox_y1" ) ;
float m_x2 = reader . GetFloat ( "merge_boundingbox_x2" ) ;
float m_y2 = reader . GetFloat ( "merge_boundingbox_y2" ) ;
if ( ! seamlessBoundryList . ContainsKey ( regionId ) )
seamlessBoundryList . Add ( regionId , new List < SeamlessBoundry > ( ) ) ;
seamlessBoundryList [ regionId ] . Add ( new SeamlessBoundry ( regionId , zoneId1 , zoneId2 , z1_x1 , z1_y1 , z1_x2 , z1_y2 , z2_x1 , z2_y1 , z2_x2 , z2_y2 , m_x1 , m_y1 , m_x2 , m_y2 ) ) ;
count + + ;
}
}
}
catch ( MySqlException e )
{ Console . WriteLine ( e ) ; }
finally
{
conn . Dispose ( ) ;
}
}
Program . Log . Info ( String . Format ( "Loaded {0} region seamless boundries." , count ) ) ;
}
2016-05-29 15:14:09 -04:00
public void LoadActorClasses ( )
2016-01-20 23:18:10 -05:00
{
int count = 0 ;
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
string query = @ "
SELECT
2017-01-10 23:47:37 -05:00
gamedata_actor_class . id ,
2016-05-29 15:14:09 -04:00
classPath ,
2016-01-28 23:24:20 -05:00
displayNameId ,
2016-07-24 10:21:45 -04:00
propertyFlags ,
2017-01-10 16:43:03 -05:00
eventConditions ,
pushCommand ,
pushCommandSub ,
pushCommandPriority
2016-01-28 23:24:20 -05:00
FROM gamedata_actor_class
2017-01-10 16:43:03 -05:00
LEFT JOIN gamedata_actor_pushcommand
ON gamedata_actor_class . id = gamedata_actor_pushcommand . id
2016-06-12 18:43:41 -04:00
WHERE classPath < > ' '
2016-01-20 23:18:10 -05:00
";
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
2016-05-29 15:14:09 -04:00
uint id = reader . GetUInt32 ( "id" ) ;
string classPath = reader . GetString ( "classPath" ) ;
2022-02-05 14:05:32 -05:00
int nameId = reader . GetInt32 ( "displayNameId" ) ;
2016-06-12 18:43:41 -04:00
string eventConditions = null ;
2016-07-24 10:21:45 -04:00
uint propertyFlags = reader . GetUInt32 ( "propertyFlags" ) ;
if ( ! reader . IsDBNull ( 4 ) )
2016-06-12 18:43:41 -04:00
eventConditions = reader . GetString ( "eventConditions" ) ;
else
eventConditions = "{}" ;
2016-01-23 22:11:45 -05:00
2017-01-10 16:43:03 -05:00
ushort pushCommand = 0 ;
ushort pushCommandSub = 0 ;
byte pushCommandPriority = 0 ;
if ( ! reader . IsDBNull ( reader . GetOrdinal ( "pushCommand" ) ) )
{
pushCommand = reader . GetUInt16 ( "pushCommand" ) ;
pushCommandSub = reader . GetUInt16 ( "pushCommandSub" ) ;
pushCommandPriority = reader . GetByte ( "pushCommandPriority" ) ;
}
ActorClass actorClass = new ActorClass ( id , classPath , nameId , propertyFlags , eventConditions , pushCommand , pushCommandSub , pushCommandPriority ) ;
2016-05-29 15:14:09 -04:00
actorClasses . Add ( id , actorClass ) ;
2016-01-20 23:18:10 -05:00
count + + ;
}
}
}
catch ( MySqlException e )
{ Console . WriteLine ( e ) ; }
finally
{
conn . Dispose ( ) ;
}
}
2016-06-14 22:54:02 +01:00
Program . Log . Info ( String . Format ( "Loaded {0} actor classes." , count ) ) ;
2016-01-20 23:18:10 -05:00
}
2016-05-29 15:14:09 -04:00
public void LoadSpawnLocations ( )
2016-01-24 03:10:17 -05:00
{
int count = 0 ;
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
string query = @ "
SELECT
2016-06-09 22:58:03 -04:00
actorClassId ,
uniqueId ,
2016-05-29 15:14:09 -04:00
zoneId ,
privateAreaName ,
privateAreaLevel ,
2016-01-24 03:10:17 -05:00
positionX ,
positionY ,
positionZ ,
rotation ,
actorState ,
animationId ,
2016-05-29 15:14:09 -04:00
customDisplayName
FROM server_spawn_locations
2016-01-24 03:10:17 -05:00
";
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
2016-08-29 13:39:50 -04:00
{
uint zoneId = reader . GetUInt32 ( "zoneId" ) ;
uint classId = reader . GetUInt32 ( "actorClassId" ) ;
if ( ! actorClasses . ContainsKey ( classId ) )
continue ;
if ( ! zoneList . ContainsKey ( zoneId ) )
continue ;
Zone zone = zoneList [ zoneId ] ;
if ( zone = = null )
continue ;
2016-01-28 23:24:20 -05:00
string customName = null ;
2016-06-09 22:58:03 -04:00
if ( ! reader . IsDBNull ( 11 ) )
2016-05-29 15:14:09 -04:00
customName = reader . GetString ( "customDisplayName" ) ;
2016-08-29 13:39:50 -04:00
string uniqueId = reader . GetString ( "uniqueId" ) ;
2016-05-29 15:14:09 -04:00
string privAreaName = reader . GetString ( "privateAreaName" ) ;
2022-02-05 14:05:32 -05:00
int privAreaType = reader . GetInt32 ( "privateAreaLevel" ) ;
2016-05-29 15:14:09 -04:00
float x = reader . GetFloat ( "positionX" ) ;
float y = reader . GetFloat ( "positionY" ) ;
float z = reader . GetFloat ( "positionZ" ) ;
float rot = reader . GetFloat ( "rotation" ) ;
ushort state = reader . GetUInt16 ( "actorState" ) ;
uint animId = reader . GetUInt32 ( "animationId" ) ;
2016-08-29 13:39:50 -04:00
2022-02-05 14:05:32 -05:00
SpawnLocation spawn = new SpawnLocation ( classId , uniqueId , zoneId , privAreaName , privAreaType , x , y , z , rot , state , animId ) ;
2016-05-29 15:14:09 -04:00
2016-06-14 22:54:02 +01:00
zone . AddSpawnLocation ( spawn ) ;
2016-05-29 15:14:09 -04:00
count + + ;
2016-01-24 03:10:17 -05:00
}
}
2016-05-29 15:14:09 -04:00
2016-01-24 03:10:17 -05:00
}
catch ( MySqlException e )
{ Console . WriteLine ( e ) ; }
finally
{
conn . Dispose ( ) ;
}
}
2016-06-14 22:54:02 +01:00
Program . Log . Info ( String . Format ( "Loaded {0} spawn(s)." , count ) ) ;
2016-05-29 15:14:09 -04:00
}
2017-09-05 23:32:57 +01:00
public void LoadBattleNpcs ( )
{
2017-09-12 01:24:02 +01:00
LoadBattleNpcModifiers ( "server_battlenpc_genus_mods" , "genusId" , battleNpcGenusMods ) ;
LoadBattleNpcModifiers ( "server_battlenpc_pool_mods" , "poolId" , battleNpcPoolMods ) ;
LoadBattleNpcModifiers ( "server_battlenpc_spawn_mods" , "bnpcId" , battleNpcSpawnMods ) ;
2017-09-05 23:32:57 +01:00
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
var query = @ "
2017-09-10 03:41:58 +01:00
SELECT bsl . bnpcId , bsl . groupId , bsl . positionX , bsl . positionY , bsl . positionZ , bsl . rotation ,
2017-09-16 02:50:32 +01:00
bgr . groupId , bgr . poolId , bgr . scriptName , bgr . minLevel , bgr . maxLevel , bgr . respawnTime , bgr . hp , bgr . mp ,
2017-09-07 22:02:02 +01:00
bgr . dropListId , bgr . allegiance , bgr . spawnType , bgr . animationId , bgr . actorState , bgr . privateAreaName , bgr . privateAreaLevel , bgr . zoneId ,
2017-09-16 02:50:32 +01:00
bpo . poolId , bpo . genusId , bpo . actorClassId , bpo . currentJob , bpo . combatSkill , bpo . combatDelay , bpo . combatDmgMult , bpo . aggroType ,
2017-09-07 22:02:02 +01:00
bpo . immunity , bpo . linkType , bpo . skillListId , bpo . spellListId ,
2017-09-12 01:24:02 +01:00
bge . genusId , bge . modelSize , bge . speed , bge . kindredId , bge . detection , bge . hpp , bge . mpp , bge . tpp , bge . str , bge . vit , bge . dex ,
2017-09-05 23:32:57 +01:00
bge . int , bge . mnd , bge . pie , bge . att , bge . acc , bge . def , bge . eva , bge . slash , bge . pierce , bge . h2h , bge . blunt ,
2017-09-16 02:50:32 +01:00
bge . fire , bge . ice , bge . wind , bge . lightning , bge . earth , bge . water , bge . element
2017-09-07 22:02:02 +01:00
FROM server_battlenpc_spawn_locations bsl
INNER JOIN server_battlenpc_groups bgr ON bsl . groupId = bgr . groupId
INNER JOIN server_battlenpc_pools bpo ON bgr . poolId = bpo . poolId
INNER JOIN server_battlenpc_genus bge ON bpo . genusId = bge . genusId
2017-09-10 03:41:58 +01:00
WHERE bgr . zoneId = @zoneId GROUP BY bsl . bnpcId ;
2017-09-05 23:32:57 +01:00
";
2017-09-06 00:28:49 +01:00
2017-09-07 22:02:02 +01:00
var count = 0 ;
foreach ( var zonePair in zoneList )
{
2017-09-12 01:24:02 +01:00
Area zone = zonePair . Value ;
2017-09-07 22:02:02 +01:00
2017-09-05 23:32:57 +01:00
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
2017-09-07 22:02:02 +01:00
cmd . Parameters . AddWithValue ( "@zoneId" , zonePair . Key ) ;
2017-09-05 23:32:57 +01:00
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
int actorId = zone . GetActorCount ( ) + 1 ;
2017-09-07 22:02:02 +01:00
// todo: add to private areas, set up immunity, mob linking,
2017-09-10 03:41:58 +01:00
// - load skill/spell/drop lists, set detection icon, load pool/family/group mods
2017-09-07 22:02:02 +01:00
2017-09-05 23:32:57 +01:00
var battleNpc = new BattleNpc ( actorId , Server . GetWorldManager ( ) . GetActorClass ( reader . GetUInt32 ( "actorClassId" ) ) ,
2017-09-07 22:02:02 +01:00
reader . GetString ( "scriptName" ) , zone , reader . GetFloat ( "positionX" ) , reader . GetFloat ( "positionY" ) , reader . GetFloat ( "positionZ" ) , reader . GetFloat ( "rotation" ) ,
2017-09-05 23:32:57 +01:00
reader . GetUInt16 ( "actorState" ) , reader . GetUInt32 ( "animationId" ) , "" ) ;
2017-09-10 03:41:58 +01:00
battleNpc . SetBattleNpcId ( reader . GetUInt32 ( "bnpcId" ) ) ;
2017-09-12 01:24:02 +01:00
battleNpc . poolId = reader . GetUInt32 ( "poolId" ) ;
battleNpc . genusId = reader . GetUInt32 ( "genusId" ) ;
battleNpcPoolMods . TryGetValue ( battleNpc . poolId , out battleNpc . poolMods ) ;
battleNpcGenusMods . TryGetValue ( battleNpc . genusId , out battleNpc . genusMods ) ;
battleNpcSpawnMods . TryGetValue ( battleNpc . GetBattleNpcId ( ) , out battleNpc . spawnMods ) ;
2019-05-27 23:05:20 -07:00
battleNpc . SetMod ( ( uint ) Modifier . MovementSpeed , reader . GetByte ( "speed" ) ) ;
2017-09-07 22:02:02 +01:00
battleNpc . neutral = reader . GetByte ( "aggroType" ) = = 0 ;
battleNpc . SetDetectionType ( reader . GetUInt32 ( "detection" ) ) ;
2017-09-05 23:32:57 +01:00
battleNpc . kindredType = ( KindredType ) reader . GetUInt32 ( "kindredId" ) ;
battleNpc . npcSpawnType = ( NpcSpawnType ) reader . GetUInt32 ( "spawnType" ) ;
2017-09-07 22:02:02 +01:00
battleNpc . charaWork . parameterSave . state_mainSkill [ 0 ] = reader . GetByte ( "currentJob" ) ;
2017-09-06 00:28:49 +01:00
battleNpc . charaWork . parameterSave . state_mainSkillLevel = ( short ) Program . Random . Next ( reader . GetByte ( "minLevel" ) , reader . GetByte ( "maxLevel" ) ) ;
2017-09-07 22:02:02 +01:00
battleNpc . allegiance = ( CharacterTargetingAllegiance ) reader . GetByte ( "allegiance" ) ;
2017-09-05 23:32:57 +01:00
// todo: setup private areas and other crap and
// set up rest of stat resists
battleNpc . SetMod ( ( uint ) Modifier . Hp , reader . GetUInt32 ( "hp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . HpPercent , reader . GetUInt32 ( "hpp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Mp , reader . GetUInt32 ( "mp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . MpPercent , reader . GetUInt32 ( "mpp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . TpPercent , reader . GetUInt32 ( "tpp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Strength , reader . GetUInt32 ( "str" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Vitality , reader . GetUInt32 ( "vit" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Dexterity , reader . GetUInt32 ( "dex" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Intelligence , reader . GetUInt32 ( "int" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Mind , reader . GetUInt32 ( "mnd" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Piety , reader . GetUInt32 ( "pie" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Attack , reader . GetUInt32 ( "att" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Accuracy , reader . GetUInt32 ( "acc" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Defense , reader . GetUInt32 ( "def" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Evasion , reader . GetUInt32 ( "eva" ) ) ;
battleNpc . dropListId = reader . GetUInt32 ( "dropListId" ) ;
battleNpc . spellListId = reader . GetUInt32 ( "spellListId" ) ;
battleNpc . skillListId = reader . GetUInt32 ( "skillListId" ) ;
2017-09-07 22:02:02 +01:00
//battleNpc.SetMod((uint)Modifier.ResistFire, )
2017-09-16 02:50:32 +01:00
// todo: this is dumb
if ( battleNpc . npcSpawnType = = NpcSpawnType . Normal )
{
zone . AddActorToZone ( battleNpc ) ;
count + + ;
}
2017-09-05 23:32:57 +01:00
}
}
}
2017-09-07 22:02:02 +01:00
Program . Log . Info ( "Loaded {0} monsters." , count ) ;
2017-09-05 23:32:57 +01:00
}
catch ( MySqlException e )
{
Program . Log . Error ( e . ToString ( ) ) ;
}
finally
{
conn . Dispose ( ) ;
}
}
}
2016-06-14 22:54:02 +01:00
public void SpawnAllActors ( )
2016-05-29 15:14:09 -04:00
{
2016-06-14 22:54:02 +01:00
Program . Log . Info ( "Spawning actors..." ) ;
2016-05-29 15:14:09 -04:00
foreach ( Zone z in zoneList . Values )
2016-06-14 22:54:02 +01:00
z . SpawnAllActors ( true ) ;
2016-01-24 03:10:17 -05:00
}
2017-10-03 07:32:32 +01:00
public BattleNpc SpawnBattleNpcById ( uint id , Area area = null )
2017-09-10 03:41:58 +01:00
{
2017-10-03 07:32:32 +01:00
BattleNpc bnpc = null ;
2017-09-10 03:41:58 +01:00
// todo: this is stupid duplicate code and really needs to die, think of a better way later
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
var query = @ "
SELECT bsl . bnpcId , bsl . groupId , bsl . positionX , bsl . positionY , bsl . positionZ , bsl . rotation ,
2017-09-16 02:50:32 +01:00
bgr . groupId , bgr . poolId , bgr . scriptName , bgr . minLevel , bgr . maxLevel , bgr . respawnTime , bgr . hp , bgr . mp ,
2017-09-10 03:41:58 +01:00
bgr . dropListId , bgr . allegiance , bgr . spawnType , bgr . animationId , bgr . actorState , bgr . privateAreaName , bgr . privateAreaLevel , bgr . zoneId ,
2017-09-16 02:50:32 +01:00
bpo . poolId , bpo . genusId , bpo . actorClassId , bpo . currentJob , bpo . combatSkill , bpo . combatDelay , bpo . combatDmgMult , bpo . aggroType ,
2017-09-10 03:41:58 +01:00
bpo . immunity , bpo . linkType , bpo . skillListId , bpo . spellListId ,
2017-09-12 01:24:02 +01:00
bge . genusId , bge . modelSize , bge . speed , bge . kindredId , bge . detection , bge . hpp , bge . mpp , bge . tpp , bge . str , bge . vit , bge . dex ,
2017-09-10 03:41:58 +01:00
bge . int , bge . mnd , bge . pie , bge . att , bge . acc , bge . def , bge . eva , bge . slash , bge . pierce , bge . h2h , bge . blunt ,
2017-09-16 02:50:32 +01:00
bge . fire , bge . ice , bge . wind , bge . lightning , bge . earth , bge . water , bge . element
2017-09-10 03:41:58 +01:00
FROM server_battlenpc_spawn_locations bsl
INNER JOIN server_battlenpc_groups bgr ON bsl . groupId = bgr . groupId
INNER JOIN server_battlenpc_pools bpo ON bgr . poolId = bpo . poolId
INNER JOIN server_battlenpc_genus bge ON bpo . genusId = bge . genusId
WHERE bsl . bnpcId = @bnpcId GROUP BY bsl . bnpcId ;
";
var count = 0 ;
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
cmd . Parameters . AddWithValue ( "@bnpcId" , id ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
2022-02-05 14:05:32 -05:00
area = area ? ? Server . GetWorldManager ( ) . GetArea ( reader . GetUInt16 ( "zoneId" ) ) ;
2017-09-12 01:24:02 +01:00
int actorId = area . GetActorCount ( ) + 1 ;
2017-10-03 07:32:32 +01:00
bnpc = area . GetBattleNpcById ( id ) ;
2017-09-10 03:41:58 +01:00
if ( bnpc ! = null )
{
bnpc . ForceRespawn ( ) ;
break ;
}
// todo: add to private areas, set up immunity, mob linking,
// - load skill/spell/drop lists, set detection icon, load pool/family/group mods
2017-10-11 14:46:24 +01:00
var allegiance = ( CharacterTargetingAllegiance ) reader . GetByte ( "allegiance" ) ;
BattleNpc battleNpc = null ;
2017-09-10 03:41:58 +01:00
2017-10-11 14:46:24 +01:00
if ( allegiance = = CharacterTargetingAllegiance . Player )
battleNpc = new Ally ( actorId , Server . GetWorldManager ( ) . GetActorClass ( reader . GetUInt32 ( "actorClassId" ) ) ,
reader . GetString ( "scriptName" ) , area , reader . GetFloat ( "positionX" ) , reader . GetFloat ( "positionY" ) , reader . GetFloat ( "positionZ" ) , reader . GetFloat ( "rotation" ) ,
reader . GetUInt16 ( "actorState" ) , reader . GetUInt32 ( "animationId" ) , "" ) ;
else
battleNpc = new BattleNpc ( actorId , Server . GetWorldManager ( ) . GetActorClass ( reader . GetUInt32 ( "actorClassId" ) ) ,
2017-09-12 01:24:02 +01:00
reader . GetString ( "scriptName" ) , area , reader . GetFloat ( "positionX" ) , reader . GetFloat ( "positionY" ) , reader . GetFloat ( "positionZ" ) , reader . GetFloat ( "rotation" ) ,
2017-09-10 03:41:58 +01:00
reader . GetUInt16 ( "actorState" ) , reader . GetUInt32 ( "animationId" ) , "" ) ;
2017-09-12 01:24:02 +01:00
2017-09-10 03:41:58 +01:00
battleNpc . SetBattleNpcId ( reader . GetUInt32 ( "bnpcId" ) ) ;
2019-05-27 23:05:20 -07:00
battleNpc . SetMod ( ( uint ) Modifier . MovementSpeed , reader . GetByte ( "speed" ) ) ;
2017-09-10 03:41:58 +01:00
battleNpc . neutral = reader . GetByte ( "aggroType" ) = = 0 ;
2017-09-12 01:24:02 +01:00
// set mob mods
battleNpc . poolId = reader . GetUInt32 ( "poolId" ) ;
battleNpc . genusId = reader . GetUInt32 ( "genusId" ) ;
battleNpcPoolMods . TryGetValue ( battleNpc . poolId , out battleNpc . poolMods ) ;
battleNpcGenusMods . TryGetValue ( battleNpc . genusId , out battleNpc . genusMods ) ;
battleNpcSpawnMods . TryGetValue ( battleNpc . GetBattleNpcId ( ) , out battleNpc . spawnMods ) ;
2017-09-10 03:41:58 +01:00
battleNpc . SetDetectionType ( reader . GetUInt32 ( "detection" ) ) ;
battleNpc . kindredType = ( KindredType ) reader . GetUInt32 ( "kindredId" ) ;
battleNpc . npcSpawnType = ( NpcSpawnType ) reader . GetUInt32 ( "spawnType" ) ;
battleNpc . charaWork . parameterSave . state_mainSkill [ 0 ] = reader . GetByte ( "currentJob" ) ;
battleNpc . charaWork . parameterSave . state_mainSkillLevel = ( short ) Program . Random . Next ( reader . GetByte ( "minLevel" ) , reader . GetByte ( "maxLevel" ) ) ;
battleNpc . allegiance = ( CharacterTargetingAllegiance ) reader . GetByte ( "allegiance" ) ;
// todo: setup private areas and other crap and
// set up rest of stat resists
battleNpc . SetMod ( ( uint ) Modifier . Hp , reader . GetUInt32 ( "hp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . HpPercent , reader . GetUInt32 ( "hpp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Mp , reader . GetUInt32 ( "mp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . MpPercent , reader . GetUInt32 ( "mpp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . TpPercent , reader . GetUInt32 ( "tpp" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Strength , reader . GetUInt32 ( "str" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Vitality , reader . GetUInt32 ( "vit" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Dexterity , reader . GetUInt32 ( "dex" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Intelligence , reader . GetUInt32 ( "int" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Mind , reader . GetUInt32 ( "mnd" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Piety , reader . GetUInt32 ( "pie" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Attack , reader . GetUInt32 ( "att" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Accuracy , reader . GetUInt32 ( "acc" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Defense , reader . GetUInt32 ( "def" ) ) ;
battleNpc . SetMod ( ( uint ) Modifier . Evasion , reader . GetUInt32 ( "eva" ) ) ;
2017-12-08 00:58:39 -06:00
if ( battleNpc . poolMods ! = null )
{
foreach ( var a in battleNpc . poolMods . mobModList )
{
battleNpc . SetMobMod ( a . Value . id , ( long ) ( a . Value . value ) ) ;
}
foreach ( var a in battleNpc . poolMods . modList )
{
battleNpc . SetMod ( a . Key , ( long ) ( a . Value . value ) ) ;
}
}
if ( battleNpc . genusMods ! = null )
{
foreach ( var a in battleNpc . genusMods . mobModList )
{
battleNpc . SetMobMod ( a . Key , ( long ) ( a . Value . value ) ) ;
}
foreach ( var a in battleNpc . genusMods . modList )
{
battleNpc . SetMod ( a . Key , ( long ) ( a . Value . value ) ) ;
}
}
if ( battleNpc . spawnMods ! = null )
{
foreach ( var a in battleNpc . spawnMods . mobModList )
{
battleNpc . SetMobMod ( a . Key , ( long ) ( a . Value . value ) ) ;
}
foreach ( var a in battleNpc . spawnMods . modList )
{
battleNpc . SetMod ( a . Key , ( long ) ( a . Value . value ) ) ;
}
}
2017-09-10 03:41:58 +01:00
battleNpc . dropListId = reader . GetUInt32 ( "dropListId" ) ;
battleNpc . spellListId = reader . GetUInt32 ( "spellListId" ) ;
battleNpc . skillListId = reader . GetUInt32 ( "skillListId" ) ;
battleNpc . SetBattleNpcId ( reader . GetUInt32 ( "bnpcId" ) ) ;
2017-12-08 00:58:39 -06:00
battleNpc . SetRespawnTime ( reader . GetUInt32 ( "respawnTime" ) ) ;
2017-09-12 01:24:02 +01:00
battleNpc . CalculateBaseStats ( ) ;
battleNpc . RecalculateStats ( ) ;
2017-09-10 03:41:58 +01:00
//battleNpc.SetMod((uint)Modifier.ResistFire, )
2017-10-03 07:32:32 +01:00
bnpc = battleNpc ;
2017-09-12 01:24:02 +01:00
area . AddActorToZone ( battleNpc ) ;
2017-09-10 03:41:58 +01:00
count + + ;
}
}
Program . Log . Info ( "WorldManager.SpawnBattleNpcById spawned BattleNpc {0}." , id ) ;
}
catch ( MySqlException e )
2017-09-12 01:24:02 +01:00
{
Program . Log . Error ( e . ToString ( ) ) ;
}
finally
{
conn . Dispose ( ) ;
}
}
2017-10-03 07:32:32 +01:00
return bnpc ;
2017-09-12 01:24:02 +01:00
}
public void LoadBattleNpcModifiers ( string tableName , string primaryKey , Dictionary < uint , ModifierList > list )
{
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
2017-12-08 00:58:39 -06:00
var query = $"SELECT {primaryKey}, modId, modVal, isMobMod FROM {tableName}" ;
2017-09-12 01:24:02 +01:00
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
var id = reader . GetUInt32 ( primaryKey ) ;
2017-12-08 00:58:39 -06:00
ModifierList modList = list . TryGetValue ( id , out modList ) ? modList : new ModifierList ( id ) ;
2017-09-12 01:24:02 +01:00
modList . SetModifier ( reader . GetUInt16 ( "modId" ) , reader . GetInt64 ( "modVal" ) , reader . GetBoolean ( "isMobMod" ) ) ;
2017-12-08 00:58:39 -06:00
list [ id ] = modList ;
2017-09-12 01:24:02 +01:00
}
}
}
catch ( MySqlException e )
2017-09-10 03:41:58 +01:00
{
Program . Log . Error ( e . ToString ( ) ) ;
}
finally
{
conn . Dispose ( ) ;
}
}
}
2016-07-31 21:48:17 -04:00
//Moves the actor to the new zone if exists. No packets are sent nor position changed. Merged zone is removed.
2016-01-17 23:36:34 -05:00
public void DoSeamlessZoneChange ( Player player , uint destinationZoneId )
{
2016-03-20 19:29:38 -04:00
Area oldZone ;
2016-01-17 23:36:34 -05:00
2022-02-05 14:05:32 -05:00
if ( player . CurrentArea ! = null )
2016-01-17 23:36:34 -05:00
{
2022-02-05 14:05:32 -05:00
oldZone = player . CurrentArea ;
2016-06-14 21:29:10 +01:00
oldZone . RemoveActorFromZone ( player ) ;
2016-01-17 23:36:34 -05:00
}
//Add player to new zone and update
2022-02-05 14:05:32 -05:00
Area newZone = GetArea ( destinationZoneId ) ;
2016-01-17 23:36:34 -05:00
//This server does not contain that zoneId
if ( newZone = = null )
return ;
2016-06-14 21:29:10 +01:00
newZone . AddActorToZone ( player ) ;
2016-03-06 17:55:42 -05:00
2022-02-05 14:05:32 -05:00
player . CurrentArea = newZone ;
2016-07-31 21:48:17 -04:00
player . zone2 = null ;
2016-08-05 18:25:24 -04:00
player . SendSeamlessZoneInPackets ( ) ;
2016-07-31 23:00:38 -04:00
player . SendMessage ( 0x20 , "" , "Doing Seamless Zone Change" ) ;
2017-04-29 20:30:54 -04:00
LuaEngine . GetInstance ( ) . CallLuaFunction ( player , newZone , "onZoneIn" , true ) ;
2016-07-31 21:48:17 -04:00
}
//Adds a second zone to pull actors from. Used for an improved seamless zone change.
public void MergeZones ( Player player , uint mergedZoneId )
2017-03-13 14:06:57 -04:00
{
2016-07-31 21:48:17 -04:00
//Add player to new zone and update
2022-02-05 14:05:32 -05:00
Area mergedZone = GetArea ( mergedZoneId ) ;
2016-07-31 21:48:17 -04:00
//This server does not contain that zoneId
if ( mergedZone = = null )
return ;
mergedZone . AddActorToZone ( player ) ;
player . zone2 = mergedZone ;
2016-07-31 23:00:38 -04:00
player . SendMessage ( 0x20 , "" , "Merging Zones" ) ;
2017-04-29 20:30:54 -04:00
LuaEngine . GetInstance ( ) . CallLuaFunction ( player , mergedZone , "onZoneIn" , true ) ;
2016-01-17 23:36:34 -05:00
}
2016-07-31 22:30:54 -04:00
//Checks all seamless bounding boxes in region to see if player needs to merge or zonechange
public void SeamlessCheck ( Player player )
{
2016-07-31 23:00:38 -04:00
//Check if you are in a seamless bounding box
//WorldMaster.DoSeamlessCheck(this) -- Return
/ *
* Find what bounding box in region I am in
* - > If none , ignore
* - > If zone box & & is my zone , ignore
* - > If zone box & & is not my zone , DoSeamlessZoneChange
* - > If merge box , MergeZones
* /
2022-02-05 14:05:32 -05:00
if ( player . CurrentArea = = null )
2016-07-31 22:30:54 -04:00
return ;
2022-02-05 14:05:32 -05:00
uint regionId = player . CurrentArea . RegionId ;
2016-07-31 22:30:54 -04:00
2016-07-31 23:00:38 -04:00
if ( ! seamlessBoundryList . ContainsKey ( regionId ) )
return ;
foreach ( SeamlessBoundry bounds in seamlessBoundryList [ regionId ] )
{
2022-02-05 14:05:32 -05:00
uint zoneId = player . CurrentArea . ZoneId ;
uint zoneId2 = player . zone2 . ZoneId ;
2016-07-31 23:00:38 -04:00
if ( CheckPosInBounds ( player . positionX , player . positionZ , bounds . zone1_x1 , bounds . zone1_y1 , bounds . zone1_x2 , bounds . zone1_y2 ) )
{
2022-02-05 14:05:32 -05:00
if ( zoneId = = bounds . zoneId1 & & zoneId2 = = 0 )
2016-07-31 23:00:38 -04:00
return ;
DoSeamlessZoneChange ( player , bounds . zoneId1 ) ;
}
else if ( CheckPosInBounds ( player . positionX , player . positionZ , bounds . zone2_x1 , bounds . zone2_y1 , bounds . zone2_x2 , bounds . zone2_y2 ) )
{
2022-02-05 14:05:32 -05:00
if ( zoneId = = bounds . zoneId2 & & zoneId2 = = 0 )
2016-07-31 23:00:38 -04:00
return ;
DoSeamlessZoneChange ( player , bounds . zoneId2 ) ;
}
else if ( CheckPosInBounds ( player . positionX , player . positionZ , bounds . merge_x1 , bounds . merge_y1 , bounds . merge_x2 , bounds . merge_y2 ) )
{
uint merged ;
2022-02-05 14:05:32 -05:00
if ( zoneId = = bounds . zoneId1 )
2016-07-31 23:00:38 -04:00
merged = bounds . zoneId2 ;
else
merged = bounds . zoneId1 ;
//Already merged
2022-02-05 14:05:32 -05:00
if ( zoneId2 = = merged )
2016-07-31 23:00:38 -04:00
return ;
MergeZones ( player , merged ) ;
}
}
}
public bool CheckPosInBounds ( float x , float y , float x1 , float y1 , float x2 , float y2 )
{
bool xIsGood = false ;
bool yIsGood = false ;
if ( ( x1 < x & & x < x2 ) | | ( x1 > x & & x > x2 ) )
xIsGood = true ;
if ( ( y1 < y & & y < y2 ) | | ( y1 > y & & y > y2 ) )
yIsGood = true ;
2016-07-31 22:30:54 -04:00
2016-07-31 23:00:38 -04:00
return xIsGood & & yIsGood ;
2016-07-31 22:30:54 -04:00
}
2016-01-17 23:36:34 -05:00
//Moves actor to new zone, and sends packets to spawn at the given coords.
2017-03-07 00:09:37 -05:00
public void DoZoneChange ( Player player , uint destinationZoneId , string destinationPrivateArea , int destinationPrivateAreaType , byte spawnType , float spawnX , float spawnY , float spawnZ , float spawnRotation )
2022-02-05 14:05:32 -05:00
{
2016-01-17 23:36:34 -05:00
//Add player to new zone and update
2022-02-05 14:05:32 -05:00
//Add check for -1 if it is a instance
Area newArea = GetArea ( destinationZoneId , destinationPrivateArea , destinationPrivateAreaType ) ;
2016-01-17 23:36:34 -05:00
//This server does not contain that zoneId
2016-03-20 19:29:38 -04:00
if ( newArea = = null )
2016-07-27 17:23:52 +01:00
{
2016-12-03 12:19:59 -05:00
Program . Log . Debug ( "Request to change to zone not on this server by: {0}." , player . customDisplayName ) ;
RequestWorldServerZoneChange ( player , destinationZoneId , spawnType , spawnX , spawnY , spawnZ , spawnRotation ) ;
2016-01-17 23:36:34 -05:00
return ;
2016-07-27 17:23:52 +01:00
}
2016-01-17 23:36:34 -05:00
2017-04-29 20:30:54 -04:00
player . playerSession . LockUpdates ( true ) ;
2022-02-05 14:05:32 -05:00
Area oldArea = player . CurrentArea ;
2016-12-03 14:00:24 -05:00
//Remove player from currentZone if transfer else it's login
2022-02-05 14:05:32 -05:00
if ( player . CurrentArea ! = null )
2016-12-03 14:00:24 -05:00
{
2022-02-05 14:05:32 -05:00
oldArea . RemoveActorFromZone ( player ) ;
2016-12-03 14:00:24 -05:00
}
2016-06-14 21:29:10 +01:00
newArea . AddActorToZone ( player ) ;
2016-04-09 12:27:04 -07:00
//Update player actor's properties
2022-02-05 14:05:32 -05:00
player . CurrentArea = newArea ;
2016-04-09 12:27:04 -07:00
player . positionX = spawnX ;
player . positionY = spawnY ;
player . positionZ = spawnZ ;
player . rotation = spawnRotation ;
2016-01-17 23:36:34 -05:00
2017-06-25 14:52:32 -04:00
//Delete any GL directors
GuildleveDirector glDirector = player . GetGuildleveDirector ( ) ;
if ( glDirector ! = null )
player . RemoveDirector ( glDirector ) ;
2017-04-29 20:30:54 -04:00
//Delete content if have
if ( player . currentContentGroup ! = null )
{
player . currentContentGroup . RemoveMember ( player . actorId ) ;
2017-06-25 14:25:54 -04:00
player . SetCurrentContentGroup ( null ) ;
2017-04-29 20:30:54 -04:00
2022-02-05 14:05:32 -05:00
if ( oldArea is PrivateAreaContent )
( ( PrivateAreaContent ) oldArea ) . CheckDestroy ( ) ;
2017-04-29 20:30:54 -04:00
}
2016-01-17 23:36:34 -05:00
//Send packets
2017-06-27 16:55:14 -04:00
player . playerSession . QueuePacket ( DeleteAllActorsPacket . BuildPacket ( player . actorId ) ) ;
2017-07-06 21:59:12 -04:00
player . playerSession . QueuePacket ( _0xE2Packet . BuildPacket ( player . actorId , 0x2 ) ) ;
2016-06-14 21:29:10 +01:00
player . SendZoneInPackets ( this , spawnType ) ;
player . playerSession . ClearInstance ( ) ;
player . SendInstanceUpdate ( ) ;
2016-03-06 17:55:42 -05:00
2017-04-29 20:30:54 -04:00
player . playerSession . LockUpdates ( false ) ;
2017-03-07 00:09:37 -05:00
//Send "You have entered an instance" if it's a Private Area
if ( newArea is PrivateArea )
player . SendGameMessage ( GetActor ( ) , 34108 , 0x20 ) ;
2017-04-29 20:30:54 -04:00
LuaEngine . GetInstance ( ) . CallLuaFunction ( player , newArea , "onZoneIn" , true ) ;
2016-01-17 23:36:34 -05:00
}
2016-03-20 21:18:46 -04:00
//Moves actor within the zone
2016-04-14 08:30:21 -04:00
public void DoPlayerMoveInZone ( Player player , float spawnX , float spawnY , float spawnZ , float spawnRotation , byte spawnType = 0xF )
2016-03-20 21:18:46 -04:00
{
//Remove player from currentZone if transfer else it's login
2022-02-05 14:05:32 -05:00
if ( player . CurrentArea ! = null )
2016-03-20 21:18:46 -04:00
{
2017-06-14 22:24:09 -04:00
player . playerSession . LockUpdates ( true ) ;
2022-02-05 14:05:32 -05:00
player . CurrentArea . RemoveActorFromZone ( player ) ;
player . CurrentArea . AddActorToZone ( player ) ;
2016-03-20 21:18:46 -04:00
//Update player actor's properties;
player . positionX = spawnX ;
player . positionY = spawnY ;
player . positionZ = spawnZ ;
player . rotation = spawnRotation ;
//Send packets
2017-06-27 16:55:14 -04:00
player . playerSession . QueuePacket ( _0xE2Packet . BuildPacket ( player . actorId , 0x10 ) ) ;
player . playerSession . QueuePacket ( player . CreateSpawnTeleportPacket ( spawnType ) ) ;
2016-03-20 21:18:46 -04:00
2017-06-14 22:24:09 -04:00
player . playerSession . LockUpdates ( false ) ;
player . SendInstanceUpdate ( ) ;
2016-03-20 21:18:46 -04:00
}
}
2017-04-29 20:30:54 -04:00
//Moves actor to new zone, and sends packets to spawn at the given coords.
public void DoZoneChangeContent ( Player player , PrivateAreaContent contentArea , float spawnX , float spawnY , float spawnZ , float spawnRotation , ushort spawnType = SetActorPositionPacket . SPAWNTYPE_WARP_DUTY )
{
//Content area was null
if ( contentArea = = null )
{
Program . Log . Debug ( "Request to change to content area not on this server by: {0}." , player . customDisplayName ) ;
return ;
}
player . playerSession . LockUpdates ( true ) ;
2022-02-05 14:05:32 -05:00
Area oldArea = player . CurrentArea ;
2017-04-29 20:30:54 -04:00
//Remove player from currentZone if transfer else it's login
2022-02-05 14:05:32 -05:00
if ( player . CurrentArea ! = null )
2017-04-29 20:30:54 -04:00
{
2022-02-05 14:05:32 -05:00
oldArea . RemoveActorFromZone ( player ) ;
2017-04-29 20:30:54 -04:00
}
contentArea . AddActorToZone ( player ) ;
//Update player actor's properties
2022-02-05 14:05:32 -05:00
player . CurrentArea = contentArea ;
2017-04-29 20:30:54 -04:00
player . positionX = spawnX ;
player . positionY = spawnY ;
player . positionZ = spawnZ ;
player . rotation = spawnRotation ;
//Send "You have entered an instance" if it's a Private Area
player . SendGameMessage ( GetActor ( ) , 34108 , 0x20 ) ;
//Send packets
2017-06-27 16:55:14 -04:00
player . playerSession . QueuePacket ( DeleteAllActorsPacket . BuildPacket ( player . actorId ) ) ;
player . playerSession . QueuePacket ( _0xE2Packet . BuildPacket ( player . actorId , 0x10 ) ) ;
2017-04-29 20:30:54 -04:00
player . SendZoneInPackets ( this , spawnType ) ;
player . playerSession . ClearInstance ( ) ;
2019-07-27 21:54:05 -04:00
player . SendInstanceUpdate ( true ) ;
2017-04-29 20:30:54 -04:00
player . playerSession . LockUpdates ( false ) ;
2017-09-17 15:04:29 -04:00
2017-04-29 20:30:54 -04:00
LuaEngine . GetInstance ( ) . CallLuaFunction ( player , contentArea , "onZoneIn" , true ) ;
}
2016-12-03 12:19:59 -05:00
//Session started, zone into world
public void DoZoneIn ( Player player , bool isLogin , ushort spawnType )
2016-01-19 21:06:41 -05:00
{
//Add player to new zone and update
2022-02-05 14:05:32 -05:00
Area playerArea = player . CurrentArea ;
2016-01-19 21:06:41 -05:00
//This server does not contain that zoneId
2017-03-08 09:12:14 -05:00
if ( playerArea = = null )
2016-01-19 21:06:41 -05:00
return ;
//Set the current zone and add player
2022-02-05 14:05:32 -05:00
player . CurrentArea = playerArea ;
2017-03-08 09:12:14 -05:00
playerArea . AddActorToZone ( player ) ;
2016-03-06 17:55:42 -05:00
2016-03-28 12:14:10 -04:00
//Send packets
2016-12-03 12:19:59 -05:00
if ( ! isLogin )
{
2017-06-27 16:55:14 -04:00
player . playerSession . QueuePacket ( DeleteAllActorsPacket . BuildPacket ( player . actorId ) ) ;
player . playerSession . QueuePacket ( _0xE2Packet . BuildPacket ( player . actorId , 0x2 ) ) ;
2016-12-03 12:19:59 -05:00
}
2016-03-06 17:55:42 -05:00
2016-12-03 12:19:59 -05:00
player . SendZoneInPackets ( this , spawnType ) ;
2016-12-03 13:23:32 -05:00
2016-12-03 13:33:39 -05:00
player . destinationZone = 0 ;
player . destinationSpawnType = 0 ;
Database . SavePlayerPosition ( player ) ;
2019-07-27 21:54:05 -04:00
player . playerSession . ClearInstance ( ) ;
player . SendInstanceUpdate ( true ) ;
2016-12-03 13:23:32 -05:00
player . playerSession . LockUpdates ( false ) ;
2016-03-06 17:55:42 -05:00
2017-04-29 20:30:54 -04:00
LuaEngine . GetInstance ( ) . CallLuaFunction ( player , playerArea , "onZoneIn" , true ) ;
2016-01-19 21:06:41 -05:00
}
2016-06-16 03:01:10 +01:00
public void ReloadZone ( uint zoneId )
2016-01-24 03:10:17 -05:00
{
2017-08-02 23:06:11 +01:00
lock ( zoneList )
{
if ( ! zoneList . ContainsKey ( zoneId ) )
return ;
2016-01-24 03:10:17 -05:00
2017-08-02 23:06:11 +01:00
Zone zone = zoneList [ zoneId ] ;
//zone.clear();
//LoadNPCs(zone.actorId);
}
2016-01-24 03:10:17 -05:00
}
2017-04-15 16:33:56 -04:00
public ContentGroup CreateContentGroup ( Director director , params Actor [ ] actors )
{
if ( director = = null )
return null ;
lock ( groupLock )
{
uint [ ] initialMembers = null ;
if ( actors ! = null )
{
initialMembers = new uint [ actors . Length ] ;
for ( int i = 0 ; i < actors . Length ; i + + )
initialMembers [ i ] = actors [ i ] . actorId ;
}
groupIndexId = groupIndexId | 0x3000000000000000 ;
ContentGroup contentGroup = new ContentGroup ( groupIndexId , director , initialMembers ) ;
mContentGroups . Add ( groupIndexId , contentGroup ) ;
groupIndexId + + ;
if ( initialMembers ! = null & & initialMembers . Length ! = 0 )
contentGroup . SendAll ( ) ;
return contentGroup ;
}
}
2017-06-25 14:25:54 -04:00
public ContentGroup CreateContentGroup ( Director director , List < Actor > actors )
{
if ( director = = null )
return null ;
lock ( groupLock )
{
uint [ ] initialMembers = null ;
if ( actors ! = null )
{
initialMembers = new uint [ actors . Count ] ;
for ( int i = 0 ; i < actors . Count ; i + + )
initialMembers [ i ] = actors [ i ] . actorId ;
}
groupIndexId = groupIndexId | 0x3000000000000000 ;
ContentGroup contentGroup = new ContentGroup ( groupIndexId , director , initialMembers ) ;
mContentGroups . Add ( groupIndexId , contentGroup ) ;
groupIndexId + + ;
if ( initialMembers ! = null & & initialMembers . Length ! = 0 )
contentGroup . SendAll ( ) ;
return contentGroup ;
}
}
public ContentGroup CreateGLContentGroup ( Director director , List < Actor > actors )
{
if ( director = = null )
return null ;
lock ( groupLock )
{
uint [ ] initialMembers = null ;
if ( actors ! = null )
{
initialMembers = new uint [ actors . Count ] ;
for ( int i = 0 ; i < actors . Count ; i + + )
initialMembers [ i ] = actors [ i ] . actorId ;
}
groupIndexId = groupIndexId | 0x2000000000000000 ;
GLContentGroup contentGroup = new GLContentGroup ( groupIndexId , director , initialMembers ) ;
mContentGroups . Add ( groupIndexId , contentGroup ) ;
groupIndexId + + ;
if ( initialMembers ! = null & & initialMembers . Length ! = 0 )
contentGroup . SendAll ( ) ;
return contentGroup ;
}
}
2017-04-15 16:33:56 -04:00
public void DeleteContentGroup ( ulong groupId )
{
lock ( groupLock )
{
if ( mContentGroups . ContainsKey ( groupId ) & & mContentGroups [ groupId ] is ContentGroup )
{
ContentGroup group = ( ContentGroup ) mContentGroups [ groupId ] ;
mContentGroups . Remove ( groupId ) ;
}
}
}
2017-09-17 15:04:29 -04:00
public RelationGroup CreateRelationGroup ( Actor inviter , Actor invitee , ulong groupType )
{
lock ( groupLock )
{
groupIndexId = groupIndexId | 0x0000000000000000 ;
RelationGroup group = new RelationGroup ( groupIndexId , inviter . actorId , invitee . actorId , 0 , groupType ) ;
mRelationGroups . Add ( groupIndexId , group ) ;
groupIndexId + + ;
group . SendGroupPacketsAll ( inviter . actorId , invitee . actorId ) ;
return group ;
}
}
public RelationGroup GetRelationGroup ( uint actorId )
{
lock ( groupLock )
{
foreach ( RelationGroup relation in mRelationGroups . Values )
{
if ( relation . GetHost ( ) = = actorId | | relation . GetOther ( ) = = actorId )
return relation ;
}
return null ;
}
}
public void DeleteRelationGroup ( ulong groupid )
{
lock ( groupLock )
{
if ( mRelationGroups . ContainsKey ( groupid ) )
mRelationGroups . Remove ( groupid ) ;
}
}
public TradeGroup CreateTradeGroup ( Player inviter , Player invitee )
2019-06-02 17:32:08 -04:00
{
//Sanity Checks
if ( inviter . Equals ( invitee ) )
{
inviter . SendGameMessage ( GetActor ( ) , 25043 , 0x20 , ( object ) invitee ) ; //You cannot trade with yourself.
return null ;
}
else if ( GetTradeGroup ( inviter . actorId ) ! = null )
{
inviter . SendGameMessage ( GetActor ( ) , 25045 , 0x20 , ( object ) invitee ) ; //You may only trade with one person at a time.
return null ;
}
else if ( GetTradeGroup ( invitee . actorId ) ! = null )
{
inviter . SendGameMessage ( GetActor ( ) , 25044 , 0x20 , ( object ) invitee ) ; //Your target is unable to trade.
return null ;
}
//Create a trade group between these two players
2017-09-17 15:04:29 -04:00
lock ( groupLock )
{
groupIndexId = groupIndexId | 0x0000000000000000 ;
TradeGroup group = new TradeGroup ( groupIndexId , inviter . actorId , invitee . actorId ) ;
mTradeGroups . Add ( groupIndexId , group ) ;
groupIndexId + + ;
group . SendGroupPacketsAll ( inviter . actorId , invitee . actorId ) ;
inviter . SendGameMessage ( GetActor ( ) , 25101 , 0x20 , ( object ) invitee ) ; //You request to trade with X
invitee . SendGameMessage ( GetActor ( ) , 25037 , 0x20 , ( object ) inviter ) ; //X wishes to trade with you
return group ;
}
}
public TradeGroup GetTradeGroup ( uint actorId )
{
lock ( groupLock )
{
foreach ( TradeGroup group in mTradeGroups . Values )
{
if ( group . GetHost ( ) = = actorId | | group . GetOther ( ) = = actorId )
return ( TradeGroup ) group ;
}
return null ;
}
}
public void DeleteTradeGroup ( ulong groupid )
{
lock ( groupLock )
{
if ( mTradeGroups . ContainsKey ( groupid ) )
{
TradeGroup group = mTradeGroups [ groupid ] ;
group . SendDeletePackets ( group . GetHost ( ) , group . GetOther ( ) ) ;
mTradeGroups . Remove ( groupid ) ;
}
}
}
2017-10-08 12:26:22 -04:00
public void TradeTEST ( Player player )
{
player . KickEventSpecial ( Server . GetStaticActors ( "TradeExecuteCommand" ) , 0 , "commandContent" , null , null , null , 16 , null , null , null , null , null ) ;
}
2017-09-17 15:04:29 -04:00
public void AcceptTrade ( Player invitee )
{
TradeGroup group = GetTradeGroup ( invitee . actorId ) ;
if ( group = = null )
{
invitee . SendMessage ( 0x20 , "" , "MASSIVE ERROR: No tradegroup found!!!" ) ;
return ;
}
2022-02-05 14:05:32 -05:00
Player inviter = ( Player ) invitee . CurrentArea . FindActorInArea ( group . GetHost ( ) ) ;
2017-09-17 15:04:29 -04:00
2017-10-08 12:26:22 -04:00
//DeleteTradeGroup(group.groupIndex);
2017-10-01 12:23:54 -04:00
inviter . StartTradeTransaction ( invitee ) ;
invitee . StartTradeTransaction ( inviter ) ;
2017-10-08 12:26:22 -04:00
inviter . KickEventSpecial ( Server . GetStaticActors ( "TradeExecuteCommand" ) , 0 , "commandContent" , null , null , null , 16 , null , null , null , null , null ) ;
invitee . KickEventSpecial ( Server . GetStaticActors ( "TradeExecuteCommand" ) , 0 , "commandContent" , null , null , null , 16 , null , null , null , null , null ) ;
2017-09-17 15:04:29 -04:00
}
public void CancelTradeTooFar ( Player inviter )
{
TradeGroup group = GetTradeGroup ( inviter . actorId ) ;
if ( group = = null )
{
inviter . SendMessage ( 0x20 , "" , "MASSIVE ERROR: No tradegroup found!!!" ) ;
return ;
}
2022-02-05 14:05:32 -05:00
Player invitee = ( Player ) inviter . CurrentArea . FindActorInArea ( group . GetOther ( ) ) ;
2017-09-17 15:04:29 -04:00
inviter . SendGameMessage ( GetActor ( ) , 25042 , 0x20 ) ; //You cancel the trade.
if ( invitee ! = null )
invitee . SendGameMessage ( GetActor ( ) , 25042 , 0x20 ) ; //The trade has been canceled.
DeleteTradeGroup ( group . groupIndex ) ;
}
public void CancelTrade ( Player inviter )
{
TradeGroup group = GetTradeGroup ( inviter . actorId ) ;
if ( group = = null )
{
inviter . SendMessage ( 0x20 , "" , "MASSIVE ERROR: No tradegroup found!!!" ) ;
return ;
}
2022-02-05 14:05:32 -05:00
Player invitee = ( Player ) inviter . CurrentArea . FindActorInArea ( group . GetOther ( ) ) ;
2017-09-17 15:04:29 -04:00
inviter . SendGameMessage ( GetActor ( ) , 25041 , 0x20 ) ; //You cancel the trade.
if ( invitee ! = null )
invitee . SendGameMessage ( GetActor ( ) , 25040 , 0x20 ) ; //The trade has been canceled.
DeleteTradeGroup ( group . groupIndex ) ;
}
public void RefuseTrade ( Player invitee )
{
TradeGroup group = GetTradeGroup ( invitee . actorId ) ;
if ( group = = null )
{
invitee . SendMessage ( 0x20 , "" , "MASSIVE ERROR: No tradegroup found!!!" ) ;
return ;
}
2022-02-05 14:05:32 -05:00
Player inviter = ( Player ) invitee . CurrentArea . FindActorInArea ( group . GetHost ( ) ) ;
2017-09-17 15:04:29 -04:00
if ( inviter ! = null )
inviter . SendGameMessage ( GetActor ( ) , 25038 , 0x20 ) ; //Your trade request fails
DeleteTradeGroup ( group . groupIndex ) ;
}
2019-06-04 00:11:36 -04:00
public void CompleteTrade ( Player p1 , Player p2 )
2017-10-08 12:26:22 -04:00
{
2019-06-04 00:11:36 -04:00
if ( ! p1 . IsTradeAccepted ( ) | | ! p2 . IsTradeAccepted ( ) )
return ;
TradeGroup group = GetTradeGroup ( p1 . actorId ) ;
if ( group = = null )
2017-10-08 12:26:22 -04:00
{
2019-06-04 00:11:36 -04:00
p1 . SendMessage ( 0x20 , "" , "MASSIVE ERROR: No tradegroup found!!!" ) ;
return ;
}
ReferencedItemPackage p1Offer = p1 . GetTradeOfferings ( ) ;
ReferencedItemPackage p2Offer = p2 . GetTradeOfferings ( ) ;
int failCode = 0 ;
Player failurePlayerOffer = null ;
Player failureCauser = null ;
//TODO Add full inventory check
//Check items. If there is a failcode abort and set.
for ( ushort i = 0 ; i < p1Offer . GetCapacity ( ) ; i + + )
{
InventoryItem p1ItemToP2 = p1Offer . GetItemAtSlot ( i ) ;
InventoryItem p2ItemToP1 = p2Offer . GetItemAtSlot ( i ) ;
int failCodeP1 = CheckIfCanTrade ( p1 , p2 , p1ItemToP2 ) ; //P2's inv caused a failcode for P1
int failCodeP2 = CheckIfCanTrade ( p2 , p1 , p2ItemToP1 ) ; //P1's inv caused a failcode for P2
if ( failCodeP1 ! = 0 )
2017-10-08 12:26:22 -04:00
{
2019-06-04 00:11:36 -04:00
failCode = failCodeP1 ;
failurePlayerOffer = p1 ;
failureCauser = p2 ;
break ;
}
if ( failCodeP2 ! = 0 )
{
failCode = failCodeP2 ;
failurePlayerOffer = p2 ;
failureCauser = p1 ;
break ;
}
}
//Do we have a failcode?
switch ( failCode )
{
case 1 :
failurePlayerOffer . SendGameMessage ( GetActor ( ) , 25100 , 0x20 , ( object ) failureCauser ) ; //Transaction failed. X inventory is either full or X can only hold one of the selected items.
failureCauser . SendGameMessage ( GetActor ( ) , 25100 , 0x20 , ( object ) failureCauser ) ; //Transaction failed. X inventory is either full or X can only hold one of the selected items.
break ;
case 2 :
failurePlayerOffer . SendGameMessage ( GetActor ( ) , 25100 , 0x20 , ( object ) failureCauser ) ; //Transaction failed. X inventory is either full or X can only hold one of the selected items.
failureCauser . SendGameMessage ( GetActor ( ) , 25103 , 0x20 ) ; //Unable to complete transaction. You can only hold one of the selected items.
break ;
case 3 :
failurePlayerOffer . SendGameMessage ( GetActor ( ) , 25099 , 0x20 ) ; //Unable to complete transaction.
failureCauser . SendGameMessage ( GetActor ( ) , 25104 , 0x20 ) ; //Unable to complete transaction. You cannot receive the incoming payment.
break ;
}
//If all good, perform the swap.
if ( failCode = = 0 )
{
lock ( tradeLock )
{
for ( ushort i = 0 ; i < p1Offer . GetCapacity ( ) ; i + + )
{
InventoryItem p1ItemToP2 = p1Offer . GetItemAtSlot ( i ) ;
InventoryItem p2ItemToP1 = p2Offer . GetItemAtSlot ( i ) ;
//Transfer P1 -> P2
if ( p1ItemToP2 ! = null )
{
/ *
if ( p1ItemToP2 . GetItemData ( ) . maxStack > 1 )
{
p1 . GetItemPackage ( p1ItemToP2 . itemPackage ) . RemoveItem ( p1ItemToP2 . itemId , p1ItemToP2 . GetTradeQuantity ( ) , p1ItemToP2 . quality ) ;
p2 . GetItemPackage ( p1ItemToP2 . itemPackage ) . AddItem ( p1ItemToP2 . itemId , p1ItemToP2 . GetTradeQuantity ( ) , p1ItemToP2 . quality ) ;
}
else
{
p1 . GetItemPackage ( p1ItemToP2 . itemPackage ) . RemoveItem ( p1ItemToP2 ) ;
p2 . GetItemPackage ( p1ItemToP2 . itemPackage ) . AddItem ( p1ItemToP2 ) ;
}
* /
}
//Transfer P2 -> P1
if ( p2ItemToP1 ! = null )
{
2017-10-08 12:26:22 -04:00
2019-06-04 00:11:36 -04:00
/ *
if ( p2ItemToP1 . GetItemData ( ) . maxStack > 1 )
{
p2 . GetItemPackage ( p2ItemToP1 . itemPackage ) . RemoveItem ( p2ItemToP1 . itemId , p2ItemToP1 . GetTradeQuantity ( ) , p2ItemToP1 . quality ) ;
p1 . GetItemPackage ( p2ItemToP1 . itemPackage ) . AddItem ( p2ItemToP1 . itemId , p2ItemToP1 . GetTradeQuantity ( ) , p2ItemToP1 . quality ) ;
}
else
{
p2 . GetItemPackage ( p2ItemToP1 . itemPackage ) . RemoveItem ( p2ItemToP1 ) ;
p1 . GetItemPackage ( p2ItemToP1 . itemPackage ) . AddItem ( p2ItemToP1 ) ;
}
* /
}
}
2017-10-08 12:26:22 -04:00
}
2019-06-04 00:11:36 -04:00
p1 . SendGameMessage ( GetActor ( ) , 25039 , 0x20 ) ; //The trade is complete.
p2 . SendGameMessage ( GetActor ( ) , 25039 , 0x20 ) ; //The trade is complete.
}
//Cleanup the trade and delete the tradegroup.
p1 . FinishTradeTransaction ( ) ;
p2 . FinishTradeTransaction ( ) ;
DeleteTradeGroup ( group . groupIndex ) ;
}
private int CheckIfCanTrade ( Player itemOwner , Player itemReceiver , InventoryItem item )
{
if ( item = = null )
return 0 ;
//Check if their inventory can't hold all these things
if ( false )
{
return 1 ;
}
//Check if they already have a unique
else if ( item . GetItemData ( ) . isRare & & itemReceiver . HasItem ( item . itemId ) )
{
return 2 ;
2017-10-08 12:26:22 -04:00
}
2019-06-04 00:11:36 -04:00
//Check if gil is max
2019-06-06 01:43:27 -04:00
else if ( item . itemId = = 100001 & & item . GetTradeQuantity ( ) + itemReceiver . GetCurrentGil ( ) > item . GetItemData ( ) . maxStack )
2019-06-04 00:11:36 -04:00
{
return 3 ;
}
return 0 ;
2017-10-08 12:26:22 -04:00
}
2017-12-04 22:58:18 -05:00
public InventoryItem CreateItem ( uint itemId , int amount , byte quality = 1 , InventoryItem . ItemModifier modifiers = null )
2017-11-11 10:56:15 -05:00
{
2017-12-04 22:58:18 -05:00
return Database . CreateItem ( itemId , amount , quality , modifiers ) ;
2017-11-11 10:56:15 -05:00
}
2019-06-06 01:43:27 -04:00
public int AddToBazaar ( Player player , InventoryItem reward , InventoryItem seek , int rewardAmount , int seekAmount , byte bazaarMode )
{
//Selling Items
if ( bazaarMode = = InventoryItem . MODE_SELL_SINGLE )
2017-12-10 13:38:53 -05:00
{
2019-06-06 01:43:27 -04:00
reward . SetSelling ( bazaarMode , seekAmount ) ;
ItemPackage originalPackage = player . GetItemPackage ( reward . itemPackage ) ;
ItemPackage bazaarPackage = player . GetItemPackage ( ItemPackage . BAZAAR ) ;
originalPackage . MoveItem ( reward , bazaarPackage ) ;
2017-12-10 13:38:53 -05:00
}
2019-06-06 01:43:27 -04:00
else if ( bazaarMode = = InventoryItem . MODE_SELL_PSTACK )
{
if ( rewardAmount < = reward . quantity )
{
ItemPackage originalPackage = player . GetItemPackage ( reward . itemPackage ) ;
ItemPackage bazaarPackage = player . GetItemPackage ( ItemPackage . BAZAAR ) ;
2017-12-10 22:53:37 -05:00
2019-06-06 01:43:27 -04:00
InventoryItem splitItem = Database . CreateItem ( reward , ( uint ) rewardAmount ) ;
2017-12-10 22:53:37 -05:00
2019-06-06 01:43:27 -04:00
if ( splitItem ! = null )
{
reward . ChangeQuantity ( - rewardAmount ) ;
splitItem . SetSelling ( bazaarMode , seekAmount ) ;
bazaarPackage . AddItem ( splitItem ) ;
}
//TODO: Refactor so that it's not a mess like V
player . QueuePacket ( InventoryBeginChangePacket . BuildPacket ( player . actorId ) ) ;
originalPackage . SendUpdate ( ) ;
player . QueuePacket ( InventoryEndChangePacket . BuildPacket ( player . actorId ) ) ;
}
}
else if ( bazaarMode = = InventoryItem . MODE_SELL_FSTACK )
2017-12-10 22:53:37 -05:00
{
2019-06-06 01:43:27 -04:00
reward . SetSelling ( bazaarMode , seekAmount ) ;
ItemPackage originalPackage = player . GetItemPackage ( reward . itemPackage ) ;
ItemPackage bazaarPackage = player . GetItemPackage ( ItemPackage . BAZAAR ) ;
originalPackage . MoveItem ( reward , bazaarPackage ) ;
2017-12-10 22:53:37 -05:00
}
2019-06-06 01:43:27 -04:00
//Seeking Items
else if ( bazaarMode = = InventoryItem . MODE_SEEK_ITEM | | bazaarMode = = InventoryItem . MODE_SEEK_REPAIR )
{
ItemPackage originalRewardPackage = player . GetItemPackage ( reward . itemPackage ) ;
ItemPackage originalSeekPackage = player . GetItemPackage ( seek . itemPackage ) ;
ItemPackage bazaarPackage = player . GetItemPackage ( ItemPackage . BAZAAR ) ;
2017-12-10 22:53:37 -05:00
2019-06-06 01:43:27 -04:00
InventoryItem finalReward , finalSeek ;
2017-12-10 22:53:37 -05:00
2019-06-06 01:43:27 -04:00
/////REWARD/////
//No Split, just move
if ( rewardAmount = = reward . itemData . maxStack )
{
finalReward = reward ;
originalRewardPackage . RemoveItem ( reward ) ;
}
else //Splitting (ughh)
{
InventoryItem splitItem = Database . CreateItem ( reward , ( uint ) rewardAmount ) ;
2017-12-10 22:53:37 -05:00
2019-06-06 01:43:27 -04:00
if ( splitItem ! = null )
{
reward . ChangeQuantity ( - rewardAmount ) ;
finalReward = splitItem ;
2017-12-04 22:58:18 -05:00
2019-06-06 01:43:27 -04:00
player . QueuePacket ( InventoryBeginChangePacket . BuildPacket ( player . actorId ) ) ;
originalRewardPackage . SendUpdate ( ) ;
player . QueuePacket ( InventoryEndChangePacket . BuildPacket ( player . actorId ) ) ;
}
else
return ItemPackage . ERROR_SYSTEM ;
}
2017-11-11 10:56:15 -05:00
2019-06-06 01:43:27 -04:00
/////SEEK/////
//No Split, just move
if ( seekAmount = = seek . itemData . maxStack )
2017-11-11 17:05:07 -05:00
{
2019-06-06 01:43:27 -04:00
finalSeek = seek ;
originalSeekPackage . RemoveItem ( seek ) ;
2017-11-11 17:05:07 -05:00
}
2019-06-06 01:43:27 -04:00
else //Splitting (ughh)
2017-11-11 17:05:07 -05:00
{
2019-06-06 01:43:27 -04:00
InventoryItem splitItem = Database . CreateItem ( seek , ( uint ) seekAmount ) ;
if ( splitItem ! = null )
{
seek . ChangeQuantity ( - seekAmount ) ;
finalSeek = splitItem ;
player . QueuePacket ( InventoryBeginChangePacket . BuildPacket ( player . actorId ) ) ;
originalSeekPackage . SendUpdate ( ) ;
player . QueuePacket ( InventoryEndChangePacket . BuildPacket ( player . actorId ) ) ;
}
else
return ItemPackage . ERROR_SYSTEM ;
2017-11-11 17:05:07 -05:00
}
2019-06-06 01:43:27 -04:00
/////FINAL/////
2017-11-11 17:05:07 -05:00
2019-06-06 01:43:27 -04:00
bazaarPackage . AddItem ( finalReward ) ;
bazaarPackage . AddItem ( finalSeek ) ;
finalReward . SetAsOfferTo ( bazaarMode , finalSeek ) ;
player . QueuePacket ( InventoryBeginChangePacket . BuildPacket ( player . actorId ) ) ;
bazaarPackage . SendUpdate ( ) ;
player . QueuePacket ( InventoryEndChangePacket . BuildPacket ( player . actorId ) ) ;
}
2017-12-10 13:38:53 -05:00
player . CheckBazaarFlags ( ) ;
2019-06-06 01:43:27 -04:00
return ItemPackage . ERROR_SUCCESS ;
2017-11-11 10:56:15 -05:00
}
2017-12-04 22:58:18 -05:00
2019-06-06 01:43:27 -04:00
public int RemoveFromBazaar ( Player player , InventoryItem reward )
2017-11-11 10:56:15 -05:00
{
2019-06-06 01:43:27 -04:00
InventoryItem seek = reward . GetOfferedTo ( ) ;
ItemPackage bazaarPackage = player . GetItemPackage ( ItemPackage . BAZAAR ) ;
2017-11-11 10:56:15 -05:00
2019-06-06 01:43:27 -04:00
bazaarPackage . RemoveItem ( reward ) ;
reward . SetNormal ( ) ;
player . AddItem ( reward ) ;
if ( seek ! = null )
2017-12-04 22:58:18 -05:00
{
2019-06-06 01:43:27 -04:00
bazaarPackage . RemoveItem ( seek ) ;
seek . SetNormal ( ) ;
player . AddItem ( seek ) ;
2017-12-04 22:58:18 -05:00
}
2019-06-06 01:43:27 -04:00
2017-12-10 13:38:53 -05:00
player . CheckBazaarFlags ( ) ;
2019-06-06 01:43:27 -04:00
return ItemPackage . ERROR_SUCCESS ;
2017-11-11 10:56:15 -05:00
}
2019-06-06 01:43:27 -04:00
public int BazaarBuyOperation ( Player bazaar , Player buyer , InventoryItem itemToBuy , int quantity , int cost )
{
//TODO: Implement
return ItemPackage . ERROR_SYSTEM ;
}
2017-11-11 10:56:15 -05:00
2019-06-06 01:43:27 -04:00
public int BazaarSellOperation ( Player bazaar , Player buyer , InventoryItem reward , int rewardQuantity , InventoryItem seek , int seekQuantity )
{
//TODO: Implement
return ItemPackage . ERROR_SYSTEM ;
}
2017-11-11 10:56:15 -05:00
2017-04-15 16:33:56 -04:00
public bool SendGroupInit ( Session session , ulong groupId )
{
if ( mContentGroups . ContainsKey ( groupId ) )
{
mContentGroups [ groupId ] . SendInitWorkValues ( session ) ;
return true ;
2017-09-17 15:04:29 -04:00
}
else if ( mTradeGroups . ContainsKey ( groupId ) )
{
mTradeGroups [ groupId ] . SendInitWorkValues ( session ) ;
2017-04-15 16:33:56 -04:00
return true ;
}
return false ;
}
2016-12-21 08:27:23 -05:00
public void RequestWorldLinkshellCreate ( Player player , string name , ushort crest )
{
SubPacket packet = CreateLinkshellPacket . BuildPacket ( player . playerSession , name , crest , player . actorId ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2016-12-21 08:27:23 -05:00
}
public void RequestWorldLinkshellCrestModify ( Player player , string name , ushort crest )
{
SubPacket packet = ModifyLinkshellPacket . BuildPacket ( player . playerSession , 1 , name , null , crest , 0 ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2016-12-21 08:27:23 -05:00
}
public void RequestWorldLinkshellDelete ( Player player , string name )
{
SubPacket packet = DeleteLinkshellPacket . BuildPacket ( player . playerSession , name ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2016-12-21 08:27:23 -05:00
}
2017-01-08 21:42:43 -05:00
public void RequestWorldLinkshellRankChange ( Player player , string lsname , string memberName , byte newRank )
2016-12-21 08:27:23 -05:00
{
2017-01-08 23:13:15 -05:00
SubPacket packet = LinkshellRankChangePacket . BuildPacket ( player . playerSession , memberName , lsname , newRank ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2016-12-21 08:27:23 -05:00
}
2017-01-08 21:42:43 -05:00
public void RequestWorldLinkshellInviteMember ( Player player , string lsname , uint invitedActorId )
2016-12-21 08:27:23 -05:00
{
2017-01-08 21:42:43 -05:00
SubPacket packet = LinkshellInvitePacket . BuildPacket ( player . playerSession , invitedActorId , lsname ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2017-01-08 21:42:43 -05:00
}
public void RequestWorldLinkshellCancelInvite ( Player player )
{
SubPacket packet = LinkshellInviteCancelPacket . BuildPacket ( player . playerSession ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2016-12-21 08:27:23 -05:00
}
2017-01-08 23:13:15 -05:00
public void RequestWorldLinkshellLeave ( Player player , string lsname )
2016-12-21 08:27:23 -05:00
{
2017-01-09 00:12:11 -05:00
SubPacket packet = LinkshellLeavePacket . BuildPacket ( player . playerSession , lsname , null , false ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2017-01-09 00:12:11 -05:00
}
public void RequestWorldLinkshellKick ( Player player , string lsname , string kickedName )
{
SubPacket packet = LinkshellLeavePacket . BuildPacket ( player . playerSession , lsname , kickedName , true ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2016-12-21 08:27:23 -05:00
}
2016-01-24 03:10:17 -05:00
2017-01-09 23:12:56 -05:00
public void RequestWorldLinkshellChangeActive ( Player player , string lsname )
{
SubPacket packet = LinkshellChangePacket . BuildPacket ( player . playerSession , lsname ) ;
2017-06-27 21:08:30 -04:00
player . QueuePacket ( packet ) ;
2017-01-09 23:12:56 -05:00
}
2016-12-03 12:19:59 -05:00
private void RequestWorldServerZoneChange ( Player player , uint destinationZoneId , byte spawnType , float spawnX , float spawnY , float spawnZ , float spawnRotation )
{
ZoneConnection zc = Server . GetWorldConnection ( ) ;
zc . RequestZoneChange ( player . playerSession . id , destinationZoneId , spawnType , spawnX , spawnY , spawnZ , spawnRotation ) ;
}
2016-12-20 19:17:50 -05:00
//World server sent a party member list synch packet to the zone server. Add and update players that may be a part of it.
public void PartyMemberListRecieved ( PartySyncPacket syncPacket )
{
2016-12-21 18:02:50 -05:00
lock ( currentPlayerParties )
{
Party group ;
2016-12-20 19:17:50 -05:00
2016-12-21 18:02:50 -05:00
//If no members on this server, get out or clean
if ( ! currentPlayerParties . ContainsKey ( syncPacket . partyGroupId ) & & syncPacket . memberActorIds . Length = = 0 )
return ;
else if ( ! currentPlayerParties . ContainsKey ( syncPacket . partyGroupId ) & & syncPacket . memberActorIds . Length = = 0 )
NoMembersInParty ( currentPlayerParties [ syncPacket . partyGroupId ] ) ;
2016-12-20 19:17:50 -05:00
2016-12-21 18:02:50 -05:00
//Get or create group
if ( ! currentPlayerParties . ContainsKey ( syncPacket . partyGroupId ) )
{
group = new Party ( syncPacket . partyGroupId , syncPacket . owner ) ;
currentPlayerParties . Add ( syncPacket . partyGroupId , group ) ;
}
else
group = currentPlayerParties [ syncPacket . partyGroupId ] ;
2016-12-20 19:17:50 -05:00
2016-12-21 21:49:50 -05:00
group . SetLeader ( syncPacket . owner ) ;
2016-12-21 18:02:50 -05:00
group . members = syncPacket . memberActorIds . ToList ( ) ;
2016-12-20 19:17:50 -05:00
2016-12-21 18:02:50 -05:00
//Add group to everyone
for ( int i = 0 ; i < group . members . Count ; i + + )
{
uint member = group . members [ i ] ;
Session session = Server . GetServer ( ) . GetSession ( member ) ;
2016-12-21 09:27:51 -05:00
2016-12-21 18:02:50 -05:00
if ( session = = null )
continue ;
2016-12-21 09:27:51 -05:00
2016-12-21 18:02:50 -05:00
Player player = session . GetActor ( ) ;
if ( player = = null )
continue ;
player . SetParty ( group ) ;
}
2016-12-20 19:17:50 -05:00
}
}
//Player was removed from the party either due to leaving it or leaving the server. Remove if empty.
2016-12-21 09:27:51 -05:00
public void NoMembersInParty ( Party party )
2016-12-20 19:17:50 -05:00
{
2016-12-21 09:27:51 -05:00
if ( currentPlayerParties . ContainsKey ( party . groupIndex ) )
currentPlayerParties . Remove ( party . groupIndex ) ;
2016-12-20 19:17:50 -05:00
}
2017-01-02 14:35:11 -05:00
public void CreateInvitePartyGroup ( Player player , string name )
{
SubPacket invitePacket = PartyInvitePacket . BuildPacket ( player . playerSession , name ) ;
player . QueuePacket ( invitePacket ) ;
}
public void CreateInvitePartyGroup ( Player player , uint actorId )
{
SubPacket invitePacket = PartyInvitePacket . BuildPacket ( player . playerSession , actorId ) ;
player . QueuePacket ( invitePacket ) ;
}
public void GroupInviteResult ( Player player , uint groupType , uint result )
{
SubPacket groupInviteResultPacket = GroupInviteResultPacket . BuildPacket ( player . playerSession , groupType , result ) ;
player . QueuePacket ( groupInviteResultPacket ) ;
}
2017-01-16 19:14:13 -05:00
public void StartZoneThread ( )
{
mZoneTimer = new Timer ( ZoneThreadLoop , null , 0 , MILIS_LOOPTIME ) ;
Program . Log . Info ( "Zone Loop has started" ) ;
}
public void ZoneThreadLoop ( Object state )
2017-08-26 04:08:26 +01:00
{
2017-09-05 23:32:57 +01:00
// todo: coroutines GetActorInWorld stuff seems to be causing it to hang
2017-06-14 20:01:15 +01:00
// todo: spawn new thread for each zone on startup
2017-01-16 19:14:13 -05:00
lock ( zoneList )
{
2017-06-14 20:01:15 +01:00
Program . Tick = DateTime . Now ;
2017-06-12 20:13:26 +01:00
foreach ( Zone zone in zoneList . Values )
2018-02-15 13:20:46 -06:00
{
2017-06-14 20:01:15 +01:00
zone . Update ( Program . Tick ) ;
2017-10-10 13:32:47 -05:00
}
2017-07-18 04:51:35 +01:00
Program . LastTick = Program . Tick ;
2017-01-16 19:14:13 -05:00
}
}
2017-01-02 14:35:11 -05:00
2016-01-17 23:36:34 -05:00
public Player GetPCInWorld ( string name )
2017-03-08 09:12:14 -05:00
{
if ( Server . GetServer ( ) . GetSession ( name ) ! = null )
return Server . GetServer ( ) . GetSession ( name ) . GetActor ( ) ;
else
return null ;
}
public Player GetPCInWorld ( uint charId )
{
if ( Server . GetServer ( ) . GetSession ( charId ) ! = null )
return Server . GetServer ( ) . GetSession ( charId ) . GetActor ( ) ;
else
return null ;
2016-01-17 23:36:34 -05:00
}
2016-01-24 17:11:35 -05:00
public Actor GetActorInWorld ( uint charId )
{
2017-08-02 23:06:11 +01:00
lock ( zoneList )
2016-01-24 17:11:35 -05:00
{
2017-08-02 23:06:11 +01:00
foreach ( Zone zone in zoneList . Values )
{
Actor a = zone . FindActorInZone ( charId ) ;
if ( a ! = null )
return a ;
}
2016-01-24 17:11:35 -05:00
}
return null ;
}
2017-03-07 00:09:37 -05:00
public Actor GetActorInWorldByUniqueId ( string uid )
{
2017-08-02 23:06:11 +01:00
lock ( zoneList )
2017-03-07 00:09:37 -05:00
{
2017-08-02 23:06:11 +01:00
foreach ( Zone zone in zoneList . Values )
{
Actor a = zone . FindActorInZoneByUniqueID ( uid ) ;
if ( a ! = null )
return a ;
}
2017-03-07 00:09:37 -05:00
}
return null ;
}
2022-02-05 14:05:32 -05:00
public Area GetArea ( uint zoneId , string privateAreaName = "" , int privateAreaType = 0 )
2016-01-17 23:36:34 -05:00
{
2017-08-02 23:06:11 +01:00
lock ( zoneList )
{
if ( ! zoneList . ContainsKey ( zoneId ) )
return null ;
2022-02-05 14:05:32 -05:00
if ( privateAreaName = = null | | privateAreaName . Equals ( "" ) )
return zoneList [ zoneId ] ;
else
return zoneList [ zoneId ] . GetPrivateArea ( privateAreaName , privateAreaType ) ;
2017-08-02 23:06:11 +01:00
}
2017-03-07 00:09:37 -05:00
}
2016-01-17 23:36:34 -05:00
public WorldMaster GetActor ( )
{
return worldMaster ;
}
public DebugProg GetDebugActor ( )
{
return debug ;
}
public class ZoneEntrance
{
public uint zoneId ;
2016-03-20 19:29:38 -04:00
public string privateAreaName ;
2017-03-07 00:09:37 -05:00
public int privateAreaType ;
2016-01-17 23:36:34 -05:00
public byte spawnType ;
public float spawnX ;
public float spawnY ;
public float spawnZ ;
public float spawnRotation ;
2017-03-07 00:09:37 -05:00
public ZoneEntrance ( uint zoneId , string privateAreaName , int privateAreaType , byte spawnType , float x , float y , float z , float rot )
2016-01-17 23:36:34 -05:00
{
this . zoneId = zoneId ;
2016-03-20 19:29:38 -04:00
this . privateAreaName = privateAreaName ;
2017-03-07 00:09:37 -05:00
this . privateAreaType = privateAreaType ;
2016-01-17 23:36:34 -05:00
this . spawnType = spawnType ;
this . spawnX = x ;
this . spawnY = y ;
this . spawnZ = z ;
this . spawnRotation = rot ;
}
}
2016-05-29 15:14:09 -04:00
public ActorClass GetActorClass ( uint id )
{
if ( actorClasses . ContainsKey ( id ) )
return actorClasses [ id ] ;
else
return null ;
2016-12-20 19:17:50 -05:00
}
2017-07-15 19:33:47 +01:00
public void LoadStatusEffects ( )
{
2017-08-29 01:15:12 +01:00
statusEffectList = Database . LoadGlobalStatusEffectList ( ) ;
2017-07-15 19:33:47 +01:00
}
public StatusEffect GetStatusEffect ( uint id )
{
2017-08-29 01:15:12 +01:00
StatusEffect statusEffect ;
2017-07-15 19:33:47 +01:00
2017-08-29 01:15:12 +01:00
return statusEffectList . TryGetValue ( id , out statusEffect ) ? new StatusEffect ( null , statusEffect ) : null ;
2017-07-15 19:33:47 +01:00
}
2017-08-02 23:06:11 +01:00
2017-08-29 01:15:12 +01:00
public void LoadBattleCommands ( )
2017-08-02 23:06:11 +01:00
{
2017-09-27 18:10:22 -05:00
Database . LoadGlobalBattleCommandList ( battleCommandList , battleCommandIdByLevel ) ;
2017-08-02 23:06:11 +01:00
}
2018-04-18 16:06:41 -05:00
public void LoadBattleTraits ( )
{
Database . LoadGlobalBattleTraitList ( battleTraitList , battleTraitIdsForClass ) ;
}
2017-08-29 01:15:12 +01:00
public BattleCommand GetBattleCommand ( uint id )
2017-08-02 23:06:11 +01:00
{
2017-08-29 01:15:12 +01:00
BattleCommand battleCommand ;
return battleCommandList . TryGetValue ( ( ushort ) id , out battleCommand ) ? battleCommand . Clone ( ) : null ;
2017-08-02 23:06:11 +01:00
}
2017-09-27 18:10:22 -05:00
2019-06-08 21:11:51 -07:00
public List < ushort > GetBattleCommandIdByLevel ( byte classId , short level )
2017-09-27 18:10:22 -05:00
{
2019-06-08 21:11:51 -07:00
List < ushort > ids ;
return battleCommandIdByLevel . TryGetValue ( Tuple . Create ( classId , level ) , out ids ) ? ids : new List < ushort > ( ) ;
2017-09-27 18:10:22 -05:00
}
2018-04-18 16:06:41 -05:00
public BattleTrait GetBattleTrait ( ushort id )
{
BattleTrait battleTrait ;
battleTraitList . TryGetValue ( id , out battleTrait ) ;
return battleTrait ;
}
public List < ushort > GetAllBattleTraitIdsForClass ( byte classId )
{
List < ushort > ids ;
return battleTraitIdsForClass . TryGetValue ( classId , out ids ) ? ids : new List < ushort > ( ) ;
}
2016-01-17 23:36:34 -05:00
}
}