mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-02 19:42:05 -04:00
added some more targetfind stuff to handle pets (needs testing)
This commit is contained in:
parent
1637bba167
commit
59fab08230
@ -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,7 +205,7 @@ 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;
|
||||||
|
|
||||||
@ -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,19 +377,22 @@ 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)
|
||||||
public virtual List<Actor> GetAllActors()
|
public virtual List<T> GetAllActors<T>() where T : Actor
|
||||||
{
|
{
|
||||||
lock (mActorList)
|
lock (mActorList)
|
||||||
{
|
{
|
||||||
List<Actor> actorList = new List<Actor>(mActorList.Count);
|
List<T> actorList = new List<T>(mActorList.Count);
|
||||||
foreach (var actor in mActorList.Values)
|
actorList.AddRange(mActorList.Values.OfType<T>());
|
||||||
{
|
|
||||||
actorList.Add(actor);
|
|
||||||
}
|
|
||||||
return actorList;
|
return actorList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual List<Actor> GetAllActors()
|
||||||
|
{
|
||||||
|
return GetAllActors<Actor>();
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -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();
|
||||||
|
@ -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/
|
||||||
|
|
||||||
@ -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;
|
||||||
@ -128,19 +131,48 @@ 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, bool withPet)
|
public void FindWithinArea(Character target, TargetFindFlags flags)
|
||||||
{
|
{
|
||||||
// todo: maybe we should keep a snapshot which is only updated on each tick for consistency
|
findFlags = flags;
|
||||||
|
|
||||||
|
// 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 = GetMasterTarget(target);
|
||||||
|
|
||||||
|
// todo: this is stupid
|
||||||
|
bool withPet = (flags & TargetFindFlags.Pets) != 0 || masterTarget.currentSubState != owner.currentSubState;
|
||||||
|
|
||||||
|
if (IsPlayer(owner))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
if (aoeType == TargetFindAOEType.Box)
|
if (aoeType == TargetFindAOEType.Box)
|
||||||
{
|
{
|
||||||
FindWithinBox(withPet);
|
FindWithinBox(withPet);
|
||||||
@ -149,6 +181,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
{
|
{
|
||||||
FindWithinCircle(withPet);
|
FindWithinCircle(withPet);
|
||||||
}
|
}
|
||||||
|
else if (aoeType == TargetFindAOEType.Cone)
|
||||||
|
{
|
||||||
|
FindWithinCone(withPet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -163,7 +199,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
// if we have flag set to hit all characters in zone, do it
|
// if we have flag set to hit all characters in zone, do it
|
||||||
|
|
||||||
// todo: make the distance check modifiable
|
// todo: make the distance check modifiable
|
||||||
var actors = (findFlags & TargetFindFlags.ZoneWide) != 0 ? owner.zone.GetAllActors() : owner.zone.GetActorsAroundActor(owner, 30);
|
var actors = (findFlags & TargetFindFlags.ZoneWide) != 0 ? owner.zone.GetAllActors<Character>() : owner.zone.GetActorsAroundActor<Character>(owner, 70);
|
||||||
var myPos = owner.GetPosAsVector3();
|
var myPos = owner.GetPosAsVector3();
|
||||||
var angle = Vector3.GetAngle(myPos, targetPosition);
|
var angle = Vector3.GetAngle(myPos, targetPosition);
|
||||||
|
|
||||||
@ -174,12 +210,12 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
var targetCorner = targetPosition.NewHorizontalVector(angle, extents);
|
var targetCorner = targetPosition.NewHorizontalVector(angle, extents);
|
||||||
var targetCorner2 = targetPosition.NewHorizontalVector(angle, -extents);
|
var targetCorner2 = targetPosition.NewHorizontalVector(angle, -extents);
|
||||||
|
|
||||||
foreach (Character actor in actors)
|
foreach (Character actor in actors.OfType<Character>())
|
||||||
{
|
{
|
||||||
// dont wanna add static actors
|
// dont wanna add static actors
|
||||||
if (actor is Player || actor is BattleNpc)
|
if (actor is Player || actor is BattleNpc)
|
||||||
{
|
{
|
||||||
if (actor.GetPosAsVector3().IsWithinBox(myCorner2, targetCorner))
|
if (actor.GetPosAsVector3().IsWithinBox(targetCorner2, myCorner))
|
||||||
{
|
{
|
||||||
if (CanTarget(actor))
|
if (CanTarget(actor))
|
||||||
AddTarget(actor, withPet);
|
AddTarget(actor, withPet);
|
||||||
@ -196,18 +232,23 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void FindWithinCircle(bool withPet)
|
private void FindWithinCircle(bool withPet)
|
||||||
{
|
{
|
||||||
var actors = (findFlags & TargetFindFlags.ZoneWide) != 0 ? owner.zone.GetAllActors() : owner.zone.GetActorsAroundActor(owner, 30);
|
var actors = (findFlags & TargetFindFlags.ZoneWide) != 0 ? owner.zone.GetAllActors<Character>() : owner.zone.GetActorsAroundActor<Character>(owner, 70);
|
||||||
|
|
||||||
foreach (Character target in actors)
|
foreach (Character actor in actors)
|
||||||
{
|
{
|
||||||
if (target is Player || target is BattleNpc)
|
if (actor is Player || actor is BattleNpc)
|
||||||
{
|
{
|
||||||
if (target.GetPosAsVector3().IsWithinCircle(targetPosition, extents))
|
if (actor.GetPosAsVector3().IsWithinCircle(targetPosition, extents))
|
||||||
AddTarget(target, withPet);
|
AddTarget(target, withPet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FindWithinCone(bool withPet)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void AddTarget(Character target, bool withPet)
|
private void AddTarget(Character target, bool withPet)
|
||||||
{
|
{
|
||||||
if (CanTarget(target))
|
if (CanTarget(target))
|
||||||
@ -220,11 +261,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
private void AddAllInParty(Character target, bool withPet)
|
private void AddAllInParty(Character target, bool withPet)
|
||||||
{
|
{
|
||||||
// todo:
|
// todo:
|
||||||
|
AddTarget(target, withPet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddAllInAlliance(Character target, bool withPet)
|
private void AddAllInAlliance(Character target, bool withPet)
|
||||||
{
|
{
|
||||||
// todo:
|
// todo:
|
||||||
|
AddTarget(target, withPet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanTarget(Character target)
|
public bool CanTarget(Character target)
|
||||||
@ -241,8 +284,32 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
if (target is Player && ((Player)target).playerSession.isUpdatesLocked)
|
if (target is Player && ((Player)target).playerSession.isUpdatesLocked)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsPlayer(Character target)
|
||||||
|
{
|
||||||
|
if (target is Player)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// treat player owned pets as players too
|
||||||
|
return GetMasterTarget(target) is Player;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Character GetMasterTarget(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 target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,65 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user