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());
}
public static uint UnixTimeStampUTC()
public static uint UnixTimeStampUTC(DateTime? time = null)
{
uint unixTimeStamp;
var currentTime = DateTime.Now;
var currentTime = time ?? DateTime.Now;
var zuluTime = currentTime.ToUniversalTime();
var unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (uint)zuluTime.Subtract(unixEpoch).TotalSeconds;
@ -95,10 +95,10 @@ namespace FFXIVClassic.Common
return unixTimeStamp;
}
public static ulong MilisUnixTimeStampUTC()
public static ulong MilisUnixTimeStampUTC(DateTime? time = null)
{
ulong unixTimeStamp;
var currentTime = DateTime.Now;
var currentTime = time ?? DateTime.Now;
var zuluTime = currentTime.ToUniversalTime();
var unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (ulong)zuluTime.Subtract(unixEpoch).TotalMilliseconds;

View file

@ -109,7 +109,7 @@ namespace FFXIVClassic_Map_Server.Actors
ResetMoveSpeeds();
// todo: base this on equip and shit
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()
@ -322,6 +322,11 @@ namespace FFXIVClassic_Map_Server.Actors
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)
{
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()
{
return states.Count == 0 || states.Peek().CanInterrupt();
return GetCurrentState() == null || states.Peek().CanInterrupt();
}
public void ChangeTarget(Character target)
@ -217,6 +217,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
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)
{
if (controller != null)
@ -293,6 +301,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
ClearStates();
}
public void InternalAbility(Character target, uint abilityId)
{
}
public void InternalCast(Character target, uint 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)
{
owner.aiContainer.InternalAbility(target, abilityId);
}
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) :
base(owner, target)
{
this.canInterrupt = true;
this.startTime = DateTime.Now;
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
owner.aiContainer.ChangeTarget(target);
this.startTime = DateTime.Now;
attackTime = startTime;
owner.aiContainer.pathFind?.Clear();
// 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.battle;
using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.utils;
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
startPos = owner.GetPosAsVector3();
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
//player.QueuePacket(BattleActionX01Packet.BuildPacket(player.actorId, owner.actorId, target != null ? target.actorId : 0xC0000000, spell.battleAnimation, spell.effectAnimation, 0, spell.id, 0, (byte)spell.castTimeSeconds));
// todo: modify spellSpeed based on modifiers and stuff
// ((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);
}
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 System;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{
class SetActorStatePacket

View file

@ -10,6 +10,17 @@ namespace FFXIVClassic_Map_Server.packets.send.actor
public const ushort OPCODE = 0x144;
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)
{
byte[] data = new byte[PACKET_SIZE - 0x20];

View file

@ -10,6 +10,89 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle
Disengage = 12002,
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
{
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