mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-02 19:42:05 -04:00
fixed death/despawning kinda (need to figure out why hp wont tick down after respawning)
This commit is contained in:
parent
c5cc7c2f00
commit
4978813c27
@ -401,6 +401,16 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
return GetAllActors<Actor>();
|
||||
}
|
||||
|
||||
public virtual List<Player> GetPlayers()
|
||||
{
|
||||
return GetAllActors<Player>();
|
||||
}
|
||||
|
||||
public virtual List<BattleNpc> GetMonsters()
|
||||
{
|
||||
return GetAllActors<BattleNpc>();
|
||||
}
|
||||
|
||||
public void BroadcastPacketsAroundActor(Actor actor, List<SubPacket> packets)
|
||||
{
|
||||
foreach (SubPacket packet in packets)
|
||||
@ -635,7 +645,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
a.Update(tick);
|
||||
|
||||
var deltaTime = (tick - Program.LastTick).TotalMilliseconds;
|
||||
LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime);
|
||||
LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
|
||||
public virtual void OnPath(Vector3 point)
|
||||
{
|
||||
lua.LuaEngine.CallLuaBattleAction(this, "onPath", this, point);
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onPath", this, point);
|
||||
|
||||
updateFlags |= ActorUpdateFlags.Position;
|
||||
this.isAtSpawn = false;
|
||||
@ -428,6 +428,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
|
||||
public virtual void Spawn(DateTime tick)
|
||||
{
|
||||
aiContainer.Reset();
|
||||
// todo: reset hp/mp/tp etc here
|
||||
ChangeState(SetActorStatePacket.MAIN_STATE_PASSIVE);
|
||||
charaWork.parameterSave.hp = charaWork.parameterSave.hpMax;
|
||||
@ -448,23 +449,23 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
|
||||
public bool IsDead()
|
||||
{
|
||||
return currentMainState == SetActorStatePacket.MAIN_STATE_DEAD || currentMainState == SetActorStatePacket.MAIN_STATE_DEAD2;
|
||||
return aiContainer.IsDead();
|
||||
}
|
||||
|
||||
public bool IsAlive()
|
||||
{
|
||||
return !IsDead();
|
||||
return !aiContainer.IsDead();
|
||||
}
|
||||
|
||||
public short GetHP()
|
||||
{
|
||||
// todo:
|
||||
return charaWork.parameterSave.hp[currentJob];
|
||||
return charaWork.parameterSave.hp[0];
|
||||
}
|
||||
|
||||
public short GetMaxHP()
|
||||
{
|
||||
return charaWork.parameterSave.hpMax[currentJob];
|
||||
return charaWork.parameterSave.hpMax[0];
|
||||
}
|
||||
|
||||
public short GetMP()
|
||||
@ -500,16 +501,20 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
// todo: the following functions are virtuals since we want to check hidden item bonuses etc on player for certain conditions
|
||||
public virtual void AddHP(int hp)
|
||||
{
|
||||
// todo: +/- hp and die
|
||||
// todo: battlenpcs probably have way more hp?
|
||||
var addHp = charaWork.parameterSave.hp[currentJob] + hp;
|
||||
addHp = addHp.Clamp(ushort.MinValue, charaWork.parameterSave.hpMax[currentJob]);
|
||||
charaWork.parameterSave.hp[currentJob] = (short)addHp;
|
||||
// dont wanna die ded
|
||||
if (IsAlive())
|
||||
{
|
||||
// todo: +/- hp and die
|
||||
// todo: battlenpcs probably have way more hp?
|
||||
var addHp = charaWork.parameterSave.hp[0] + hp;
|
||||
addHp = addHp.Clamp(ushort.MinValue, charaWork.parameterSave.hpMax[0]);
|
||||
charaWork.parameterSave.hp[0] = (short)addHp;
|
||||
|
||||
if (charaWork.parameterSave.hp[currentJob] < 1)
|
||||
Die(Program.Tick);
|
||||
if (charaWork.parameterSave.hp[0] < 1)
|
||||
Die(Program.Tick);
|
||||
|
||||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddMP(int mp)
|
||||
@ -580,21 +585,47 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
|
||||
// todo: call onAttack/onDamageTaken
|
||||
target.DelHP(action.amount);
|
||||
if (target is BattleNpc)
|
||||
((BattleNpc)target).lastAttacker = this;
|
||||
}
|
||||
|
||||
public virtual void OnCast(State state, BattleAction[] actions, ref BattleAction[] errors)
|
||||
{
|
||||
var spell = ((MagicState)state).GetSpell();
|
||||
// damage is handled in script
|
||||
this.DelMP(spell.mpCost); // mpCost can be set in script e.g. if caster has something for free spells
|
||||
|
||||
if (target is BattleNpc)
|
||||
((BattleNpc)target).lastAttacker = this;
|
||||
}
|
||||
|
||||
public virtual void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors)
|
||||
{
|
||||
var skill = ((WeaponSkillState)state).GetWeaponSkill();
|
||||
// damage is handled in script
|
||||
this.DelTP(skill.tpCost);
|
||||
|
||||
if (target is BattleNpc)
|
||||
((BattleNpc)target).lastAttacker = this;
|
||||
}
|
||||
|
||||
public virtual void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors)
|
||||
{
|
||||
if (target is BattleNpc)
|
||||
((BattleNpc)target).lastAttacker = this;
|
||||
}
|
||||
|
||||
public virtual void OnSpawn()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void OnDeath()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void OnDespawn()
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ namespace FFXIVClassic_Map_Server.actors.chara
|
||||
|
||||
HarvestPotency = 38,
|
||||
HarvestLimit = 39,
|
||||
HarvestRate = 40
|
||||
HarvestRate = 40,
|
||||
|
||||
Raise = 41,
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||
public bool IsDead()
|
||||
{
|
||||
return owner.currentMainState == SetActorStatePacket.MAIN_STATE_DEAD ||
|
||||
owner.currentMainState == SetActorStatePacket.MAIN_STATE_DEAD2 || owner.GetHP() == 0;
|
||||
owner.currentMainState == SetActorStatePacket.MAIN_STATE_DEAD2;
|
||||
}
|
||||
|
||||
public bool IsRoaming()
|
||||
@ -262,8 +262,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||
|
||||
public void InternalChangeTarget(Character target)
|
||||
{
|
||||
// todo: use invalid target id
|
||||
// todo: this is retarded, call entity's changetarget function
|
||||
// targets are changed in the controller
|
||||
if (IsEngaged() || target == null)
|
||||
{
|
||||
|
||||
@ -288,7 +287,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||
|
||||
if (CanChangeState() || (GetCurrentState() != null && GetCurrentState().IsCompleted()))
|
||||
{
|
||||
ForceChangeState(new AttackState(this.owner, target));
|
||||
ForceChangeState(new AttackState(owner, target));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -301,7 +300,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||
|
||||
owner.updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
ChangeTarget(null);
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_PASSIVE);
|
||||
|
||||
if (owner.currentMainState == SetActorStatePacket.MAIN_STATE_ACTIVE)
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_PASSIVE);
|
||||
|
||||
ClearStates();
|
||||
}
|
||||
|
||||
@ -337,11 +339,18 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||
}
|
||||
}
|
||||
|
||||
public void InternalDie(DateTime tick, uint timeToFadeout)
|
||||
public void InternalDie(DateTime tick, uint fadeoutTimerSeconds)
|
||||
{
|
||||
pathFind?.Clear();
|
||||
ClearStates();
|
||||
ForceChangeState(new DeathState(owner, tick, fadeoutTimerSeconds));
|
||||
}
|
||||
|
||||
public void InternalDespawn(DateTime tick, uint respawnTimerSeconds)
|
||||
{
|
||||
ClearStates();
|
||||
Disengage();
|
||||
ForceChangeState(new DeathState(owner, tick, timeToFadeout));
|
||||
ForceChangeState(new DespawnState(owner, respawnTimerSeconds));
|
||||
}
|
||||
|
||||
public void InternalRaise(Character target)
|
||||
|
@ -384,12 +384,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||
// todo: use tick instead of now?
|
||||
this.startTime = DateTime.Now;
|
||||
this.lastTick = startTime;
|
||||
|
||||
// todo: set the effect name to be called by scripts or just lookup effects in db
|
||||
// name = WorldManager.GetEffectInfo(id).Name;
|
||||
// todo: check if can gain effect
|
||||
// todo: call effect's onGain
|
||||
// todo: broadcast effect gain packet
|
||||
}
|
||||
|
||||
public StatusEffect(Character owner, StatusEffect effect)
|
||||
|
@ -96,6 +96,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
||||
{
|
||||
var target = owner.target;
|
||||
base.Disengage();
|
||||
owner.statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnDeath, true);
|
||||
// todo:
|
||||
lastActionTime = lastUpdate.AddSeconds(5);
|
||||
owner.isMovingToSpawn = true;
|
||||
@ -104,7 +105,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
||||
neutralTime = lastActionTime;
|
||||
owner.hateContainer.ClearHate();
|
||||
owner.moveState = 1;
|
||||
lua.LuaEngine.CallLuaBattleAction(owner, "onDisengage", owner, target, Utils.UnixTimeStampUTC(battleStartTime));
|
||||
lua.LuaEngine.CallLuaBattleFunction(owner, "onDisengage", owner, target, Utils.UnixTimeStampUTC(battleStartTime));
|
||||
}
|
||||
|
||||
public override void Cast(Character target, uint spellId)
|
||||
@ -203,7 +204,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
||||
}
|
||||
|
||||
Move();
|
||||
lua.LuaEngine.CallLuaBattleAction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC());
|
||||
lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick));
|
||||
}
|
||||
|
||||
private void Move()
|
||||
@ -308,6 +309,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
||||
|
||||
public bool CanDetectTarget(Character target, bool forceSight = false)
|
||||
{
|
||||
if (owner.IsDead())
|
||||
return false;
|
||||
|
||||
// todo: this should probably be changed to only allow detection at end of path?
|
||||
if (owner.aiContainer.pathFind.IsFollowingScriptedPath() || owner.aiContainer.pathFind.IsFollowingPath() && !owner.aiContainer.pathFind.AtPoint())
|
||||
{
|
||||
|
@ -33,15 +33,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
public override bool Update(DateTime tick)
|
||||
{
|
||||
/*
|
||||
TryInterrupt();
|
||||
|
||||
if (interrupt)
|
||||
{
|
||||
OnInterrupt();
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
if ((target == null || owner.target != target || owner.target?.actorId != owner.currentLockedTarget) && owner.isAutoAttackEnabled)
|
||||
owner.aiContainer.ChangeTarget(target = owner.zone.FindActorInArea<Character>(owner.currentLockedTarget));
|
||||
@ -159,7 +150,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
// todo: shouldnt need to check if owner is dead since all states would be cleared
|
||||
if (owner.aiContainer.IsDead() || target.aiContainer.IsDead())
|
||||
{
|
||||
target = null;
|
||||
owner.aiContainer.ChangeTarget(null);
|
||||
return false;
|
||||
}
|
||||
else if (!owner.aiContainer.GetTargetFind().CanTarget(target, false, true))
|
||||
|
@ -14,8 +14,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
public DeathState(Character owner, DateTime tick, uint timeToFadeOut)
|
||||
: base(owner, null)
|
||||
{
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD);
|
||||
owner.Disengage();
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD);
|
||||
canInterrupt = false;
|
||||
startTime = tick;
|
||||
despawnTime = startTime.AddSeconds(timeToFadeOut);
|
||||
@ -23,17 +23,18 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
|
||||
public override bool Update(DateTime tick)
|
||||
{
|
||||
// todo: set a flag on chara for accept raise, play animation and spawn
|
||||
if (owner.GetMod((uint)Modifier.Raise) > 0)
|
||||
{
|
||||
owner.Spawn(tick);
|
||||
return true;
|
||||
}
|
||||
|
||||
// todo: handle raise etc
|
||||
if (tick >= despawnTime)
|
||||
{
|
||||
if (owner is BattleNpc)
|
||||
{
|
||||
owner.Despawn(tick);
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: queue a warp for the player
|
||||
}
|
||||
// todo: for players, return them to homepoint
|
||||
owner.Despawn(tick);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -10,22 +10,21 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
||||
{
|
||||
class DespawnState : State
|
||||
{
|
||||
private DateTime endTime;
|
||||
public DespawnState(Character owner, Character target, uint despawnTimeSeconds) :
|
||||
private DateTime respawnTime;
|
||||
public DespawnState(Character owner, uint respawnTimeSeconds) :
|
||||
base(owner, null)
|
||||
{
|
||||
startTime = Program.Tick;
|
||||
endTime = startTime.AddSeconds(despawnTimeSeconds);
|
||||
respawnTime = startTime.AddSeconds(respawnTimeSeconds);
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD2);
|
||||
owner.OnDespawn();
|
||||
}
|
||||
|
||||
public override bool Update(DateTime tick)
|
||||
{
|
||||
if (tick >= endTime)
|
||||
if (tick >= respawnTime)
|
||||
{
|
||||
// todo: send packet to despawn the npc, set it so npc is despawned when requesting spawn packets
|
||||
owner.zone.BroadcastPacketAroundActor(owner, RemoveActorPacket.BuildPacket(owner.actorId));
|
||||
owner.QueuePositionUpdate(owner.spawnX, owner.spawnY, owner.spawnZ);
|
||||
lua.LuaEngine.CallLuaBattleAction(owner, "onDespawn", owner);
|
||||
owner.Spawn(tick);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -15,6 +15,8 @@ using FFXIVClassic_Map_Server.actors.chara.ai.state;
|
||||
using FFXIVClassic_Map_Server.utils;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor.battle;
|
||||
using FFXIVClassic_Map_Server.actors.chara.ai.utils;
|
||||
using FFXIVClassic_Map_Server.actors.group;
|
||||
using FFXIVClassic_Map_Server.packets.send;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
@ -34,8 +36,10 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
public AggroType aggroType;
|
||||
public bool neutral;
|
||||
private uint despawnTime;
|
||||
private uint respawnTime;
|
||||
private uint spawnDistance;
|
||||
|
||||
public Character lastAttacker;
|
||||
|
||||
public BattleNpc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot,
|
||||
ushort actorState, uint animationId, string customDisplayName)
|
||||
@ -56,15 +60,38 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
spawnY = posY;
|
||||
spawnZ = posZ;
|
||||
|
||||
// todo: read this from db
|
||||
// todo: read these from db also
|
||||
aggroType = AggroType.Sight;
|
||||
this.moveState = 2;
|
||||
ResetMoveSpeeds();
|
||||
despawnTime = 10;
|
||||
|
||||
respawnTime = 30;
|
||||
CalculateBaseStats();
|
||||
}
|
||||
|
||||
public override List<SubPacket> GetSpawnPackets(Player player, ushort spawnType)
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
if (IsAlive())
|
||||
{
|
||||
subpackets.Add(CreateAddActorPacket());
|
||||
subpackets.AddRange(GetEventConditionPackets());
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(0x0));
|
||||
|
||||
subpackets.Add(CreateAppearancePacket());
|
||||
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIdleAnimationPacket());
|
||||
subpackets.Add(CreateInitStatusPacket());
|
||||
subpackets.Add(CreateSetActorIconPacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket(player));
|
||||
}
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public uint GetAggroType()
|
||||
{
|
||||
return (uint)aggroType;
|
||||
@ -135,6 +162,16 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
despawnTime = seconds;
|
||||
}
|
||||
|
||||
public uint GetRespawnTime()
|
||||
{
|
||||
return respawnTime;
|
||||
}
|
||||
|
||||
public void SetRespawnTime(uint seconds)
|
||||
{
|
||||
respawnTime = seconds;
|
||||
}
|
||||
|
||||
///<summary> // todo: create an action object? </summary>
|
||||
public bool OnAttack(AttackState state)
|
||||
{
|
||||
@ -143,32 +180,61 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
|
||||
public override void Spawn(DateTime tick)
|
||||
{
|
||||
base.Spawn(tick);
|
||||
if (respawnTime > 0)
|
||||
{
|
||||
base.Spawn(tick);
|
||||
|
||||
this.isMovingToSpawn = false;
|
||||
this.ResetMoveSpeeds();
|
||||
this.hateContainer.ClearHate();
|
||||
this.ChangeState(SetActorStatePacket.MAIN_STATE_PASSIVE);
|
||||
this.isMovingToSpawn = false;
|
||||
this.ResetMoveSpeeds();
|
||||
this.hateContainer.ClearHate();
|
||||
zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01));
|
||||
zone.BroadcastPacketsAroundActor(this, GetInitPackets());
|
||||
charaWork.parameterSave.hp = charaWork.parameterSave.hpMax;
|
||||
charaWork.parameterSave.mp = charaWork.parameterSave.mpMax;
|
||||
RecalculateStats();
|
||||
|
||||
updateFlags |= ActorUpdateFlags.AllNpc;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Die(DateTime tick)
|
||||
{
|
||||
if (IsAlive())
|
||||
{
|
||||
if (lastAttacker is Pet && ((Pet)lastAttacker).master is Player)
|
||||
{
|
||||
lastAttacker = ((Pet)lastAttacker).master;
|
||||
}
|
||||
|
||||
if (lastAttacker is Player)
|
||||
{
|
||||
if (lastAttacker.currentParty != null && lastAttacker.currentParty is Party)
|
||||
{
|
||||
foreach (var memberId in ((Party)lastAttacker.currentParty).members)
|
||||
{
|
||||
var partyMember = zone.FindActorInArea<Player>(memberId);
|
||||
// onDeath(monster, player, killer)
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, partyMember, lastAttacker);
|
||||
// <actor> defeat/defeats <target>
|
||||
((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// onDeath(monster, player, killer)
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, lastAttacker, lastAttacker);
|
||||
((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0)));
|
||||
}
|
||||
}
|
||||
aiContainer.InternalDie(tick, despawnTime);
|
||||
aiContainer.pathFind.Clear();
|
||||
|
||||
this.ResetMoveSpeeds();
|
||||
this.positionX = oldPositionX;
|
||||
this.positionY = oldPositionY;
|
||||
this.positionZ = oldPositionZ;
|
||||
|
||||
|
||||
this.isAtSpawn = true;
|
||||
// todo: reset cooldowns
|
||||
}
|
||||
else
|
||||
{
|
||||
var err = $"[{actorId}][{customDisplayName}] {positionX} {positionY} {positionZ} {GetZoneID()} tried to die ded";
|
||||
var err = $"[{actorId}][{GetUniqueId()}] {positionX} {positionY} {positionZ} {GetZone().GetName()} tried to die ded";
|
||||
Program.Log.Error(err);
|
||||
//throw new Exception(err);
|
||||
}
|
||||
@ -176,9 +242,10 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
|
||||
public override void Despawn(DateTime tick)
|
||||
{
|
||||
aiContainer.ClearStates();
|
||||
// todo: probably didnt need to make a new state...
|
||||
aiContainer.ForceChangeState(new DespawnState(this, null, 0));
|
||||
aiContainer.InternalDespawn(tick, respawnTime);
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onDespawn", this);
|
||||
this.isAtSpawn = true;
|
||||
}
|
||||
|
||||
public void OnRoam(DateTime tick)
|
||||
@ -203,6 +270,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
else
|
||||
{
|
||||
this.isMovingToSpawn = false;
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onRoam", this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,5 +285,20 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
// todo: move this somewhere else prolly and change based on model/appearance (so maybe in Character.cs instead)
|
||||
action.animation = 0x11001000; // (temporary) wolf anim
|
||||
}
|
||||
|
||||
public override void OnSpawn()
|
||||
{
|
||||
base.OnSpawn();
|
||||
}
|
||||
|
||||
public override void OnDeath()
|
||||
{
|
||||
base.OnDeath();
|
||||
}
|
||||
|
||||
public override void OnDespawn()
|
||||
{
|
||||
base.OnDespawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,13 +58,15 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
|
||||
charaWork.battleSave.potencial = 1.0f;
|
||||
|
||||
charaWork.parameterSave.state_mainSkill[0] = 3;
|
||||
charaWork.parameterSave.state_mainSkill[2] = 3;
|
||||
charaWork.parameterSave.state_mainSkillLevel = 2;
|
||||
|
||||
charaWork.parameterSave.hp[0] = 500;
|
||||
charaWork.parameterSave.hpMax[0] = 500;
|
||||
// todo: these really need to be read from db etc
|
||||
{
|
||||
charaWork.parameterSave.state_mainSkill[0] = 3;
|
||||
charaWork.parameterSave.state_mainSkill[2] = 3;
|
||||
charaWork.parameterSave.state_mainSkillLevel = 1;
|
||||
|
||||
charaWork.parameterSave.hp[0] = 80;
|
||||
charaWork.parameterSave.hpMax[0] = 80;
|
||||
}
|
||||
for (int i = 0; i < 32; i++ )
|
||||
charaWork.property[i] = (byte)(((int)actorClass.propertyFlags >> i) & 1);
|
||||
|
||||
@ -400,13 +402,30 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
aiContainer.Update(tick);
|
||||
}
|
||||
|
||||
//A party member list packet came, set the party
|
||||
/* public void SetParty(MonsterPartyGroup group)
|
||||
public override void OnSpawn()
|
||||
{
|
||||
if (group is MonsterPartyGroup)
|
||||
currentParty = group;
|
||||
base.OnSpawn();
|
||||
}
|
||||
*/
|
||||
|
||||
public override void OnDeath()
|
||||
{
|
||||
base.OnDeath();
|
||||
}
|
||||
|
||||
public override void OnDespawn()
|
||||
{
|
||||
zone.BroadcastPacketAroundActor(this, RemoveActorPacket.BuildPacket(this.actorId));
|
||||
zone.BroadcastPacketAroundActor(this, RemoveActorPacket.BuildPacket(this.actorId));
|
||||
QueuePositionUpdate(spawnX, spawnY, spawnZ);
|
||||
LuaEngine.CallLuaBattleFunction(this, "onDespawn", this);
|
||||
}
|
||||
//A party member list packet came, set the party
|
||||
/* public void SetParty(MonsterPartyGroup group)
|
||||
{
|
||||
if (group is MonsterPartyGroup)
|
||||
currentParty = group;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
class Pet : BattleNpc
|
||||
{
|
||||
public Character master;
|
||||
public Pet(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)
|
||||
|
@ -1781,21 +1781,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
base.PostUpdate(tick, packets);
|
||||
}
|
||||
|
||||
public override void AddHP(int hp)
|
||||
{
|
||||
// todo: +/- hp and die
|
||||
// todo: check hidden effects and shit
|
||||
var addHp = charaWork.parameterSave.hp[currentJob] + hp;
|
||||
addHp = addHp.Clamp(ushort.MinValue, charaWork.parameterSave.hpMax[currentJob]);
|
||||
charaWork.parameterSave.hp[currentJob] = (short)addHp;
|
||||
|
||||
if (charaWork.parameterSave.hp[currentJob] < 1)
|
||||
Die(Program.Tick);
|
||||
|
||||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
}
|
||||
|
||||
|
||||
public override void Die(DateTime tick)
|
||||
{
|
||||
// todo: death timer
|
||||
@ -1981,7 +1966,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
if (aiContainer.CanChangeState())
|
||||
aiContainer.Cast(zone.FindActorInArea<Character>(targetId == 0 ? currentTarget : targetId), spellId);
|
||||
else if (aiContainer.GetCurrentState() is MagicState)
|
||||
else if (aiContainer.IsCurrentState<MagicState>())
|
||||
// You are already casting.
|
||||
SendGameMessage(Server.GetWorldManager().GetActor(), 32536, 0x20);
|
||||
else
|
||||
@ -2141,7 +2126,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
//action.animation = 0x19001000;
|
||||
}
|
||||
var target = state.GetTarget();
|
||||
//if (target is BattleNpc)
|
||||
if (target is BattleNpc)
|
||||
{
|
||||
((BattleNpc)target).hateContainer.UpdateHate(this, action.amount);
|
||||
}
|
||||
@ -2164,6 +2149,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||
var skill = ((WeaponSkillState)state).GetWeaponSkill();
|
||||
// todo: should just make a thing that updates the one slot cause this is dumb as hell
|
||||
UpdateHotbarTimer(skill.id, skill.recastTimeSeconds);
|
||||
// todo: this really shouldnt be called on each ws?
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onWeaponSkill", this, state.GetTarget(), skill);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,9 +134,10 @@ namespace FFXIVClassic_Map_Server.lua
|
||||
/// // 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 CallLuaBattleAction(Character actor, string functionName, params object[] args)
|
||||
public static void CallLuaBattleFunction(Character actor, string functionName, params object[] args)
|
||||
{
|
||||
string path = $"./scripts/unique/{actor.zone.zoneName}/Monster/{actor.customDisplayName}.lua";
|
||||
// todo: should use "scripts/zones/ZONE_NAME/battlenpcs/NAME.lua" instead of scripts/unique
|
||||
string path = "";
|
||||
|
||||
// todo: should we call this for players too?
|
||||
if (actor is Player)
|
||||
@ -144,6 +145,12 @@ namespace FFXIVClassic_Map_Server.lua
|
||||
// todo: check this is correct
|
||||
path = FILEPATH_PLAYER;
|
||||
}
|
||||
else if (actor is Npc)
|
||||
{
|
||||
// todo: this is probably unnecessary as im not sure there were pets for players
|
||||
if (!(actor is Pet && ((Pet)actor).master is Player))
|
||||
path = String.Format("./scripts/unique/{0}/{1}/{2}.lua", actor.zone.zoneName, actor is BattleNpc ? "Monster" : "PopulaceStandard", ((Npc)actor).GetUniqueId());
|
||||
}
|
||||
// dont wanna throw an error if file doesnt exist
|
||||
if (File.Exists(path))
|
||||
{
|
||||
@ -154,7 +161,7 @@ namespace FFXIVClassic_Map_Server.lua
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Program.Log.Error($"LuaEngine.CallLuaBattleAction [{functionName}] {e.Message}");
|
||||
Program.Log.Error($"LuaEngine.CallLuaBattleFunction [{functionName}] {e.Message}");
|
||||
}
|
||||
DynValue res = new DynValue();
|
||||
|
||||
@ -167,6 +174,7 @@ namespace FFXIVClassic_Map_Server.lua
|
||||
|
||||
public static int CallLuaStatusEffectFunction(Character actor, StatusEffect effect, string functionName, params object[] args)
|
||||
{
|
||||
// todo: this is stupid, load the actual effect crap
|
||||
var name = ((StatusEffectId)effect.GetStatusEffectId()).ToString().ToLower();
|
||||
string path = $"./scripts/effects/{name}.lua";
|
||||
|
||||
|
@ -116,6 +116,12 @@ namespace FFXIVClassic_Map_Server
|
||||
|
||||
public static void WriteLuaParams(BinaryWriter writer, List<LuaParam> luaParams)
|
||||
{
|
||||
if (luaParams == null)
|
||||
{
|
||||
Program.Log.Error("LuaUtils.WriteLuaParams LuaParams are null!");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (LuaParam l in luaParams)
|
||||
{
|
||||
if (l.typeID == 0x1)
|
||||
|
@ -61,7 +61,7 @@ function onEventStarted(player, actor, triggerName)
|
||||
|
||||
end
|
||||
|
||||
function onUpdate()
|
||||
function onUpdate(deltaTime, area)
|
||||
end
|
||||
|
||||
function onTalkEvent(player, npc)
|
||||
|
Loading…
Reference in New Issue
Block a user