added some more targetfind stuff to handle pets (needs testing)

This commit is contained in:
Tahir Akhlaq
2017-07-10 23:52:31 +01:00
parent 1637bba167
commit 59fab08230
4 changed files with 172 additions and 34 deletions

View File

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

View File

@@ -5,6 +5,8 @@ using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Map_Server.Actors;
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/
@@ -67,6 +69,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{
private Character owner;
private Character target;
private Character masterTarget; // if target is a pet, this is the owner
private TargetFindCharacterType findType;
private TargetFindFlags findFlags;
private TargetFindAOEType aoeType;
@@ -128,19 +131,48 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
/// <para> Call SetAOEType before calling this </para>
/// Find targets within area set by <see cref="SetAOEType"/>
/// </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
if ((aoeType & TargetFindAOEType.Circle) != 0 && radiusType != TargetFindAOERadiusType.Self)
this.targetPosition = owner.GetPosAsVector3();
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)
{
FindWithinBox(withPet);
@@ -149,6 +181,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{
FindWithinCircle(withPet);
}
else if (aoeType == TargetFindAOEType.Cone)
{
FindWithinCone(withPet);
}
}
/// <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
// 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 angle = Vector3.GetAngle(myPos, targetPosition);
@@ -174,12 +210,12 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
var targetCorner = 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
if (actor is Player || actor is BattleNpc)
{
if (actor.GetPosAsVector3().IsWithinBox(myCorner2, targetCorner))
if (actor.GetPosAsVector3().IsWithinBox(targetCorner2, myCorner))
{
if (CanTarget(actor))
AddTarget(actor, withPet);
@@ -196,18 +232,23 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
/// </summary>
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);
}
}
}
private void FindWithinCone(bool withPet)
{
}
private void AddTarget(Character target, bool withPet)
{
if (CanTarget(target))
@@ -220,11 +261,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private void AddAllInParty(Character target, bool withPet)
{
// todo:
AddTarget(target, withPet);
}
private void AddAllInAlliance(Character target, bool withPet)
{
// todo:
AddTarget(target, withPet);
}
public bool CanTarget(Character target)
@@ -241,8 +284,32 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if (target is Player && ((Player)target).playerSession.isUpdatesLocked)
return false;
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;
}
}
}

View File

@@ -3,10 +3,65 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Map_Server.Actors;
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;
}
}
}