mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-05-20 08:26:59 -04:00
Cleaned up namespaces (still have to do Map Project) and removed references to FFXIV Classic from the code. Removed the Launcher Editor project as it is no longer needed (host file editing is cleaner).
This commit is contained in:
696
Map Server/actors/area/Area.cs
Normal file
696
Map Server/actors/area/Area.cs
Normal file
@@ -0,0 +1,696 @@
|
||||
/*
|
||||
===========================================================================
|
||||
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/>.
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using FFXIVClassic_Map_Server.actors.area;
|
||||
using FFXIVClassic_Map_Server.actors.chara.npc;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FFXIVClassic_Map_Server.packets.send;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
class Area : Actor
|
||||
{
|
||||
public string zoneName;
|
||||
public ushort regionId;
|
||||
public bool isIsolated, canStealth, isInn, canRideChocobo, isInstanceRaid;
|
||||
public ushort weatherNormal, weatherCommon, weatherRare;
|
||||
public ushort bgmDay, bgmNight, bgmBattle;
|
||||
|
||||
protected string classPath;
|
||||
|
||||
public int boundingGridSize = 50;
|
||||
public int minX = -5000, minY = -5000, maxX = 5000, maxY = 5000;
|
||||
protected int numXBlocks, numYBlocks;
|
||||
protected int halfWidth, halfHeight;
|
||||
|
||||
private Dictionary<uint, Director> currentDirectors = new Dictionary<uint, Director>();
|
||||
private Object directorLock = new Object();
|
||||
private uint directorIdCount = 0;
|
||||
|
||||
protected Director mWeatherDirector;
|
||||
|
||||
protected List<SpawnLocation> mSpawnLocations = new List<SpawnLocation>();
|
||||
protected Dictionary<uint, Actor> mActorList = new Dictionary<uint, Actor>();
|
||||
protected List<Actor>[,] mActorBlock;
|
||||
|
||||
LuaScript areaScript;
|
||||
|
||||
public Area(uint id, string zoneName, ushort regionId, string classPath, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
|
||||
: base(id)
|
||||
{
|
||||
|
||||
this.zoneName = zoneName;
|
||||
this.regionId = regionId;
|
||||
this.canStealth = canStealth;
|
||||
this.isIsolated = isIsolated;
|
||||
this.isInn = isInn;
|
||||
this.canRideChocobo = canRideChocobo;
|
||||
this.isInstanceRaid = isInstanceRaid;
|
||||
|
||||
this.bgmDay = bgmDay;
|
||||
this.bgmNight = bgmNight;
|
||||
this.bgmBattle = bgmBattle;
|
||||
|
||||
this.displayNameId = 0;
|
||||
this.customDisplayName = "_areaMaster";
|
||||
this.actorName = String.Format("_areaMaster@{0:X5}", id << 8);
|
||||
|
||||
this.classPath = classPath;
|
||||
this.className = classPath.Substring(classPath.LastIndexOf("/") + 1);
|
||||
|
||||
numXBlocks = (maxX - minX) / boundingGridSize;
|
||||
numYBlocks = (maxY - minY) / boundingGridSize;
|
||||
mActorBlock = new List<Actor>[numXBlocks, numYBlocks];
|
||||
halfWidth = numXBlocks / 2;
|
||||
halfHeight = numYBlocks / 2;
|
||||
|
||||
for (int y = 0; y < numYBlocks; y++)
|
||||
{
|
||||
for (int x = 0; x < numXBlocks; x++)
|
||||
{
|
||||
mActorBlock[x, y] = new List<Actor>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "/Area/Zone/ZoneDefault", -1, (byte)1, true, false, false, false, false, false, false, false);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, "ZoneDefault", lParams);
|
||||
}
|
||||
|
||||
public override List<SubPacket> GetSpawnPackets()
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(0));
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(0x1));
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket());
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
// todo: handle instance areas in derived class? (see virtuals)
|
||||
#region Actor Management
|
||||
|
||||
public void AddActorToZone(Actor actor)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (actor is Character)
|
||||
((Character)actor).ResetTempVars();
|
||||
|
||||
if (!mActorList.ContainsKey(actor.actorId))
|
||||
mActorList.Add(actor.actorId, actor);
|
||||
|
||||
|
||||
int gridX = (int)actor.positionX / boundingGridSize;
|
||||
int gridY = (int)actor.positionZ / boundingGridSize;
|
||||
|
||||
gridX += halfWidth;
|
||||
gridY += halfHeight;
|
||||
|
||||
//Boundries
|
||||
if (gridX < 0)
|
||||
gridX = 0;
|
||||
if (gridX >= numXBlocks)
|
||||
gridX = numXBlocks - 1;
|
||||
if (gridY < 0)
|
||||
gridY = 0;
|
||||
if (gridY >= numYBlocks)
|
||||
gridY = numYBlocks - 1;
|
||||
|
||||
lock (mActorBlock)
|
||||
mActorBlock[gridX, gridY].Add(actor);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveActorFromZone(Actor actor)
|
||||
{
|
||||
if (actor != null)
|
||||
lock (mActorList)
|
||||
{
|
||||
mActorList.Remove(actor.actorId);
|
||||
|
||||
int gridX = (int)actor.positionX / boundingGridSize;
|
||||
int gridY = (int)actor.positionZ / boundingGridSize;
|
||||
|
||||
gridX += halfWidth;
|
||||
gridY += halfHeight;
|
||||
|
||||
//Boundries
|
||||
if (gridX < 0)
|
||||
gridX = 0;
|
||||
if (gridX >= numXBlocks)
|
||||
gridX = numXBlocks - 1;
|
||||
if (gridY < 0)
|
||||
gridY = 0;
|
||||
if (gridY >= numYBlocks)
|
||||
gridY = numYBlocks - 1;
|
||||
|
||||
lock (mActorBlock)
|
||||
mActorBlock[gridX, gridY].Remove(actor);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateActorPosition(Actor actor)
|
||||
{
|
||||
int gridX = (int)actor.positionX / boundingGridSize;
|
||||
int gridY = (int)actor.positionZ / boundingGridSize;
|
||||
|
||||
gridX += halfWidth;
|
||||
gridY += halfHeight;
|
||||
|
||||
//Boundries
|
||||
if (gridX < 0)
|
||||
gridX = 0;
|
||||
if (gridX >= numXBlocks)
|
||||
gridX = numXBlocks - 1;
|
||||
if (gridY < 0)
|
||||
gridY = 0;
|
||||
if (gridY >= numYBlocks)
|
||||
gridY = numYBlocks - 1;
|
||||
|
||||
int gridOldX = (int)actor.oldPositionX / boundingGridSize;
|
||||
int gridOldY = (int)actor.oldPositionZ / boundingGridSize;
|
||||
|
||||
gridOldX += halfWidth;
|
||||
gridOldY += halfHeight;
|
||||
|
||||
//Boundries
|
||||
if (gridOldX < 0)
|
||||
gridOldX = 0;
|
||||
if (gridOldX >= numXBlocks)
|
||||
gridOldX = numXBlocks - 1;
|
||||
if (gridOldY < 0)
|
||||
gridOldY = 0;
|
||||
if (gridOldY >= numYBlocks)
|
||||
gridOldY = numYBlocks - 1;
|
||||
|
||||
//Still in same block
|
||||
if (gridX == gridOldX && gridY == gridOldY)
|
||||
return;
|
||||
|
||||
lock (mActorBlock)
|
||||
{
|
||||
mActorBlock[gridOldX, gridOldY].Remove(actor);
|
||||
mActorBlock[gridX, gridY].Add(actor);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual List<T> GetActorsAroundPoint<T>(float x, float y, int checkDistance) where T : Actor
|
||||
{
|
||||
checkDistance /= boundingGridSize;
|
||||
|
||||
int gridX = (int)x / boundingGridSize;
|
||||
int gridY = (int)y / boundingGridSize;
|
||||
|
||||
gridX += halfWidth;
|
||||
gridY += halfHeight;
|
||||
|
||||
//Boundries
|
||||
if (gridX < 0)
|
||||
gridX = 0;
|
||||
if (gridX >= numXBlocks)
|
||||
gridX = numXBlocks - 1;
|
||||
if (gridY < 0)
|
||||
gridY = 0;
|
||||
if (gridY >= numYBlocks)
|
||||
gridY = numYBlocks - 1;
|
||||
|
||||
List<T> result = new List<T>();
|
||||
|
||||
lock (mActorBlock)
|
||||
{
|
||||
for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++)
|
||||
{
|
||||
for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++)
|
||||
{
|
||||
result.AddRange(mActorBlock[gx, gy].OfType<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Remove players if isolation zone
|
||||
if (isIsolated)
|
||||
{
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
if (result[i] is Player)
|
||||
result.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual List<Actor> GetActorsAroundPoint(float x, float y, int checkDistance)
|
||||
{
|
||||
return GetActorsAroundPoint<Actor>(x, y, checkDistance);
|
||||
}
|
||||
|
||||
public virtual List<Actor> GetActorsAroundActor(Actor actor, int checkDistance)
|
||||
{
|
||||
return GetActorsAroundActor<Actor>(actor, checkDistance);
|
||||
}
|
||||
|
||||
public virtual List<T> GetActorsAroundActor<T>(Actor actor, int checkDistance) where T : Actor
|
||||
{
|
||||
checkDistance /= boundingGridSize;
|
||||
|
||||
int gridX = (int)actor.positionX / boundingGridSize;
|
||||
int gridY = (int)actor.positionZ / boundingGridSize;
|
||||
|
||||
gridX += halfWidth;
|
||||
gridY += halfHeight;
|
||||
|
||||
//Boundries
|
||||
if (gridX < 0)
|
||||
gridX = 0;
|
||||
if (gridX >= numXBlocks)
|
||||
gridX = numXBlocks - 1;
|
||||
if (gridY < 0)
|
||||
gridY = 0;
|
||||
if (gridY >= numYBlocks)
|
||||
gridY = numYBlocks - 1;
|
||||
|
||||
var result = new List<T>();
|
||||
|
||||
lock (mActorBlock)
|
||||
{
|
||||
for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++)
|
||||
{
|
||||
for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++)
|
||||
{
|
||||
result.AddRange(mActorBlock[gx, gy].OfType<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Remove players if isolation zone
|
||||
if (isIsolated)
|
||||
{
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
if (result[i] is Player)
|
||||
result.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Actor FindActorInArea(uint id)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (!mActorList.ContainsKey(id))
|
||||
return null;
|
||||
return mActorList[id];
|
||||
}
|
||||
}
|
||||
|
||||
public T FindActorInArea<T>(uint id) where T : Actor
|
||||
{
|
||||
return FindActorInArea(id) as T;
|
||||
}
|
||||
|
||||
public Actor FindActorInZoneByUniqueID(string uniqueId)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (Actor a in mActorList.Values)
|
||||
{
|
||||
if (a is Npc)
|
||||
{
|
||||
if (((Npc)a).GetUniqueId().ToLower().Equals(uniqueId))
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Player FindPCInZone(string name)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (Player player in mActorList.Values.OfType<Player>())
|
||||
{
|
||||
if (player.customDisplayName.ToLower().Equals(name.ToLower()))
|
||||
return player;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Player FindPCInZone(uint id)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (!mActorList.ContainsKey(id))
|
||||
return null;
|
||||
return (Player)mActorList[id];
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
//Clear All
|
||||
mActorList.Clear();
|
||||
lock (mActorBlock)
|
||||
{
|
||||
for (int y = 0; y < numYBlocks; y++)
|
||||
{
|
||||
for (int x = 0; x < numXBlocks; x++)
|
||||
{
|
||||
mActorBlock[x, y].Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo: for zones override this to search contentareas (assuming flag is passed)
|
||||
public virtual List<T> GetAllActors<T>() where T : Actor
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
List<T> actorList = new List<T>(mActorList.Count);
|
||||
actorList.AddRange(mActorList.Values.OfType<T>());
|
||||
return actorList;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetActorCount()
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
return mActorList.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual List<Actor> GetAllActors()
|
||||
{
|
||||
return GetAllActors<Actor>();
|
||||
}
|
||||
|
||||
public virtual List<Player> GetPlayers()
|
||||
{
|
||||
return GetAllActors<Player>();
|
||||
}
|
||||
|
||||
public virtual List<BattleNpc> GetMonsters()
|
||||
{
|
||||
return GetAllActors<BattleNpc>();
|
||||
}
|
||||
|
||||
public virtual List<Ally> GetAllies()
|
||||
{
|
||||
return GetAllActors<Ally>();
|
||||
}
|
||||
|
||||
public void BroadcastPacketsAroundActor(Actor actor, List<SubPacket> packets)
|
||||
{
|
||||
foreach (SubPacket packet in packets)
|
||||
BroadcastPacketAroundActor(actor, packet);
|
||||
}
|
||||
|
||||
public void BroadcastPacketAroundActor(Actor actor, SubPacket packet)
|
||||
{
|
||||
if (isIsolated)
|
||||
return;
|
||||
|
||||
List<Actor> aroundActor = GetActorsAroundActor(actor, 50);
|
||||
foreach (Actor a in aroundActor)
|
||||
{
|
||||
if (a is Player)
|
||||
{
|
||||
if (isIsolated)
|
||||
continue;
|
||||
|
||||
SubPacket clonedPacket = new SubPacket(packet, a.actorId);
|
||||
Player p = (Player)a;
|
||||
p.QueuePacket(clonedPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SpawnActor(SpawnLocation location)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
ActorClass actorClass = Server.GetWorldManager().GetActorClass(location.classId);
|
||||
|
||||
if (actorClass == null)
|
||||
return;
|
||||
|
||||
uint zoneId;
|
||||
|
||||
if (this is PrivateArea)
|
||||
zoneId = ((PrivateArea)this).GetParentZone().actorId;
|
||||
else
|
||||
zoneId = actorId;
|
||||
|
||||
Npc npc = new Npc(mActorList.Count + 1, actorClass, location.uniqueId, this, location.x, location.y, location.z, location.rot, location.state, location.animId, null);
|
||||
|
||||
|
||||
npc.LoadEventConditions(actorClass.eventConditions);
|
||||
|
||||
AddActorToZone(npc);
|
||||
}
|
||||
}
|
||||
|
||||
public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, float rot = 0, ushort state = 0, uint animId = 0, bool isMob = false)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
ActorClass actorClass = Server.GetWorldManager().GetActorClass(classId);
|
||||
|
||||
if (actorClass == null)
|
||||
return null;
|
||||
|
||||
uint zoneId;
|
||||
if (this is PrivateArea)
|
||||
zoneId = ((PrivateArea)this).GetParentZone().actorId;
|
||||
else
|
||||
zoneId = actorId;
|
||||
|
||||
Npc npc;
|
||||
if (isMob)
|
||||
npc = new BattleNpc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null);
|
||||
else
|
||||
npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null);
|
||||
|
||||
npc.LoadEventConditions(actorClass.eventConditions);
|
||||
npc.SetMaxHP(100);
|
||||
npc.SetHP(100);
|
||||
npc.ResetMoveSpeeds();
|
||||
|
||||
AddActorToZone(npc);
|
||||
|
||||
return npc;
|
||||
}
|
||||
}
|
||||
|
||||
public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, uint regionId, uint layoutId)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
ActorClass actorClass = Server.GetWorldManager().GetActorClass(classId);
|
||||
|
||||
if (actorClass == null)
|
||||
return null;
|
||||
|
||||
uint zoneId;
|
||||
|
||||
if (this is PrivateArea)
|
||||
zoneId = ((PrivateArea)this).GetParentZone().actorId;
|
||||
else
|
||||
zoneId = actorId;
|
||||
|
||||
Npc npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, 0, regionId, layoutId);
|
||||
|
||||
npc.LoadEventConditions(actorClass.eventConditions);
|
||||
|
||||
AddActorToZone(npc);
|
||||
|
||||
return npc;
|
||||
}
|
||||
}
|
||||
|
||||
public BattleNpc GetBattleNpcById(uint id)
|
||||
{
|
||||
foreach (var bnpc in GetAllActors<BattleNpc>())
|
||||
{
|
||||
if (bnpc.GetBattleNpcId() == id)
|
||||
return bnpc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void DespawnActor(string uniqueId)
|
||||
{
|
||||
RemoveActorFromZone(FindActorInZoneByUniqueID(uniqueId));
|
||||
}
|
||||
|
||||
public void DespawnActor(Actor actor)
|
||||
{
|
||||
RemoveActorFromZone(actor);
|
||||
}
|
||||
|
||||
public Director GetWeatherDirector()
|
||||
{
|
||||
return mWeatherDirector;
|
||||
}
|
||||
|
||||
public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false)
|
||||
{
|
||||
weatherNormal = weather;
|
||||
|
||||
if (player != null && !zoneWide)
|
||||
{
|
||||
player.QueuePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime));
|
||||
}
|
||||
if (zoneWide)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (var actor in mActorList)
|
||||
{
|
||||
if (actor.Value is Player)
|
||||
{
|
||||
player = ((Player)actor.Value);
|
||||
player.QueuePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Director CreateDirector(string path, bool hasContentGroup, params object[] args)
|
||||
{
|
||||
lock (directorLock)
|
||||
{
|
||||
Director director = new Director(directorIdCount, this, path, hasContentGroup, args);
|
||||
currentDirectors.Add(director.actorId, director);
|
||||
directorIdCount++;
|
||||
return director;
|
||||
}
|
||||
}
|
||||
|
||||
public Director CreateGuildleveDirector(uint glid, byte difficulty, Player owner, params object[] args)
|
||||
{
|
||||
String directorScriptPath = "";
|
||||
|
||||
uint type = Server.GetGuildleveGamedata(glid).plateId;
|
||||
|
||||
if (glid == 10801 || glid == 12401 || glid == 11601)
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleTutorial";
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 20021:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleSweepNormal";
|
||||
break;
|
||||
case 20022:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleChaseNormal";
|
||||
break;
|
||||
case 20023:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleOrbNormal";
|
||||
break;
|
||||
case 20024:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleHuntNormal";
|
||||
break;
|
||||
case 20025:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleGatherNormal";
|
||||
break;
|
||||
case 20026:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleRoundNormal";
|
||||
break;
|
||||
case 20027:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleSurviveNormal";
|
||||
break;
|
||||
case 20028:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleDetectNormal";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lock (directorLock)
|
||||
{
|
||||
GuildleveDirector director = new GuildleveDirector(directorIdCount, this, directorScriptPath, glid, difficulty, owner, args);
|
||||
currentDirectors.Add(director.actorId, director);
|
||||
directorIdCount++;
|
||||
return director;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteDirector(uint id)
|
||||
{
|
||||
lock (directorLock)
|
||||
{
|
||||
if (currentDirectors.ContainsKey(id))
|
||||
{
|
||||
if (!currentDirectors[id].IsDeleted())
|
||||
currentDirectors[id].EndDirector();
|
||||
currentDirectors.Remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Director GetDirectorById(uint id)
|
||||
{
|
||||
if (currentDirectors.ContainsKey(id))
|
||||
return currentDirectors[id];
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Update(DateTime tick)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (Actor a in mActorList.Values.ToList())
|
||||
a.Update(tick);
|
||||
|
||||
if ((tick - lastUpdateScript).TotalMilliseconds > 1500)
|
||||
{
|
||||
//LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick);
|
||||
lastUpdateScript = tick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
86
Map Server/actors/area/PrivateArea.cs
Normal file
86
Map Server/actors/area/PrivateArea.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
===========================================================================
|
||||
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/>.
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
using Meteor.Common;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.area
|
||||
{
|
||||
class PrivateArea : Area
|
||||
{
|
||||
private Zone parentZone;
|
||||
private string privateAreaName;
|
||||
private uint privateAreaType;
|
||||
|
||||
public PrivateArea(Zone parent, uint id, string classPath, string privateAreaName, uint privateAreaType, ushort bgmDay, ushort bgmNight, ushort bgmBattle)
|
||||
: base(id, parent.zoneName, parent.regionId, classPath, bgmDay, bgmNight, bgmBattle, parent.isIsolated, parent.isInn, parent.canRideChocobo, parent.canStealth, true)
|
||||
{
|
||||
this.parentZone = parent;
|
||||
this.zoneName = parent.zoneName;
|
||||
this.privateAreaName = privateAreaName;
|
||||
this.privateAreaType = privateAreaType;
|
||||
}
|
||||
|
||||
public string GetPrivateAreaName()
|
||||
{
|
||||
return privateAreaName;
|
||||
}
|
||||
|
||||
public uint GetPrivateAreaType()
|
||||
{
|
||||
return privateAreaType;
|
||||
}
|
||||
|
||||
public Zone GetParentZone()
|
||||
{
|
||||
return parentZone;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
|
||||
string path = className;
|
||||
|
||||
string realClassName = className.Substring(className.LastIndexOf("/") + 1);
|
||||
|
||||
lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, privateAreaName, privateAreaType, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, false, false, false);
|
||||
ActorInstantiatePacket.BuildPacket(actorId, actorName, realClassName, lParams).DebugPrintSubPacket();
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, realClassName, lParams);
|
||||
}
|
||||
|
||||
|
||||
public void AddSpawnLocation(SpawnLocation spawn)
|
||||
{
|
||||
mSpawnLocations.Add(spawn);
|
||||
}
|
||||
|
||||
public void SpawnAllActors()
|
||||
{
|
||||
foreach (SpawnLocation spawn in mSpawnLocations)
|
||||
SpawnActor(spawn);
|
||||
}
|
||||
}
|
||||
}
|
76
Map Server/actors/area/PrivateAreaContent.cs
Normal file
76
Map Server/actors/area/PrivateAreaContent.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
===========================================================================
|
||||
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/>.
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using System;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.area
|
||||
{
|
||||
|
||||
class PrivateAreaContent : PrivateArea
|
||||
{
|
||||
private Director currentDirector;
|
||||
private bool isContentFinished = false;
|
||||
|
||||
public static PrivateAreaContent CreateContentArea(String scriptPath)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public PrivateAreaContent(Zone parent, string classPath, string privateAreaName, uint privateAreaType, Director director, Player contentStarter) //TODO: Make it a list
|
||||
: base(parent, parent.actorId, classPath, privateAreaName, privateAreaType, 0, 0, 0)
|
||||
{
|
||||
currentDirector = director;
|
||||
LuaEngine.GetInstance().CallLuaFunction(contentStarter, this, "onCreate", false, currentDirector);
|
||||
}
|
||||
|
||||
public Director GetContentDirector()
|
||||
{
|
||||
return currentDirector;
|
||||
}
|
||||
|
||||
public void ContentFinished()
|
||||
{
|
||||
isContentFinished = true;
|
||||
}
|
||||
|
||||
public void CheckDestroy()
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (isContentFinished)
|
||||
{
|
||||
bool noPlayersLeft = true;
|
||||
foreach (Actor a in mActorList.Values)
|
||||
{
|
||||
if (a is Player)
|
||||
noPlayersLeft = false;
|
||||
}
|
||||
if (noPlayersLeft)
|
||||
GetParentZone().DeleteContentArea(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
53
Map Server/actors/area/SpawnLocation.cs
Normal file
53
Map Server/actors/area/SpawnLocation.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
===========================================================================
|
||||
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/>.
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.area
|
||||
{
|
||||
class SpawnLocation
|
||||
{
|
||||
public uint classId;
|
||||
public string uniqueId;
|
||||
public uint zoneId;
|
||||
public string privAreaName;
|
||||
public uint privAreaLevel;
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
public float rot;
|
||||
public ushort state;
|
||||
public uint animId;
|
||||
|
||||
public SpawnLocation(uint classId, string uniqueId, uint zoneId, string privAreaName, uint privAreaLevel, float x, float y, float z, float rot, ushort state, uint animId)
|
||||
{
|
||||
this.classId = classId;
|
||||
this.uniqueId = uniqueId;
|
||||
this.zoneId = zoneId;
|
||||
this.privAreaName = privAreaName;
|
||||
this.privAreaLevel = privAreaLevel;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.rot = rot;
|
||||
this.state = state;
|
||||
this.animId = animId;
|
||||
}
|
||||
}
|
||||
}
|
220
Map Server/actors/area/Zone.cs
Normal file
220
Map Server/actors/area/Zone.cs
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
===========================================================================
|
||||
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/>.
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
using Meteor.Common;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.area
|
||||
{
|
||||
class Zone : Area
|
||||
{
|
||||
Dictionary<string, Dictionary<uint, PrivateArea>> privateAreas = new Dictionary<string, Dictionary<uint, PrivateArea>>();
|
||||
Dictionary<string, List<PrivateAreaContent>> contentAreas = new Dictionary<string, List<PrivateAreaContent>>();
|
||||
Object contentAreasLock = new Object();
|
||||
|
||||
public SharpNav.TiledNavMesh tiledNavMesh;
|
||||
public SharpNav.NavMeshQuery navMeshQuery;
|
||||
|
||||
public Int64 pathCalls;
|
||||
public Int64 prevPathCalls = 0;
|
||||
public Int64 pathCallTime;
|
||||
|
||||
public Zone(uint id, string zoneName, ushort regionId, string classPath, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid, bool loadNavMesh = false)
|
||||
: base(id, zoneName, regionId, classPath, bgmDay, bgmNight, bgmBattle, isIsolated, isInn, canRideChocobo, canStealth, isInstanceRaid)
|
||||
{
|
||||
if (loadNavMesh)
|
||||
{
|
||||
try
|
||||
{
|
||||
tiledNavMesh = utils.NavmeshUtils.LoadNavmesh(tiledNavMesh, zoneName + ".snb");
|
||||
navMeshQuery = new SharpNav.NavMeshQuery(tiledNavMesh, 100);
|
||||
|
||||
if (tiledNavMesh != null && tiledNavMesh.Tiles[0].PolyCount > 0)
|
||||
Program.Log.Info($"Loaded navmesh for {zoneName}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Program.Log.Error(e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPrivateArea(PrivateArea pa)
|
||||
{
|
||||
if (privateAreas.ContainsKey(pa.GetPrivateAreaName()))
|
||||
privateAreas[pa.GetPrivateAreaName()][pa.GetPrivateAreaType()] = pa;
|
||||
else
|
||||
{
|
||||
privateAreas[pa.GetPrivateAreaName()] = new Dictionary<uint, PrivateArea>();
|
||||
privateAreas[pa.GetPrivateAreaName()][pa.GetPrivateAreaType()] = pa;
|
||||
}
|
||||
}
|
||||
|
||||
public PrivateArea GetPrivateArea(string type, uint number)
|
||||
{
|
||||
if (privateAreas.ContainsKey(type))
|
||||
{
|
||||
Dictionary<uint, PrivateArea> instances = privateAreas[type];
|
||||
if (instances.ContainsKey(number))
|
||||
return instances[number];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
bool isEntranceDesion = false;
|
||||
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "", -1, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, true, isInstanceRaid, isEntranceDesion);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
|
||||
}
|
||||
|
||||
public void AddSpawnLocation(SpawnLocation spawn)
|
||||
{
|
||||
//Is it in a private area?
|
||||
if (!spawn.privAreaName.Equals(""))
|
||||
{
|
||||
if (privateAreas.ContainsKey(spawn.privAreaName))
|
||||
{
|
||||
Dictionary<uint, PrivateArea> levels = privateAreas[spawn.privAreaName];
|
||||
if (levels.ContainsKey(spawn.privAreaLevel))
|
||||
levels[spawn.privAreaLevel].AddSpawnLocation(spawn);
|
||||
else
|
||||
Program.Log.Error("Tried to add a spawn location to non-existing private area level \"{0}\" in area {1} in zone {2}", spawn.privAreaName, spawn.privAreaLevel, zoneName);
|
||||
}
|
||||
else
|
||||
Program.Log.Error("Tried to add a spawn location to non-existing private area \"{0}\" in zone {1}", spawn.privAreaName, zoneName);
|
||||
}
|
||||
else
|
||||
mSpawnLocations.Add(spawn);
|
||||
}
|
||||
|
||||
public void SpawnAllActors(bool doPrivAreas)
|
||||
{
|
||||
foreach (SpawnLocation spawn in mSpawnLocations)
|
||||
SpawnActor(spawn);
|
||||
|
||||
if (doPrivAreas)
|
||||
{
|
||||
foreach (Dictionary<uint, PrivateArea> areas in privateAreas.Values)
|
||||
{
|
||||
foreach (PrivateArea pa in areas.Values)
|
||||
pa.SpawnAllActors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Actor FindActorInZone(uint id)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (!mActorList.ContainsKey(id))
|
||||
{
|
||||
foreach (Dictionary<uint, PrivateArea> paList in privateAreas.Values)
|
||||
{
|
||||
foreach (PrivateArea pa in paList.Values)
|
||||
{
|
||||
Actor actor = pa.FindActorInArea(id);
|
||||
if (actor != null)
|
||||
return actor;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (List<PrivateAreaContent> paList in contentAreas.Values)
|
||||
{
|
||||
foreach (PrivateArea pa in paList)
|
||||
{
|
||||
Actor actor = pa.FindActorInArea(id);
|
||||
if (actor != null)
|
||||
return actor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
else
|
||||
return mActorList[id];
|
||||
}
|
||||
}
|
||||
|
||||
public PrivateAreaContent CreateContentArea(Player starterPlayer, string areaClassPath, string contentScript, string areaName, string directorName, params object[] args)
|
||||
{
|
||||
lock (contentAreasLock)
|
||||
{
|
||||
Director director = CreateDirector(directorName, true, args);
|
||||
|
||||
if (director == null)
|
||||
return null;
|
||||
|
||||
if (!contentAreas.ContainsKey(areaName))
|
||||
contentAreas.Add(areaName, new List<PrivateAreaContent>());
|
||||
PrivateAreaContent contentArea = new PrivateAreaContent(this, classPath, areaName, 1, director, starterPlayer);
|
||||
contentAreas[areaName].Add(contentArea);
|
||||
|
||||
return contentArea;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteContentArea(PrivateAreaContent area)
|
||||
{
|
||||
if (contentAreas.ContainsKey(area.GetPrivateAreaName()))
|
||||
{
|
||||
contentAreas[area.GetPrivateAreaName()].Remove(area);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(DateTime tick)
|
||||
{
|
||||
base.Update(tick);
|
||||
|
||||
foreach (var a in privateAreas.Values)
|
||||
foreach(var b in a.Values)
|
||||
b.Update(tick);
|
||||
|
||||
foreach (var a in contentAreas.Values)
|
||||
foreach (var b in a)
|
||||
b.Update(tick);
|
||||
|
||||
// todo: again, this is retarded but debug stuff
|
||||
var diffTime = tick - lastUpdate;
|
||||
|
||||
if (diffTime.TotalSeconds >= 10)
|
||||
{
|
||||
if (this.pathCalls > 0)
|
||||
{
|
||||
Program.Log.Debug("Number of pathfinding calls {0} average time {1}ms. {2} this tick", pathCalls, (float)(pathCallTime / pathCalls), pathCalls - prevPathCalls);
|
||||
prevPathCalls = pathCalls;
|
||||
}
|
||||
lastUpdate = tick;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user