1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-20 19:57:46 +00:00

stubbed some more functions

This commit is contained in:
Tahir Akhlaq 2017-07-11 20:49:38 +01:00
parent 84d5eee1fc
commit 7ab40a30f1
7 changed files with 108 additions and 9 deletions

View file

@ -204,7 +204,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public void MobSkill(Character target, uint mobSkillId) public void MobSkill(Character target, uint mobSkillId)
{ {
if (controller != null) if (controller != null)
controller.MobSkill(target, mobSkillId); controller.MonsterSkill(target, mobSkillId);
else else
InternalMobSkill(target, mobSkillId); InternalMobSkill(target, mobSkillId);
} }

View file

@ -9,6 +9,17 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{ {
class BattleNpcController : Controller class BattleNpcController : Controller
{ {
private DateTime lastActionTime;
private DateTime lastSpellCastTime;
private DateTime lastSkillTime;
private DateTime lastSpecialSkillTime; // todo: i dont think monsters have "2hr" cooldowns like ffxi
private DateTime deaggroTime;
private DateTime neutralTime;
private DateTime waitTime;
private bool firstSpell = true;
private DateTime lastRoamScript; // todo: what even is this used as
public BattleNpcController(Character owner) public BattleNpcController(Character owner)
{ {
this.owner = owner; this.owner = owner;
@ -16,16 +27,36 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
} }
public override void Update(DateTime tick) public override void Update(DateTime tick)
{
var battleNpc = this.owner as BattleNpc;
if (battleNpc != null)
{ {
// todo: handle aggro/deaggro and other shit here // todo: handle aggro/deaggro and other shit here
((BattleNpc)this.owner).statusEffects.Update(tick); if (battleNpc.aiContainer.IsEngaged())
{
DoCombatTick(tick);
}
else if (!battleNpc.IsDead())
{
DoRoamTick(tick);
}
battleNpc.Update(tick);
}
} }
public override bool Engage(Character target) public override bool Engage(Character target)
{ {
// todo: check distance, last swing time, status effects // todo: check distance, last swing time, status effects
this.owner.aiContainer.InternalEngage(target); var canEngage = this.owner.aiContainer.InternalEngage(target);
return true; if (canEngage)
{
// reset casting
firstSpell = true;
// todo: adjust cooldowns with modifiers
}
return canEngage;
} }
private bool TryEngage(Character target) private bool TryEngage(Character target)
@ -55,7 +86,17 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
} }
public override void MobSkill(Character target, uint mobSkillId) public override void MonsterSkill(Character target, uint mobSkillId)
{
}
private void DoRoamTick(DateTime tick)
{
}
private void DoCombatTick(DateTime tick)
{ {
} }

View file

@ -24,7 +24,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
public abstract bool Disengage(); public abstract bool Disengage();
public abstract void Cast(Character target, uint spellId); public abstract void Cast(Character target, uint spellId);
public virtual void WeaponSkill(Character target, uint weaponSkillId) { } public virtual void WeaponSkill(Character target, uint weaponSkillId) { }
public virtual void MobSkill(Character target, uint mobSkillId) { } public virtual void MonsterSkill(Character target, uint mobSkillId) { }
public abstract void Ability(Character target, uint abilityId); public abstract void Ability(Character target, uint abilityId);
public abstract void RangedAttack(Character target); public abstract void RangedAttack(Character target);
public virtual void Spawn() { } public virtual void Spawn() { }

View file

@ -13,18 +13,41 @@ using FFXIVClassic_Map_Server.packets.send.actor;
namespace FFXIVClassic_Map_Server.Actors namespace FFXIVClassic_Map_Server.Actors
{ {
[Flags]
enum AggroType
{
None,
Sight,
Scent,
LowHp,
IgnoreLevelDifference
}
class BattleNpc : Npc class BattleNpc : Npc
{ {
public HateContainer hateContainer; public HateContainer hateContainer;
public AggroType aggroType;
public BattleNpc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot, public BattleNpc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot,
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 BattleNpcController(this), new PathFind(this), new TargetFind(this));
this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER; this.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER;
//this.currentMainState = SetActorStatePacket.MAIN_STATE_ACTIVE;
//charaWork.property[2] = 1;
//npcWork.hateType = 1;
this.hateContainer = new HateContainer(this); this.hateContainer = new HateContainer(this);
this.allegiance = CharacterTargetingAllegiance.BattleNpcs; this.allegiance = CharacterTargetingAllegiance.BattleNpcs;
} }
public override void Update(DateTime tick)
{
// todo:
this.statusEffects.Update(tick);
}
} }
} }

View file

@ -125,6 +125,7 @@ namespace FFXIVClassic_Map_Server.Actors
this.instance = instance; this.instance = instance;
GenerateActorName((int)actorNumber); GenerateActorName((int)actorNumber);
this.aiContainer = new AIContainer(this, null, new PathFind(this), new TargetFind(null));
} }
public SubPacket CreateAddActorPacket() public SubPacket CreateAddActorPacket()
@ -393,7 +394,7 @@ namespace FFXIVClassic_Map_Server.Actors
zone.DespawnActor(this); zone.DespawnActor(this);
} }
public void Update(DateTime tick) public override void Update(DateTime tick)
{ {
var deltaTime = (tick - aiContainer.GetLatestUpdate()).Milliseconds; var deltaTime = (tick - aiContainer.GetLatestUpdate()).Milliseconds;
LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime); LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime);

View file

@ -129,6 +129,40 @@ namespace FFXIVClassic_Map_Server.lua
player.EndEvent(); player.EndEvent();
} }
/// <summary>
/// // todo: this is dumb, should probably make a function for each action with different default return values
/// or just make generic function and pass default value as first arg after functionName
/// </summary>
public static void CallLuaMonsterAction(Character actor, string functionName, params object[] args)
{
// todo: should we call this for players too?
if (actor is BattleNpc)
{
// todo: check this is correct
string path = $"./scripts/unique/{actor.zone.zoneName}/Monster/{actor.customDisplayName}.lua";
// dont wanna throw an error if file doesnt exist
if (File.Exists(path))
{
var script = LoadGlobals();
try
{
script.DoFile(path);
}
catch (Exception e)
{
Program.Log.Error($"LuaEngine.CallLuaMonsterAction [{functionName}] {e.Message}");
}
DynValue res = new DynValue();
if (!script.Globals.Get(functionName).IsNil())
{
res = script.Call(script.Globals.Get(functionName));
}
}
}
}
private static string GetScriptPath(Actor target) private static string GetScriptPath(Actor target)
{ {
if (target is Player) if (target is Player)

View file

@ -169,7 +169,7 @@ namespace FFXIVClassic_World_Server
{ {
uint sessionId = subpacket.header.targetId; uint sessionId = subpacket.header.targetId;
Session session = GetSession(sessionId); Session session = GetSession(sessionId);
subpacket.DebugPrintSubPacket(); //subpacket.DebugPrintSubPacket();
if (subpacket.gameMessage.opcode >= 0x1000) if (subpacket.gameMessage.opcode >= 0x1000)
{ {
//subpacket.DebugPrintSubPacket(); //subpacket.DebugPrintSubPacket();