1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-24 05:37:46 +00:00
This commit is contained in:
yogurt 2017-07-11 09:40:10 -05:00
commit b2e86d282a
12 changed files with 351 additions and 154 deletions

View file

@ -99,7 +99,7 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
return AddActorPacket.BuildPacket(actorId, val); return AddActorPacket.BuildPacket(actorId, val);
} }
public SubPacket CreateNamePacket() public SubPacket CreateNamePacket()
{ {
return SetActorNamePacket.BuildPacket(actorId, displayNameId, displayNameId == 0xFFFFFFFF | displayNameId == 0x0 ? customDisplayName : ""); return SetActorNamePacket.BuildPacket(actorId, displayNameId, displayNameId == 0xFFFFFFFF | displayNameId == 0x0 ? customDisplayName : "");
@ -149,39 +149,11 @@ namespace FFXIVClassic_Map_Server.Actors
//spawnPacket.DebugPrintSubPacket(); //spawnPacket.DebugPrintSubPacket();
return spawnPacket; return spawnPacket;
} }
public SubPacket CreatePositionUpdatePacket(bool forceUpdate = false)
{
int updateMs = 300;
var diffTime = (DateTime.Now - lastMoveUpdate);
if (this.target != null) public SubPacket CreatePositionUpdatePacket(uint playerActorId)
{ {
updateMs = 150; return MoveActorToPositionPacket.BuildPacket(actorId, playerActorId, positionX, positionY, positionZ, rotation, moveState);
}
if (forceUpdate || (hasMoved && ((this is Player ) || diffTime.Milliseconds >= updateMs)))
{
hasMoved = (this.positionUpdates != null && this.positionUpdates.Count > 0);
if (hasMoved)
{
var pos = positionUpdates[0];
if (this is Character)
((Character)this).OnPath(pos);
positionX = pos.X;
positionY = pos.Y;
positionZ = pos.Z;
//Program.Server.GetInstance().mLuaEngine.OnPath(actor, position, positionUpdates)
positionUpdates.RemoveAt(0);
}
lastMoveUpdate = DateTime.Now;
return MoveActorToPositionPacket.BuildPacket(actorId, playerActorId, positionX, positionY, positionZ, rotation, moveState);
}
return null;
} }
public SubPacket CreateStatePacket() public SubPacket CreateStatePacket()
@ -285,7 +257,7 @@ namespace FFXIVClassic_Map_Server.Actors
public SubPacket CreateIsZoneingPacket() public SubPacket CreateIsZoneingPacket()
{ {
return SetActorIsZoningPacket.BuildPacket(actorId, false); return SetActorIsZoningPacket.BuildPacket(actorId, false);
} }
public virtual SubPacket CreateScriptBindPacket(Player player) public virtual SubPacket CreateScriptBindPacket(Player player)
@ -293,13 +265,13 @@ namespace FFXIVClassic_Map_Server.Actors
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, classParams); return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, classParams);
} }
public virtual SubPacket CreateScriptBindPacket() public virtual SubPacket CreateScriptBindPacket()
{ {
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, classParams); return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, classParams);
} }
public virtual List<SubPacket> GetSpawnPackets(Player player, ushort spawnType) public virtual List<SubPacket> GetSpawnPackets(Player player, ushort spawnType)
{ {
List<SubPacket> subpackets = new List<SubPacket>(); List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(8)); subpackets.Add(CreateAddActorPacket(8));
subpackets.AddRange(GetEventConditionPackets()); subpackets.AddRange(GetEventConditionPackets());

View file

@ -104,6 +104,7 @@ namespace FFXIVClassic_Map_Server.Actors
return subpackets; return subpackets;
} }
// todo: handle instance areas in derived class? (see virtuals)
#region Actor Management #region Actor Management
public void AddActorToZone(Actor actor) public void AddActorToZone(Actor actor)
@ -204,12 +205,12 @@ namespace FFXIVClassic_Map_Server.Actors
} }
} }
public List<Actor> GetActorsAroundPoint(float x, float y, int checkDistance) public virtual List<T> GetActorsAroundPoint<T>(float x, float y, int checkDistance) where T : Actor
{ {
checkDistance /= boundingGridSize; checkDistance /= boundingGridSize;
int gridX = (int)x/boundingGridSize; int gridX = (int)x / boundingGridSize;
int gridY = (int)y/boundingGridSize; int gridY = (int)y / boundingGridSize;
gridX += halfWidth; gridX += halfWidth;
gridY += halfHeight; gridY += halfHeight;
@ -224,7 +225,7 @@ namespace FFXIVClassic_Map_Server.Actors
if (gridY >= numYBlocks) if (gridY >= numYBlocks)
gridY = numYBlocks - 1; gridY = numYBlocks - 1;
List<Actor> result = new List<Actor>(); List<T> result = new List<T>();
lock (mActorBlock) lock (mActorBlock)
{ {
@ -232,7 +233,7 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++)
{ {
result.AddRange(mActorBlock[gx, gy]); result.AddRange(mActorBlock[gx, gy].OfType<T>());
} }
} }
} }
@ -246,11 +247,20 @@ namespace FFXIVClassic_Map_Server.Actors
result.RemoveAt(i); result.RemoveAt(i);
} }
} }
return result; return result;
} }
public List<Actor> GetActorsAroundActor(Actor actor, int checkDistance) 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; checkDistance /= boundingGridSize;
@ -270,7 +280,7 @@ namespace FFXIVClassic_Map_Server.Actors
if (gridY >= numYBlocks) if (gridY >= numYBlocks)
gridY = numYBlocks - 1; gridY = numYBlocks - 1;
List<Actor> result = new List<Actor>(); var result = new List<T>();
lock (mActorBlock) lock (mActorBlock)
{ {
@ -278,10 +288,11 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++) for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++)
{ {
result.AddRange(mActorBlock[gx, gy]); result.AddRange(mActorBlock[gx, gy].OfType<T>());
} }
} }
} }
//Remove players if isolation zone //Remove players if isolation zone
if (isIsolated) if (isIsolated)
{ {
@ -327,13 +338,10 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
lock (mActorList) lock (mActorList)
{ {
foreach (Actor a in mActorList.Values) foreach (Player player in mActorList.Values.OfType<Player>())
{ {
if (a is Player) if (player.customDisplayName.ToLower().Equals(name.ToLower()))
{ return player;
if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower()))
return (Player)a;
}
} }
return null; return null;
} }
@ -369,6 +377,7 @@ namespace FFXIVClassic_Map_Server.Actors
} }
// todo: for zones override this to seach contentareas (assuming flag is passed) // todo: for zones override this to seach contentareas (assuming flag is passed)
<<<<<<< HEAD
public virtual List<Actor> GetAllActors() public virtual List<Actor> GetAllActors()
{ {
lock (mActorList) lock (mActorList)
@ -378,10 +387,27 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
actorList.Add(actor); actorList.Add(actor);
} }
=======
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>());
>>>>>>> 84d5eee1fcc284d252b7953a70aebed60b195ee8
return actorList; return actorList;
} }
} }
<<<<<<< HEAD
=======
public virtual List<Actor> GetAllActors()
{
return GetAllActors<Actor>();
}
>>>>>>> 84d5eee1fcc284d252b7953a70aebed60b195ee8
public void BroadcastPacketsAroundActor(Actor actor, List<SubPacket> packets) public void BroadcastPacketsAroundActor(Actor actor, List<SubPacket> packets)
{ {
foreach (SubPacket packet in packets) foreach (SubPacket packet in packets)

View file

@ -10,7 +10,16 @@ using System;
namespace FFXIVClassic_Map_Server.Actors namespace FFXIVClassic_Map_Server.Actors
{ {
class Character:Actor /// <summary> Which Character types am I friendly with </summary>
enum CharacterTargetingAllegiance
{
/// <summary> Friendly to Players </summary>
Player,
/// <summary> Friendly to BattleNpcs </summary>
BattleNpcs
}
class Character : Actor
{ {
public const int SIZE = 0; public const int SIZE = 0;
public const int COLORINFO = 1; public const int COLORINFO = 1;
@ -66,6 +75,8 @@ namespace FFXIVClassic_Map_Server.Actors
public AIContainer aiContainer; public AIContainer aiContainer;
public StatusEffects statusEffects; public StatusEffects statusEffects;
public CharacterTargetingAllegiance allegiance;
public Character(uint actorID) : base(actorID) public Character(uint actorID) : base(actorID)
{ {
//Init timer array to "notimer" //Init timer array to "notimer"

View file

@ -88,6 +88,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
this.controller = controller; this.controller = controller;
} }
public Controller GetController()
{
return controller;
}
public bool CanChangeState() public bool CanChangeState()
{ {
return states.Count == 0 || states.Peek().CanInterrupt(); return states.Count == 0 || states.Peek().CanInterrupt();

View file

@ -5,6 +5,8 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.chara.ai;
using FFXIVClassic_Map_Server.actors.chara.ai.controllers;
// port of dsp's ai code https://github.com/DarkstarProject/darkstar/blob/master/src/map/ai/ // port of dsp's ai code https://github.com/DarkstarProject/darkstar/blob/master/src/map/ai/
@ -16,7 +18,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{ {
None, None,
/// <summary> Able to target <see cref="Player"/>s even if not in target's party </summary> /// <summary> Able to target <see cref="Player"/>s even if not in target's party </summary>
All, HitAll,
/// <summary> Able to target all <see cref="Player"/>s in target's party/alliance </summary> /// <summary> Able to target all <see cref="Player"/>s in target's party/alliance </summary>
Alliance, Alliance,
/// <summary> Able to target any <see cref="Pet"/> in target's party/alliance </summary> /// <summary> Able to target any <see cref="Pet"/> in target's party/alliance </summary>
@ -67,6 +69,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{ {
private Character owner; private Character owner;
private Character target; private Character target;
private Character masterTarget; // if target is a pet, this is the owner
private TargetFindCharacterType findType; private TargetFindCharacterType findType;
private TargetFindFlags findFlags; private TargetFindFlags findFlags;
private TargetFindAOEType aoeType; private TargetFindAOEType aoeType;
@ -95,6 +98,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
this.targets = new List<Character>(); this.targets = new List<Character>();
} }
public List<T> GetTargets<T>() where T : Character
{
return new List<T>(targets.OfType<T>());
}
public List<Character> GetTargets()
{
return targets;
}
/// <summary> /// <summary>
/// Call this before <see cref="FindWithinArea"/> <para/> /// Call this before <see cref="FindWithinArea"/> <para/>
/// </summary> /// </summary>
@ -128,84 +141,103 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
/// <para> Call SetAOEType before calling this </para> /// <para> Call SetAOEType before calling this </para>
/// Find targets within area set by <see cref="SetAOEType"/> /// Find targets within area set by <see cref="SetAOEType"/>
/// </summary> /// </summary>
/// <param name="withPet">Include pets?</param> public void FindWithinArea(Character target, TargetFindFlags flags)
public void FindWithinArea(Character target, TargetFindFlags flags, bool withPet)
{ {
findFlags = flags;
// todo: maybe we should keep a snapshot which is only updated on each tick for consistency // todo: maybe we should keep a snapshot which is only updated on each tick for consistency
// are we creating aoe circles around target or self // are we creating aoe circles around target or self
if ((aoeType & TargetFindAOEType.Circle) != 0 && radiusType != TargetFindAOERadiusType.Self) if ((aoeType & TargetFindAOEType.Circle) != 0 && radiusType != TargetFindAOERadiusType.Self)
this.targetPosition = owner.GetPosAsVector3(); this.targetPosition = owner.GetPosAsVector3();
else else
this.targetPosition = new Vector3(target.positionX, target.positionY, target.positionZ); this.targetPosition = target.GetPosAsVector3();
this.findFlags = flags; masterTarget = TryGetMasterTarget(target) ?? target;
if (aoeType == TargetFindAOEType.Box)
// todo: should i set this yet or wait til checked if valid target
this.target = target;
// todo: this is stupid
bool withPet = (flags & TargetFindFlags.Pets) != 0 || masterTarget.allegiance != owner.allegiance;
if (IsPlayer(owner))
{ {
FindWithinBox(withPet); if (masterTarget is Player)
{
findType = TargetFindCharacterType.PlayerToPlayer;
// todo: handle player parties
if (masterTarget.currentParty != null)
{
if ((findFlags & TargetFindFlags.Alliance) != 0)
AddAllInAlliance(masterTarget, withPet);
else
AddAllInParty(masterTarget, withPet);
}
else
{
AddTarget(masterTarget, withPet);
}
}
else
{
findType = TargetFindCharacterType.PlayerToBattleNpc;
AddAllBattleNpcs(masterTarget, false);
}
} }
else if (aoeType == TargetFindAOEType.Circle) else
{ {
FindWithinCircle(withPet); // todo: this needs checking..
if (masterTarget is Player || owner.allegiance == CharacterTargetingAllegiance.Player)
findType = TargetFindCharacterType.BattleNpcToPlayer;
else
findType = TargetFindCharacterType.BattleNpcToBattleNpc;
// todo: configurable pet aoe buff
if (findType == TargetFindCharacterType.BattleNpcToBattleNpc && TryGetMasterTarget(target) != null)
withPet = true;
// todo: does ffxiv have call for help flag?
//if ((findFlags & TargetFindFlags.HitAll) != 0)
//{
// AddAllInZone(masterTarget, withPet);
//}
AddAllInAlliance(target, withPet);
if (findType == TargetFindCharacterType.BattleNpcToPlayer)
{
if (owner.allegiance == CharacterTargetingAllegiance.Player)
AddAllInZone(masterTarget, withPet);
else
AddAllInHateList();
}
} }
} }
/// <summary> /// <summary>
/// Find targets within a box using owner's coordinates and target's coordinates as length /// Find targets within a box using owner's coordinates and target's coordinates as length
/// with corners being `extents` yalms to either side of self and target /// with corners being `extents` yalms to either side of self and target
/// </summary> /// </summary>
private void FindWithinBox(bool withPet) private bool IsWithinBox(Character target, bool withPet)
{ {
// todo: loop over party members var myPos = owner.GetPosAsVector3();
if ((findFlags & TargetFindFlags.All) != 0) var angle = Vector3.GetAngle(myPos, targetPosition);
{
// if we have flag set to hit all characters in zone, do it
// todo: make the distance check modifiable // todo: actually check this works..
var actors = (findFlags & TargetFindFlags.ZoneWide) != 0 ? owner.zone.GetAllActors() : owner.zone.GetActorsAroundActor(owner, 30); var myCorner = myPos.NewHorizontalVector(angle, extents);
var myPos = owner.GetPosAsVector3(); var myCorner2 = myPos.NewHorizontalVector(angle, -extents);
var angle = Vector3.GetAngle(myPos, targetPosition);
// todo: actually check this works.. var targetCorner = targetPosition.NewHorizontalVector(angle, extents);
var myCorner = myPos.NewHorizontalVector(angle, extents); var targetCorner2 = targetPosition.NewHorizontalVector(angle, -extents);
var myCorner2 = myPos.NewHorizontalVector(angle, -extents);
var targetCorner = targetPosition.NewHorizontalVector(angle, extents); return target.GetPosAsVector3().IsWithinBox(targetCorner2, myCorner);
var targetCorner2 = targetPosition.NewHorizontalVector(angle, -extents);
foreach (Character actor in actors)
{
// dont wanna add static actors
if (actor is Player || actor is BattleNpc)
{
if (actor.GetPosAsVector3().IsWithinBox(myCorner2, targetCorner))
{
if (CanTarget(actor))
AddTarget(actor, withPet);
}
}
}
}
} }
/// <summary> private bool IsWithinCone(Character target, bool withPet)
/// Find targets within circle area. <para/>
/// As the name implies, it only checks horizontal coords, not vertical -
/// effectively creating cylinder with infinite height
/// </summary>
private void FindWithinCircle(bool withPet)
{ {
var actors = (findFlags & TargetFindFlags.ZoneWide) != 0 ? owner.zone.GetAllActors() : owner.zone.GetActorsAroundActor(owner, 30); // todo:
return false;
foreach (Character target in actors)
{
if (target is Player || target is BattleNpc)
{
if (target.GetPosAsVector3().IsWithinCircle(targetPosition, extents))
AddTarget(target, withPet);
}
}
} }
private void AddTarget(Character target, bool withPet) private void AddTarget(Character target, bool withPet)
@ -220,14 +252,61 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private void AddAllInParty(Character target, bool withPet) private void AddAllInParty(Character target, bool withPet)
{ {
// todo: // todo:
/*
* foreach (var actor in target.currentParty.GetMembers())
* {
* AddTarget(actor, withPet);
* }
*/
AddTarget(target, withPet);
} }
private void AddAllInAlliance(Character target, bool withPet) private void AddAllInAlliance(Character target, bool withPet)
{ {
// todo: // todo:
/*
* foreach (var actor in target.currentParty.GetAllianceMembers())
* {
* AddTarget(actor, withPet);
* }
*/
AddTarget(target, withPet);
} }
public bool CanTarget(Character target) private void AddAllBattleNpcs(Character target, bool withPet)
{
// 70 is client render distance so we'll go with that
var actors = (findFlags & TargetFindFlags.ZoneWide) != 0 ? owner.zone.GetAllActors<BattleNpc>() : owner.zone.GetActorsAroundActor<BattleNpc>(owner, 70);
// todo: should we look for Characters instead in case player is charmed by BattleNpc
foreach (BattleNpc actor in actors)
{
// todo:
AddTarget(actor, false);
}
}
private void AddAllInZone(Character target, bool withPet)
{
var actors = owner.zone.GetAllActors<Character>();
foreach (Character actor in actors)
{
AddTarget(actor, withPet);
}
}
private void AddAllInHateList()
{
if (!(owner is BattleNpc))
Program.Log.Error($"TargetFind.AddAllInHateList() owner [{owner.actorId}] {owner.customDisplayName} {owner.actorName} is not a BattleNpc");
foreach (var hateEntry in ((BattleNpc)owner).hateContainer.GetHateList())
{
AddTarget(hateEntry.Value.actor, false);
}
}
public bool CanTarget(Character target, bool withPet = false)
{ {
// already targeted, dont target again // already targeted, dont target again
if (targets.Contains(target)) if (targets.Contains(target))
@ -237,12 +316,55 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if ((findFlags & TargetFindFlags.Dead) == 0 && target.IsDead()) if ((findFlags & TargetFindFlags.Dead) == 0 && target.IsDead())
return false; return false;
// cant target if player is zoning bool targetingPlayer = target is Player;
if (target is Player && ((Player)target).playerSession.isUpdatesLocked)
// cant target if zoning
if (target.isZoning || owner.isZoning || target.zone != owner.zone || targetingPlayer && ((Player)target).playerSession.isUpdatesLocked)
return false; return false;
return true; // hit everything within zone or within aoe region
if ((findFlags & TargetFindFlags.ZoneWide) != 0 || aoeType == TargetFindAOEType.Circle && target.GetPosAsVector3().IsWithinCircle(targetPosition, extents))
return true;
if (aoeType == TargetFindAOEType.Cone && IsWithinCone(target, withPet))
return true;
if (aoeType == TargetFindAOEType.Box && IsWithinBox(target, withPet))
return true;
return false;
} }
private bool IsPlayer(Character target)
{
if (target is Player)
return true;
// treat player owned pets as players too
return TryGetMasterTarget(target) is Player;
}
private Character TryGetMasterTarget(Character target)
{
// if character is a player owned pet, treat as a player
if (target.aiContainer != null)
{
var controller = target.aiContainer.GetController();
if (controller != null && controller is PetController)
return ((PetController)controller).GetPetMaster();
}
return null;
}
private bool IsBattleNpcOwner(Character target)
{
// i know i copied this from dsp but what even
if (!(owner is Player) || target is Player)
return true;
// todo: check hate list
return false;
}
} }
} }

View file

@ -3,10 +3,70 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FFXIVClassic_Map_Server.Actors;
namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{ {
class PetController class PetController : Controller
{ {
private Character petMaster;
public PetController(Character owner)
{
this.owner = owner;
this.lastUpdate = Program.Tick;
}
public override void Update(DateTime tick)
{
// todo: handle player stuff on tick
}
public override void ChangeTarget(Character target)
{
base.ChangeTarget(target);
}
public override bool Engage(Character target)
{
// todo: check distance, last swing time, status effects
return true;
}
public override bool Disengage()
{
// todo:
return true;
}
public override void Cast(Character target, uint spellId)
{
}
public override void Ability(Character target, uint abilityId)
{
}
public override void RangedAttack(Character target)
{
}
public Character GetPetMaster()
{
return petMaster;
}
public void SetPetMaster(Character master)
{
petMaster = master;
if (master is Player)
owner.allegiance = CharacterTargetingAllegiance.Player;
else
owner.allegiance = CharacterTargetingAllegiance.BattleNpcs;
}
} }
} }

View file

@ -24,6 +24,7 @@ namespace FFXIVClassic_Map_Server.Actors
this.aiContainer = new AIContainer(this, new BattleNpcController(this), new PathFind(this), new TargetFind(this)); this.aiContainer = new AIContainer(this, new BattleNpcController(this), new PathFind(this), new TargetFind(this));
this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER; this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER;
this.hateContainer = new HateContainer(this); this.hateContainer = new HateContainer(this);
this.allegiance = CharacterTargetingAllegiance.BattleNpcs;
} }
} }
} }

View file

@ -388,7 +388,6 @@ namespace FFXIVClassic_Map_Server.Actors
player.QueuePacket(PlayBGAnimation.BuildPacket(actorId, animationName)); player.QueuePacket(PlayBGAnimation.BuildPacket(actorId, animationName));
} }
public void Despawn() public void Despawn()
{ {
zone.DespawnActor(this); zone.DespawnActor(this);

View file

@ -17,7 +17,7 @@ namespace FFXIVClassic_Map_Server.Actors
ushort actorState, uint animationId, string customDisplayName) ushort actorState, uint animationId, string customDisplayName)
: base(actorNumber, actorClass, uniqueId, spawnedArea, posX, posY, posZ, rot, actorState, animationId, customDisplayName) : base(actorNumber, actorClass, uniqueId, spawnedArea, posX, posY, posZ, rot, actorState, animationId, customDisplayName)
{ {
this.aiContainer = new AIContainer(this, new BattleNpcController(this), new PathFind(this), new TargetFind(this)); this.aiContainer = new AIContainer(this, new PetController(this), new PathFind(this), new TargetFind(this));
this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER; this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER;
this.hateContainer = new HateContainer(this); this.hateContainer = new HateContainer(this);
} }

View file

@ -243,6 +243,7 @@ namespace FFXIVClassic_Map_Server.Actors
lastPlayTimeUpdate = Utils.UnixTimeStampUTC(); lastPlayTimeUpdate = Utils.UnixTimeStampUTC();
this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this)); this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this));
allegiance = CharacterTargetingAllegiance.Player;
} }
public List<SubPacket> Create0x132Packets() public List<SubPacket> Create0x132Packets()
@ -267,9 +268,9 @@ namespace FFXIVClassic_Map_Server.Actors
* Unknown - Bool * Unknown - Bool
* Unknown - Number * Unknown - Number
* Unknown - Bool * Unknown - Bool
* Timer Array - 20 Number * Timer Array - 20 Number
*/ */
public override SubPacket CreateScriptBindPacket(Player requestPlayer) public override SubPacket CreateScriptBindPacket(Player requestPlayer)
{ {
List<LuaParam> lParams; List<LuaParam> lParams;
@ -285,7 +286,8 @@ namespace FFXIVClassic_Map_Server.Actors
ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams).DebugPrintSubPacket(); ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams).DebugPrintSubPacket();
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
} }
public override List<SubPacket> GetSpawnPackets(Player requestPlayer, ushort spawnType) public override List<SubPacket> GetSpawnPackets(Player requestPlayer, ushort spawnType)
@ -294,21 +296,21 @@ namespace FFXIVClassic_Map_Server.Actors
subpackets.Add(CreateAddActorPacket(8)); subpackets.Add(CreateAddActorPacket(8));
if (IsMyPlayer(requestPlayer.actorId)) if (IsMyPlayer(requestPlayer.actorId))
subpackets.AddRange(Create0x132Packets()); subpackets.AddRange(Create0x132Packets());
subpackets.Add(CreateSpeedPacket()); subpackets.Add(CreateSpeedPacket());
subpackets.Add(CreateSpawnPositonPacket(this, spawnType)); subpackets.Add(CreateSpawnPositonPacket(this, spawnType));
subpackets.Add(CreateAppearancePacket()); subpackets.Add(CreateAppearancePacket());
subpackets.Add(CreateNamePacket()); subpackets.Add(CreateNamePacket());
subpackets.Add(_0xFPacket.BuildPacket(actorId)); subpackets.Add(_0xFPacket.BuildPacket(actorId));
subpackets.Add(CreateStatePacket()); subpackets.Add(CreateStatePacket());
subpackets.Add(CreateIdleAnimationPacket()); subpackets.Add(CreateIdleAnimationPacket());
subpackets.Add(CreateInitStatusPacket()); subpackets.Add(CreateInitStatusPacket());
subpackets.Add(CreateSetActorIconPacket()); subpackets.Add(CreateSetActorIconPacket());
subpackets.Add(CreateIsZoneingPacket()); subpackets.Add(CreateIsZoneingPacket());
subpackets.AddRange(CreatePlayerRelatedPackets(requestPlayer.actorId)); subpackets.AddRange(CreatePlayerRelatedPackets(requestPlayer.actorId));
subpackets.Add(CreateScriptBindPacket(requestPlayer)); subpackets.Add(CreateScriptBindPacket(requestPlayer));
return subpackets; return subpackets;
} }
public List<SubPacket> CreatePlayerRelatedPackets(uint requestingPlayerActorId) public List<SubPacket> CreatePlayerRelatedPackets(uint requestingPlayerActorId)
{ {
List<SubPacket> subpackets = new List<SubPacket>(); List<SubPacket> subpackets = new List<SubPacket>();
@ -319,9 +321,9 @@ namespace FFXIVClassic_Map_Server.Actors
if (currentTitle != 0) if (currentTitle != 0)
subpackets.Add(SetPlayerTitlePacket.BuildPacket(actorId, currentTitle)); subpackets.Add(SetPlayerTitlePacket.BuildPacket(actorId, currentTitle));
if (currentJob != 0) if (currentJob != 0)
subpackets.Add(SetCurrentJobPacket.BuildPacket(actorId, currentJob)); subpackets.Add(SetCurrentJobPacket.BuildPacket(actorId, currentJob));
if (IsMyPlayer(requestingPlayerActorId)) if (IsMyPlayer(requestingPlayerActorId))
{ {
subpackets.Add(SetSpecialEventWorkPacket.BuildPacket(actorId)); subpackets.Add(SetSpecialEventWorkPacket.BuildPacket(actorId));
@ -347,7 +349,7 @@ namespace FFXIVClassic_Map_Server.Actors
return subpackets; return subpackets;
} }
public override List<SubPacket> GetInitPackets() public override List<SubPacket> GetInitPackets()
{ {
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this); ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this);
@ -512,8 +514,8 @@ namespace FFXIVClassic_Map_Server.Actors
QueuePacket(SetWeatherPacket.BuildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR, 1)); QueuePacket(SetWeatherPacket.BuildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR, 1));
QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId));
QueuePackets(GetSpawnPackets(this, spawnType)); QueuePackets(GetSpawnPackets(this, spawnType));
//GetSpawnPackets(actorId, spawnType).DebugPrintPacket(); //GetSpawnPackets(actorId, spawnType).DebugPrintPacket();
#region Inventory & Equipment #region Inventory & Equipment
@ -523,17 +525,17 @@ namespace FFXIVClassic_Map_Server.Actors
inventories[Inventory.KEYITEMS].SendFullInventory(); inventories[Inventory.KEYITEMS].SendFullInventory();
inventories[Inventory.BAZAAR].SendFullInventory(); inventories[Inventory.BAZAAR].SendFullInventory();
inventories[Inventory.MELDREQUEST].SendFullInventory(); inventories[Inventory.MELDREQUEST].SendFullInventory();
inventories[Inventory.LOOT].SendFullInventory(); inventories[Inventory.LOOT].SendFullInventory();
equipment.SendFullEquipment(false); equipment.SendFullEquipment(false);
playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
#endregion #endregion
playerSession.QueuePacket(GetInitPackets()); playerSession.QueuePacket(GetInitPackets());
List<SubPacket> areaMasterSpawn = zone.GetSpawnPackets(); List<SubPacket> areaMasterSpawn = zone.GetSpawnPackets();
List<SubPacket> debugSpawn = world.GetDebugActor().GetSpawnPackets(); List<SubPacket> debugSpawn = world.GetDebugActor().GetSpawnPackets();
List<SubPacket> worldMasterSpawn = world.GetActor().GetSpawnPackets(); List<SubPacket> worldMasterSpawn = world.GetActor().GetSpawnPackets();
playerSession.QueuePacket(areaMasterSpawn); playerSession.QueuePacket(areaMasterSpawn);
playerSession.QueuePacket(debugSpawn); playerSession.QueuePacket(debugSpawn);
playerSession.QueuePacket(worldMasterSpawn); playerSession.QueuePacket(worldMasterSpawn);
@ -551,15 +553,15 @@ namespace FFXIVClassic_Map_Server.Actors
QueuePacket(SetPlayerItemStoragePacket.BuildPacket(actorId)); QueuePacket(SetPlayerItemStoragePacket.BuildPacket(actorId));
} }
if (zone.GetWeatherDirector() != null) if (zone.GetWeatherDirector() != null)
{ {
playerSession.QueuePacket(zone.GetWeatherDirector().GetSpawnPackets()); playerSession.QueuePacket(zone.GetWeatherDirector().GetSpawnPackets());
} }
foreach (Director director in ownedDirectors) foreach (Director director in ownedDirectors)
{ {
QueuePackets(director.GetSpawnPackets()); QueuePackets(director.GetSpawnPackets());
QueuePackets(director.GetInitPackets()); QueuePackets(director.GetInitPackets());
} }
@ -592,8 +594,8 @@ namespace FFXIVClassic_Map_Server.Actors
public bool IsMyPlayer(uint otherActorId) public bool IsMyPlayer(uint otherActorId)
{ {
return actorId == otherActorId; return actorId == otherActorId;
} }
public void QueuePacket(SubPacket packet) public void QueuePacket(SubPacket packet)
{ {
@ -601,7 +603,7 @@ namespace FFXIVClassic_Map_Server.Actors
} }
public void QueuePackets(List<SubPacket> packets) public void QueuePackets(List<SubPacket> packets)
{ {
playerSession.QueuePacket(packets); playerSession.QueuePacket(packets);
} }
@ -1141,16 +1143,16 @@ namespace FFXIVClassic_Map_Server.Actors
} }
public void MarkGuildleve(uint id, bool abandoned, bool completed) public void MarkGuildleve(uint id, bool abandoned, bool completed)
{ {
if (HasGuildleve(id)) if (HasGuildleve(id))
{ {
for (int i = 0; i < work.guildleveId.Length; i++) for (int i = 0; i < work.guildleveId.Length; i++)
{ {
if (work.guildleveId[i] == id) if (work.guildleveId[i] == id)
{ {
work.guildleveChecked[i] = completed; work.guildleveChecked[i] = completed;
work.guildleveDone[i] = abandoned; work.guildleveDone[i] = abandoned;
Database.MarkGuildleve(this, id, abandoned, completed); Database.MarkGuildleve(this, id, abandoned, completed);
SendGuildleveMarkClientUpdate(i); SendGuildleveMarkClientUpdate(i);
} }
} }
@ -1426,9 +1428,8 @@ namespace FFXIVClassic_Map_Server.Actors
private void SendGuildleveMarkClientUpdate(int slot) private void SendGuildleveMarkClientUpdate(int slot)
{ {
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("work/guildleve", this); ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("work/guildleve", this);
propPacketUtil.AddProperty(String.Format("work.guildleveDone[{0}]", slot)); propPacketUtil.AddProperty(String.Format("work.guildleveId[{0}]", slot));
propPacketUtil.AddProperty(String.Format("work.guildleveChecked[{0}]", slot));
QueuePackets(propPacketUtil.Done()); QueuePackets(propPacketUtil.Done());
} }
@ -1447,16 +1448,16 @@ namespace FFXIVClassic_Map_Server.Actors
} }
} }
public void SendDirectorPackets(Director director) public void SendDirectorPackets(Director director)
{ {
QueuePackets(director.GetSpawnPackets()); QueuePackets(director.GetSpawnPackets());
QueuePackets(director.GetInitPackets()); QueuePackets(director.GetInitPackets());
} }
public void RemoveDirector(Director director) public void RemoveDirector(Director director)
{ {
if (ownedDirectors.Contains(director)) if (ownedDirectors.Contains(director))
{ {
QueuePacket(RemoveActorPacket.BuildPacket(director.actorId)); QueuePacket(RemoveActorPacket.BuildPacket(director.actorId));
ownedDirectors.Remove(director); ownedDirectors.Remove(director);
director.RemoveMember(this); director.RemoveMember(this);

View file

@ -83,7 +83,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
playerActor.rotation = rot; playerActor.rotation = rot;
playerActor.moveState = moveState; playerActor.moveState = moveState;
GetActor().zone.UpdateActorPosition(GetActor()); GetActor().GetZone().UpdateActorPosition(GetActor());
playerActor.QueuePositionUpdate(new Vector3(x,y,z)); playerActor.QueuePositionUpdate(new Vector3(x,y,z));
} }

View file

@ -387,8 +387,8 @@ namespace FFXIVClassic_Map_Server.lua
} }
else else
CallLuaFunction(player, target, "onEventStarted", false, LuaUtils.CreateLuaParamObjectList(lparams)); CallLuaFunction(player, target, "onEventStarted", false, LuaUtils.CreateLuaParamObjectList(lparams));
} }
public DynValue ResolveResume(Actor actor, Coroutine coroutine, DynValue value) public DynValue ResolveResume(Actor actor, Coroutine coroutine, DynValue value)
{ {
var isPlayer = actor is Player; var isPlayer = actor is Player;