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)
{
if (controller != null)
controller.MobSkill(target, mobSkillId);
controller.MonsterSkill(target, mobSkillId);
else
InternalMobSkill(target, mobSkillId);
}

View file

@ -9,6 +9,17 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{
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)
{
this.owner = owner;
@ -16,16 +27,36 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
}
public override void Update(DateTime tick)
{
var battleNpc = this.owner as BattleNpc;
if (battleNpc != null)
{
// 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)
{
// todo: check distance, last swing time, status effects
this.owner.aiContainer.InternalEngage(target);
return true;
var canEngage = this.owner.aiContainer.InternalEngage(target);
if (canEngage)
{
// reset casting
firstSpell = true;
// todo: adjust cooldowns with modifiers
}
return canEngage;
}
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 void Cast(Character target, uint spellId);
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 RangedAttack(Character target);
public virtual void Spawn() { }

View file

@ -13,18 +13,41 @@ using FFXIVClassic_Map_Server.packets.send.actor;
namespace FFXIVClassic_Map_Server.Actors
{
[Flags]
enum AggroType
{
None,
Sight,
Scent,
LowHp,
IgnoreLevelDifference
}
class BattleNpc : Npc
{
public HateContainer hateContainer;
public AggroType aggroType;
public BattleNpc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot,
ushort actorState, uint animationId, string 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.currentSubState = SetActorStatePacket.SUB_STATE_MONSTER;
//this.currentMainState = SetActorStatePacket.MAIN_STATE_ACTIVE;
//charaWork.property[2] = 1;
//npcWork.hateType = 1;
this.hateContainer = new HateContainer(this);
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;
GenerateActorName((int)actorNumber);
this.aiContainer = new AIContainer(this, null, new PathFind(this), new TargetFind(null));
}
public SubPacket CreateAddActorPacket()
@ -393,7 +394,7 @@ namespace FFXIVClassic_Map_Server.Actors
zone.DespawnActor(this);
}
public void Update(DateTime tick)
public override void Update(DateTime tick)
{
var deltaTime = (tick - aiContainer.GetLatestUpdate()).Milliseconds;
LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime);

View file

@ -129,6 +129,40 @@ namespace FFXIVClassic_Map_Server.lua
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)
{
if (target is Player)

View file

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