1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-23 21:27:46 +00:00

added ion's and showmo's enums

- added nullable DateTime param to UnixTimeStampUTC
This commit is contained in:
Tahir Akhlaq 2017-08-26 17:39:28 +01:00
parent 1ae15df64c
commit c070f5b80e
10 changed files with 188 additions and 19 deletions

View file

@ -84,10 +84,10 @@ namespace FFXIVClassic.Common
return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray()); return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray());
} }
public static uint UnixTimeStampUTC() public static uint UnixTimeStampUTC(DateTime? time = null)
{ {
uint unixTimeStamp; uint unixTimeStamp;
var currentTime = DateTime.Now; var currentTime = time ?? DateTime.Now;
var zuluTime = currentTime.ToUniversalTime(); var zuluTime = currentTime.ToUniversalTime();
var unixEpoch = new DateTime(1970, 1, 1); var unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (uint)zuluTime.Subtract(unixEpoch).TotalSeconds; unixTimeStamp = (uint)zuluTime.Subtract(unixEpoch).TotalSeconds;
@ -95,10 +95,10 @@ namespace FFXIVClassic.Common
return unixTimeStamp; return unixTimeStamp;
} }
public static ulong MilisUnixTimeStampUTC() public static ulong MilisUnixTimeStampUTC(DateTime? time = null)
{ {
ulong unixTimeStamp; ulong unixTimeStamp;
var currentTime = DateTime.Now; var currentTime = time ?? DateTime.Now;
var zuluTime = currentTime.ToUniversalTime(); var zuluTime = currentTime.ToUniversalTime();
var unixEpoch = new DateTime(1970, 1, 1); var unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (ulong)zuluTime.Subtract(unixEpoch).TotalMilliseconds; unixTimeStamp = (ulong)zuluTime.Subtract(unixEpoch).TotalMilliseconds;

View file

@ -98,7 +98,7 @@ namespace FFXIVClassic_Map_Server.Actors
public ushort currentJob; public ushort currentJob;
public Character(uint actorID) : base(actorID) public Character(uint actorID) : base(actorID)
{ {
//Init timer array to "notimer" //Init timer array to "notimer"
for (int i = 0; i < charaWork.statusShownTime.Length; i++) for (int i = 0; i < charaWork.statusShownTime.Length; i++)
charaWork.statusShownTime[i] = 0xFFFFFFFF; charaWork.statusShownTime[i] = 0xFFFFFFFF;
@ -109,7 +109,7 @@ namespace FFXIVClassic_Map_Server.Actors
ResetMoveSpeeds(); ResetMoveSpeeds();
// todo: base this on equip and shit // todo: base this on equip and shit
SetMod((uint)Modifier.AttackRange, 3); SetMod((uint)Modifier.AttackRange, 3);
SetMod((uint)Modifier.AttackDelay, (Program.Random.Next(30,60) * 100)); SetMod((uint)Modifier.AttackDelay, (Program.Random.Next(30, 60) * 100));
} }
public SubPacket CreateAppearancePacket() public SubPacket CreateAppearancePacket()
@ -120,7 +120,7 @@ namespace FFXIVClassic_Map_Server.Actors
public SubPacket CreateInitStatusPacket() public SubPacket CreateInitStatusPacket()
{ {
return (SetActorStatusAllPacket.BuildPacket(actorId, charaWork.status)); return (SetActorStatusAllPacket.BuildPacket(actorId, charaWork.status));
} }
public SubPacket CreateSetActorIconPacket() public SubPacket CreateSetActorIconPacket()
@ -148,7 +148,7 @@ namespace FFXIVClassic_Map_Server.Actors
currentContentGroup = group; currentContentGroup = group;
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/currentContentGroup", this); ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/currentContentGroup", this);
propPacketUtil.AddProperty("charaWork.currentContentGroup"); propPacketUtil.AddProperty("charaWork.currentContentGroup");
zone.BroadcastPacketsAroundActor(this, propPacketUtil.Done()); zone.BroadcastPacketsAroundActor(this, propPacketUtil.Done());
} }
@ -167,7 +167,7 @@ namespace FFXIVClassic_Map_Server.Actors
} }
public void PlayAnimation(uint animId, bool onlySelf = false) public void PlayAnimation(uint animId, bool onlySelf = false)
{ {
if (onlySelf) if (onlySelf)
{ {
if (this is Player) if (this is Player)
@ -236,7 +236,7 @@ namespace FFXIVClassic_Map_Server.Actors
if (updateFlags != ActorUpdateFlags.None) if (updateFlags != ActorUpdateFlags.None)
{ {
packets = packets ?? new List<SubPacket>(); packets = packets ?? new List<SubPacket>();
if ((updateFlags & ActorUpdateFlags.Appearance) != 0) if ((updateFlags & ActorUpdateFlags.Appearance) != 0)
{ {
packets.Add(new SetActorAppearancePacket(modelId, appearanceIds).BuildPacket(actorId)); packets.Add(new SetActorAppearancePacket(modelId, appearanceIds).BuildPacket(actorId));
@ -322,6 +322,11 @@ namespace FFXIVClassic_Map_Server.Actors
aiContainer.Cast(Server.GetWorldManager().GetActorInWorld(targetId == 0 ? currentTarget : targetId) as Character, spellId); aiContainer.Cast(Server.GetWorldManager().GetActorInWorld(targetId == 0 ? currentTarget : targetId) as Character, spellId);
} }
public void Ability(uint abilityId, uint targetId = 0)
{
aiContainer.Ability(Server.GetWorldManager().GetActorInWorld(targetId == 0 ? currentTarget : targetId) as Character, abilityId);
}
public void WeaponSkill(uint skillId) public void WeaponSkill(uint skillId)
{ {
aiContainer.WeaponSkill(Server.GetWorldManager().GetActorInWorld(currentTarget) as Character, skillId); aiContainer.WeaponSkill(Server.GetWorldManager().GetActorInWorld(currentTarget) as Character, skillId);

View file

@ -113,7 +113,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public bool CanChangeState() public bool CanChangeState()
{ {
return states.Count == 0 || states.Peek().CanInterrupt(); return GetCurrentState() == null || states.Peek().CanInterrupt();
} }
public void ChangeTarget(Character target) public void ChangeTarget(Character target)
@ -217,6 +217,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
InternalDisengage(); InternalDisengage();
} }
public void Ability(Character target, uint abilityId)
{
if (controller != null)
controller.Ability(target, abilityId);
else
InternalAbility(target, abilityId);
}
public void Cast(Character target, uint spellId) public void Cast(Character target, uint spellId)
{ {
if (controller != null) if (controller != null)
@ -293,6 +301,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
ClearStates(); ClearStates();
} }
public void InternalAbility(Character target, uint abilityId)
{
}
public void InternalCast(Character target, uint spellId) public void InternalCast(Character target, uint spellId)
{ {
ChangeState(new MagicState(owner, target, (ushort)spellId)); ChangeState(new MagicState(owner, target, (ushort)spellId));

View file

@ -68,7 +68,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
public override void Ability(Character target, uint abilityId) public override void Ability(Character target, uint abilityId)
{ {
owner.aiContainer.InternalAbility(target, abilityId);
} }
public override void RangedAttack(Character target) public override void RangedAttack(Character target)

View file

@ -18,9 +18,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
public AttackState(Character owner, Character target) : public AttackState(Character owner, Character target) :
base(owner, target) base(owner, target)
{ {
this.canInterrupt = true;
this.startTime = DateTime.Now;
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE); owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
owner.aiContainer.ChangeTarget(target); owner.aiContainer.ChangeTarget(target);
this.startTime = DateTime.Now;
attackTime = startTime; attackTime = startTime;
owner.aiContainer.pathFind?.Clear(); owner.aiContainer.pathFind?.Clear();
// todo: should handle everything here instead of on next tick.. // todo: should handle everything here instead of on next tick..

View file

@ -8,6 +8,7 @@ using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.packets.send.actor.battle; using FFXIVClassic_Map_Server.packets.send.actor.battle;
using FFXIVClassic_Map_Server.packets.send; using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.utils;
namespace FFXIVClassic_Map_Server.actors.chara.ai.state namespace FFXIVClassic_Map_Server.actors.chara.ai.state
{ {
@ -56,12 +57,21 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
// todo: check within attack range // todo: check within attack range
startPos = owner.GetPosAsVector3(); startPos = owner.GetPosAsVector3();
owner.LookAt(target); owner.LookAt(target);
float[] baseCastDuration = { 1.0f, 0.25f };
foreach (var player in owner.zone.GetActorsAroundActor<Player>(owner, 50)) float spellSpeed = spell.castTimeSeconds;
List<SubPacket> packets = new List<SubPacket>();
// command casting duration
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER)
{ {
// todo: this is retarded, prolly doesnt do what i think its gonna do // todo: modify spellSpeed based on modifiers and stuff
//player.QueuePacket(BattleActionX01Packet.BuildPacket(player.actorId, owner.actorId, target != null ? target.actorId : 0xC0000000, spell.battleAnimation, spell.effectAnimation, 0, spell.id, 0, (byte)spell.castTimeSeconds)); // ((Player)owner).SendStartCastBar(spell.id, Utils.UnixTimeStampUTC(DateTime.Now.AddSeconds(spellSpeed)));
} }
// todo: change
owner.zone.BroadcastPacketsAroundActor(owner, packets);
} }
} }
@ -160,5 +170,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
{ {
return (Utils.DistanceSquared(owner.GetPosAsVector3(), startPos) > 4.0f); return (Utils.DistanceSquared(owner.GetPosAsVector3(), startPos) > 4.0f);
} }
public override void Cleanup()
{
// command casting duration
var packets = new List<SubPacket>();
if (owner.currentSubState == SetActorStatePacket.SUB_STATE_PLAYER)
{
// ((Player)owner).SendStartCastBar(0, 0);
}
owner.zone.BroadcastPacketsAroundActor(owner, packets);
}
} }
} }

View file

@ -1,8 +1,6 @@
using FFXIVClassic.Common; using FFXIVClassic.Common;
using System; using System;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorStatePacket class SetActorStatePacket

View file

@ -6,10 +6,21 @@ using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorSubStatPacket class SetActorSubStatPacket
{ {
public const ushort OPCODE = 0x144; public const ushort OPCODE = 0x144;
public const uint PACKET_SIZE = 0x28; public const uint PACKET_SIZE = 0x28;
enum SubStat : int
{
Breakage = 0x00, // (index goes high to low, bitflags)
Chant = 0x01, // [Nibbles: left / right hand = value]) (AKA SubStatObject)
Guard = 0x02, // [left / right hand = true] 0,1,2,3) ||| High byte also defines how many bools to use as flags for byte 0x4.
Waste = 0x03, // (High Nibble)
Mode = 0x04, // ???
Unknown = 0x05, // ???
SubStatMotionPack = 0x06,
Unknown2 = 0x07,
}
public static SubPacket BuildPacket(uint sourceActorId, byte breakage, int leftChant, int rightChant, int guard, int wasteStat, int statMode, uint idleAnimationId) public static SubPacket BuildPacket(uint sourceActorId, byte breakage, int leftChant, int rightChant, int guard, int wasteStat, int statMode, uint idleAnimationId)
{ {
byte[] data = new byte[PACKET_SIZE - 0x20]; byte[] data = new byte[PACKET_SIZE - 0x20];

View file

@ -10,6 +10,89 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle
Disengage = 12002, Disengage = 12002,
Attack = 22104, Attack = 22104,
} }
//These flags can be stacked and mixed, but the client will prioritize certain flags over others.
[Flags]
public enum HitEffect : uint
{
//Not setting RecoilLv2 or RecoilLv3 results in the weaker RecoilLv1.
//These are the recoil animations that play on the target, ranging from weak to strong.
//The recoil that gets set was likely based on the percentage of HP lost from the attack.
RecoilLv1 = 0,
RecoilLv2 = 1 << 0,
RecoilLv3 = 1 << 1,
//Setting both recoil flags triggers the "Critical!" pop-up text and hit visual effect.
CriticalHit = RecoilLv2 | RecoilLv3,
//Hit visual and sound effects when connecting with the target.
//Mixing these flags together will yield different results.
//Each visual likely relates to a specific weapon.
//Ex: HitVisual4 flag alone appears to be the visual and sound effect for hand-to-hand attacks.
HitVisual1 = 1 << 2,
HitVisual2 = 1 << 3,
HitVisual3 = 1 << 4,
HitVisual4 = 1 << 5,
//An additional visual effect that plays on the target when attacked if:
//The attack is physical and they have the protect buff on.
//The attack is magical and they have the shell buff on.
//Special Note: Shell was removed in later versions of the game.
//Another effect plays when both Protect and Shell flags are activated.
//Not sure what this effect is.
//Random guess: if the attack was a hybrid of both physical and magical and the target had both Protect and Shell buffs applied.
Protect = 1 << 6,
Shell = 1 << 7,
ProtectShellSpecial = Protect | Shell,
//Unknown = 1 << 8, -- Not sure what this flag does.
//If only HitEffect1 is set out of the hit effects, the "Evade!" pop-up text triggers along with the evade visual.
//If no hit effects are set, the "Miss!" pop-up is triggered and no hit visual is played.
HitEffect1 = 1 << 9,
HitEffect2 = 1 << 10, //Plays the standard hit visual effect, but with no sound if used alone.
Hit = HitEffect1 | HitEffect2, //A standard hit effect with sound effect.
HitEffect3 = 1 << 11,
HitEffect4 = 1 << 12,
HitEffect5 = 1 << 13,
GustyHitEffect = HitEffect3 | HitEffect2,
GreenTintedHitEffect = HitEffect4 | HitEffect1,
//Knocks you back away from the attacker.
KnockbackLv1 = HitEffect4 | HitEffect2 | HitEffect1,
KnockbackLv2 = HitEffect4 | HitEffect3,
KnockbackLv3 = HitEffect4 | HitEffect3 | HitEffect1,
KnockbackLv4 = HitEffect4 | HitEffect3 | HitEffect2,
KnockbackLv5 = HitEffect4 | HitEffect3 | HitEffect2 | HitEffect1,
//Knocks you away from the attacker in a counter-clockwise direction.
KnockbackCounterClockwiseLv1 = HitEffect5,
KnockbackCounterClockwiseLv2 = HitEffect5 | HitEffect1,
//Knocks you away from the attacker in a clockwise direction.
KnockbackClockwiseLv1 = HitEffect5 | HitEffect2,
KnockbackClockwiseLv2 = HitEffect5 | HitEffect2 | HitEffect1,
//Completely drags target to the attacker, even across large distances.
DrawIn = HitEffect5 | HitEffect3,
//An additional visual effect that plays on the target based on according buff.
UnknownShieldEffect = HitEffect5 | HitEffect4,
Stoneskin = HitEffect5 | HitEffect4 | HitEffect1,
//Unknown = 1 << 14, -- Not sure what this flag does; might be another HitEffect.
//A special effect when performing appropriate skill combos in succession.
//Ex: Thunder (SkillCombo1 Effect) -> Thundara (SkillCombo2 Effect) -> Thundaga (SkillCombo3 Effect)
//Special Note: SkillCombo4 was never actually used in 1.0 since combos only chained up to 3 times maximum.
SkillCombo1 = 1 << 15,
SkillCombo2 = 1 << 16,
SkillCombo3 = SkillCombo1 | SkillCombo2,
SkillCombo4 = 1 << 17
//Flags beyond here are unknown/untested.
}
class BattleActionX01Packet class BattleActionX01Packet
{ {
public const ushort OPCODE = 0x0139; public const ushort OPCODE = 0x0139;

View file

@ -0,0 +1,36 @@
require ("global")
require ("utils")
--[[
AttackWeaponSkill Script
Finds the correct weaponskill subscript to fire when a weaponskill actor is activated.
--]]
local attackMagicHandlers = {
}
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
print(command.actorId)
--Are they in active mode?
if (player:GetState() != 2) then
player:SendGameMessage(GetWorldMaster(), 32503, 0x20);
player:endEvent();
return;
end
--Does the target exist
target = player:getZone():FindActorInArea(targetActor);
if (target == nil) then
player:SendGameMessage(GetWorldMaster(), 30203, 0x20);
player:endEvent();
return;
end
player.Ability(command.actorId, targetActor);
player:endEvent();
end