This commit is contained in:
yogurt 2017-12-08 02:08:13 -06:00
commit 205d3619d6
49 changed files with 118 additions and 491 deletions

View File

@ -61,7 +61,7 @@ namespace FFXIVClassic_Map_Server.Actors
public List<LuaParam> classParams; public List<LuaParam> classParams;
public List<Vector3> positionUpdates; public List<Vector3> positionUpdates;
public DateTime lastMoveUpdate; protected DateTime lastUpdateScript;
protected DateTime lastUpdate; protected DateTime lastUpdate;
public Actor target; public Actor target;

View File

@ -667,11 +667,14 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
lock (mActorList) lock (mActorList)
{ {
foreach (Actor a in mActorList.Values) foreach (Actor a in mActorList.Values.ToList())
a.Update(tick); a.Update(tick);
var deltaTime = (tick - Program.LastTick).TotalMilliseconds; if ((tick - lastUpdateScript).TotalMilliseconds > 1500)
//LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, this, deltaTime); {
//LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick);
lastUpdateScript = tick;
}
} }
} }

View File

@ -136,7 +136,6 @@ namespace FFXIVClassic_Map_Server.Actors
this.statusEffects = new StatusEffectContainer(this); this.statusEffects = new StatusEffectContainer(this);
// todo: move this somewhere more appropriate // todo: move this somewhere more appropriate
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));
@ -279,22 +278,8 @@ namespace FFXIVClassic_Map_Server.Actors
public void FollowTarget(Actor target, float stepSize = 1.2f, int maxPath = 25, float radius = 0.0f) public void FollowTarget(Actor target, float stepSize = 1.2f, int maxPath = 25, float radius = 0.0f)
{ {
var player = target as Player; if (target != null)
PathTo(target.positionX, target.positionY, target.positionZ, stepSize, maxPath, radius);
if (player != null)
{
if (this.target != player)
{
this.target = target;
}
// todo: move this to own function thing
this.oldMoveState = this.moveState;
this.moveState = 2;
updateFlags |= ActorUpdateFlags.Position | ActorUpdateFlags.Speed;
//this.moveSpeeds = player.moveSpeeds;
PathTo(player.positionX, player.positionY, player.positionZ, stepSize, maxPath, radius);
}
} }
public Int64 GetMod(uint modifier) public Int64 GetMod(uint modifier)
@ -690,12 +675,7 @@ namespace FFXIVClassic_Map_Server.Actors
} }
// todo: call onAttack/onDamageTaken // todo: call onAttack/onDamageTaken
BattleUtils.DamageTarget(this, target, action); BattleUtils.DamageTarget(this, target, action, DamageTakenType.Attack);
target.OnDamageTaken(this, action, DamageTakenType.Ability);
if (target is BattleNpc)
((BattleNpc)target).lastAttacker = this;
AddTP(115); AddTP(115);
target.AddTP(100); target.AddTP(100);
} }
@ -708,20 +688,8 @@ namespace FFXIVClassic_Map_Server.Actors
this.DelMP(spellCost); // mpCost can be set in script e.g. if caster has something for free spells this.DelMP(spellCost); // mpCost can be set in script e.g. if caster has something for free spells
foreach (BattleAction action in actions) foreach (BattleAction action in actions)
{
if (zone.FindActorInArea<Character>(action.targetId) is Character chara) if (zone.FindActorInArea<Character>(action.targetId) is Character chara)
{ BattleUtils.DamageTarget(this, chara, action, DamageTakenType.Magic);
if (chara != null && chara is BattleNpc)
{
((BattleNpc)chara).hateContainer.UpdateHate(this, action.amount);
((BattleNpc)chara).lastAttacker = this;
}
BattleUtils.DamageTarget(this, chara, action);
}
}
if (target is BattleNpc)
lua.LuaEngine.GetInstance().OnSignal("spellUsed"); lua.LuaEngine.GetInstance().OnSignal("spellUsed");
} }
@ -733,22 +701,8 @@ namespace FFXIVClassic_Map_Server.Actors
this.DelTP(skill.tpCost); this.DelTP(skill.tpCost);
foreach (BattleAction action in actions) foreach (BattleAction action in actions)
{
if (zone.FindActorInArea<Character>(action.targetId) is Character chara) if (zone.FindActorInArea<Character>(action.targetId) is Character chara)
{ BattleUtils.DamageTarget(this, chara, action, DamageTakenType.Weaponskill);
if (chara != null && chara is BattleNpc)
{
((BattleNpc)chara).hateContainer.UpdateHate(this, action.amount);
((BattleNpc)chara).lastAttacker = this;
}
BattleUtils.DamageTarget(this, chara, action);
}
}
if (target is BattleNpc)
((BattleNpc)target).lastAttacker = this;
lua.LuaEngine.GetInstance().OnSignal("weaponskillUsed"); lua.LuaEngine.GetInstance().OnSignal("weaponskillUsed");
} }
@ -821,7 +775,7 @@ namespace FFXIVClassic_Map_Server.Actors
public bool IsMonster() public bool IsMonster()
{ {
return this is BattleNpc && !IsAlly(); return this is BattleNpc;
} }
public bool IsPet() public bool IsPet()

View File

@ -39,15 +39,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
{ {
if (!HasHateForTarget(target)) if (!HasHateForTarget(target))
hateList.Add(target, new HateEntry(target, 1, 0, true)); hateList.Add(target, new HateEntry(target, 1, 0, true));
else
Program.Log.Error($"{target.actorName} is already on [{owner.actorId}]{owner.actorName}'s hate list!");
} }
public void UpdateHate(Character target, int damage) public void UpdateHate(Character target, int damage)
{ {
if (!HasHateForTarget(target))
AddBaseHate(target); AddBaseHate(target);
//hateList[target].volatileEnmity += (uint)damage; //hateList[target].volatileEnmity += (uint)damage;
hateList[target].cumulativeEnmity += (uint)damage; hateList[target].cumulativeEnmity += (uint)damage;
} }
@ -55,14 +51,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
public void ClearHate(Character target = null) public void ClearHate(Character target = null)
{ {
if (target != null) if (target != null)
{
hateList.Remove(target); hateList.Remove(target);
}
else else
{
hateList.Clear(); hateList.Clear();
} }
}
private void UpdateHate(HateEntry entry) private void UpdateHate(HateEntry entry)
{ {

View File

@ -48,7 +48,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
if(owner.aiContainer.IsEngaged()) if(owner.aiContainer.IsEngaged())
{ {
DoCombatTick(tick); //DoCombatTick(tick);
} }
//Only move if owner isn't dead and is either too far away from their spawn point or is meant to roam //Only move if owner isn't dead and is either too far away from their spawn point or is meant to roam
@ -143,8 +143,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
owner.aiContainer.pathFind.PreparePath(owner.spawnX, owner.spawnY, owner.spawnZ, 1.5f, 10); owner.aiContainer.pathFind.PreparePath(owner.spawnX, owner.spawnY, owner.spawnZ, 1.5f, 10);
neutralTime = lastActionTime; neutralTime = lastActionTime;
owner.hateContainer.ClearHate(); owner.hateContainer.ClearHate();
owner.ResetMoveSpeeds();
owner.moveState = 1;
lua.LuaEngine.CallLuaBattleFunction(owner, "onDisengage", owner, target, Utils.UnixTimeStampUTC(lastUpdate)); lua.LuaEngine.CallLuaBattleFunction(owner, "onDisengage", owner, target, Utils.UnixTimeStampUTC(lastUpdate));
} }
@ -215,6 +213,12 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
Move(); Move();
if ((tick - lastCombatTickScript).TotalSeconds > 2)
{
lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick), contentGroupCharas);
lastCombatTickScript = tick;
}
} }
protected virtual void Move() protected virtual void Move()

View File

@ -11,6 +11,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{ {
protected Character owner; protected Character owner;
protected DateTime lastCombatTickScript;
protected DateTime lastUpdate; protected DateTime lastUpdate;
public bool canUpdate = true; public bool canUpdate = true;
protected bool autoAttackEnabled = true; protected bool autoAttackEnabled = true;

View File

@ -38,7 +38,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
if (target == null || target.IsDead()) if (target == null || target.IsDead())
{ {
if (owner is BattleNpc) if (owner.IsMonster() || owner.IsAlly())
target = ((BattleNpc)owner).hateContainer.GetMostHatedTarget(); target = ((BattleNpc)owner).hateContainer.GetMostHatedTarget();
} }
else else
@ -129,6 +129,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
private bool CanAttack() private bool CanAttack()
{ {
return false;
if (!owner.isAutoAttackEnabled) if (!owner.isAutoAttackEnabled)
{ {
return false; return false;
@ -141,7 +142,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
// todo: shouldnt need to check if owner is dead since all states would be cleared // todo: shouldnt need to check if owner is dead since all states would be cleared
if (owner.IsDead() || target.IsDead()) if (owner.IsDead() || target.IsDead())
{ {
if (owner is BattleNpc) if (owner.IsMonster() || owner.IsAlly())
((BattleNpc)owner).hateContainer.ClearHate(target); ((BattleNpc)owner).hateContainer.ClearHate(target);
owner.aiContainer.ChangeTarget(null); owner.aiContainer.ChangeTarget(null);

View File

@ -76,20 +76,23 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils
return damage; return damage;
} }
public static void DamageTarget(Character attacker, Character defender, BattleAction action) public static void DamageTarget(Character attacker, Character defender, BattleAction action, DamageTakenType type)
{ {
if (defender != null) if (defender != null)
{ {
// todo: other stuff too // todo: other stuff too
if (defender is BattleNpc) if (defender is BattleNpc)
{ {
if (!((BattleNpc)defender).hateContainer.HasHateForTarget(attacker)) var bnpc = defender as BattleNpc;
if (!bnpc.hateContainer.HasHateForTarget(attacker))
{ {
((BattleNpc)defender).hateContainer.AddBaseHate(attacker); bnpc.hateContainer.AddBaseHate(attacker);
} }
((BattleNpc)defender).hateContainer.UpdateHate(attacker, action.amount); bnpc.hateContainer.UpdateHate(attacker, action.amount);
bnpc.lastAttacker = attacker;
} }
defender.DelHP((short)action.amount); defender.DelHP((short)action.amount);
defender.OnDamageTaken(attacker, action, type);
} }
} }

View File

@ -90,12 +90,7 @@ namespace FFXIVClassic_Map_Server.Actors
spawnY = posY; spawnY = posY;
spawnZ = posZ; spawnZ = posZ;
// todo: read these from db also
detectionType = DetectionType.Sight;
this.moveState = 2;
ResetMoveSpeeds();
despawnTime = 10; despawnTime = 10;
respawnTime = 30;
CalculateBaseStats(); CalculateBaseStats();
} }
@ -245,19 +240,7 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
if (respawnTime > 0) if (respawnTime > 0)
{ {
base.Spawn(tick); ForceRespawn();
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();
OnSpawn();
updateFlags |= ActorUpdateFlags.AllNpc;
} }
} }
@ -266,7 +249,6 @@ namespace FFXIVClassic_Map_Server.Actors
base.Spawn(Program.Tick); base.Spawn(Program.Tick);
this.isMovingToSpawn = false; this.isMovingToSpawn = false;
this.ResetMoveSpeeds();
this.hateContainer.ClearHate(); this.hateContainer.ClearHate();
zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01)); zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01));
zone.BroadcastPacketsAroundActor(this, GetInitPackets()); zone.BroadcastPacketsAroundActor(this, GetInitPackets());
@ -302,7 +284,7 @@ namespace FFXIVClassic_Map_Server.Actors
// onDeath(monster, player, killer) // onDeath(monster, player, killer)
lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, partyMember, lastAttacker); lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, partyMember, lastAttacker);
if(partyMember is Player) if (partyMember is Player)
((Player)partyMember).AddExp(1500, (byte)partyMember.GetClass(), 5); ((Player)partyMember).AddExp(1500, (byte)partyMember.GetClass(), 5);
} }
} }
@ -315,7 +297,7 @@ namespace FFXIVClassic_Map_Server.Actors
} }
positionUpdates?.Clear(); positionUpdates?.Clear();
aiContainer.InternalDie(tick, despawnTime); aiContainer.InternalDie(tick, despawnTime);
this.ResetMoveSpeeds(); //this.ResetMoveSpeeds();
// todo: reset cooldowns // todo: reset cooldowns
lua.LuaEngine.GetInstance().OnSignal("mobkill"); lua.LuaEngine.GetInstance().OnSignal("mobkill");
@ -379,9 +361,6 @@ namespace FFXIVClassic_Map_Server.Actors
if (GetMobMod((uint)MobModifier.AttackScript) != 0) if (GetMobMod((uint)MobModifier.AttackScript) != 0)
lua.LuaEngine.CallLuaBattleFunction(this, "onAttack", this, state.GetTarget(), action.amount); lua.LuaEngine.CallLuaBattleFunction(this, "onAttack", this, state.GetTarget(), action.amount);
if (target is BattleNpc)
((BattleNpc)target).hateContainer.UpdateHate(this, action.amount);
} }
public override void OnCast(State state, BattleAction[] actions, ref BattleAction[] errors) public override void OnCast(State state, BattleAction[] actions, ref BattleAction[] errors)
@ -391,19 +370,6 @@ namespace FFXIVClassic_Map_Server.Actors
if (GetMobMod((uint)MobModifier.SpellScript) != 0) if (GetMobMod((uint)MobModifier.SpellScript) != 0)
foreach (var action in actions) foreach (var action in actions)
lua.LuaEngine.CallLuaBattleFunction(this, "onCast", this, zone.FindActorInArea<Character>(action.targetId), ((MagicState)state).GetSpell(), action); lua.LuaEngine.CallLuaBattleFunction(this, "onCast", this, zone.FindActorInArea<Character>(action.targetId), ((MagicState)state).GetSpell(), action);
foreach (BattleAction action in actions)
{
if (zone.FindActorInArea<Character>(action.targetId) is Character chara)
{
if (chara is BattleNpc)
{
((BattleNpc)chara).hateContainer.UpdateHate(this, action.amount);
((BattleNpc)chara).lastAttacker = this;
}
BattleUtils.DamageTarget(this, chara, action);
}
}
} }
public override void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors) public override void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors)

View File

@ -2188,6 +2188,7 @@ namespace FFXIVClassic_Map_Server.Actors
var spell = ((MagicState)state).GetSpell(); var spell = ((MagicState)state).GetSpell();
// todo: should just make a thing that updates the one slot cause this is dumb as hell // todo: should just make a thing that updates the one slot cause this is dumb as hell
UpdateHotbarTimer(spell.id, spell.recastTimeSeconds); UpdateHotbarTimer(spell.id, spell.recastTimeSeconds);
LuaEngine.GetInstance().OnSignal("spellUse");
} }
public override void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors) public override void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors)
@ -2199,6 +2200,14 @@ namespace FFXIVClassic_Map_Server.Actors
UpdateHotbarTimer(skill.id, skill.recastTimeSeconds); UpdateHotbarTimer(skill.id, skill.recastTimeSeconds);
// todo: this really shouldnt be called on each ws? // todo: this really shouldnt be called on each ws?
lua.LuaEngine.CallLuaBattleFunction(this, "onWeaponSkill", this, state.GetTarget(), skill); lua.LuaEngine.CallLuaBattleFunction(this, "onWeaponSkill", this, state.GetTarget(), skill);
LuaEngine.GetInstance().OnSignal("weaponskillUse");
}
public override void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors)
{
base.OnAbility(state, actions, ref errors);
LuaEngine.GetInstance().OnSignal("abilityUse");
} }
//Handles exp being added, does not handle figuring out exp bonus from buffs or skill/link chains or any of that //Handles exp being added, does not handle figuring out exp bonus from buffs or skill/link chains or any of that

View File

@ -259,7 +259,7 @@ namespace FFXIVClassic_Map_Server.lua
return -1; return -1;
} }
private static string GetScriptPath(Actor target) public static string GetScriptPath(Actor target)
{ {
if (target is Player) if (target is Player)
{ {

View File

@ -41,7 +41,7 @@ function allyGlobal.HelpPlayers(ally, contentGroupCharas, pickRandomTarget)
if chara then if chara then
-- probably a player, or another ally -- probably a player, or another ally
-- todo: queue support actions, heal, try pull hate off player etc -- todo: queue support actions, heal, try pull hate off player etc
if chara.IsPlayer() then if chara:IsPlayer() then
-- do stuff -- do stuff
if not ally.IsEngaged() then if not ally.IsEngaged() then
if chara.IsEngaged() then if chara.IsEngaged() then

View File

@ -1,13 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
local shortCommandId = bit32.bxor(command, 2700083200);
local ability = worldManager:GetAbility(shortCommandId);
--player:PlayAnimation(ability.modelAnimation);
player:endEvent();
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetAbility(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation, 0x756D, command.actorId, ability.animationType);
end
player:endEvent();
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetAbility(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation, 0x756D, command.actorId, ability.animationType);
end
player:endEvent();
end

View File

@ -1,6 +0,0 @@
function onEventStarted(player, caller, commandRequest, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
player:SetCurrentJob(17);
player:EndEvent();
end

View File

@ -1,3 +0,0 @@
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetAbility(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation, 0x756D, command.actorId, ability.animationType);
end
player:endEvent();
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetBattleCommand(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation);
end
player:endEvent();
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetAbility(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation, 0x756D, command.actorId, ability.animationType);
end
player:endEvent();
end

View File

@ -1,7 +0,0 @@
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
player.Cast(command.actorId, targetActor);
player:endEvent();
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetAbility(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation);
end
player:endEvent();
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetAbility(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation);
end
player:endEvent();
end

View File

@ -1,14 +0,0 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
local worldManager = GetWorldManager();
--local shortCommandId = command.actorId;--bit32:bxor(command.actorId, 2700083200);
local ability = worldManager:GetAbility(command.actorId);
if ability then
player.SendBattleActionX01Packet(ability.modelAnimation, ability.effectAnimation, 0x756D, command.actorId, ability.animationType);
end
player:endEvent();
end

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -20,8 +20,5 @@ function onMagicFinish(caster, target, spell, action)
-- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -17,8 +17,5 @@ function onMagicFinish(caster, target, spell, action)
-- magic.HandleAttackMagic(caster, target, spell, action) -- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -1,24 +0,0 @@
require("magic");
function onMagicPrepare(caster, target, spell)
return 0;
end;
function onMagicStart(caster, target, spell)
return 0;
end;
function onMagicFinish(caster, target, spell, action)
local damage = math.random(10, 100);
action.worldMasterTextId = 0x765D;
-- todo: populate a global script with statuses and modifiers
-- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage;
end;

View File

@ -20,8 +20,5 @@ function onMagicFinish(caster, target, spell, action)
-- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -20,8 +20,5 @@ function onMagicFinish(caster, target, spell, action)
-- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -20,8 +20,5 @@ function onMagicFinish(caster, target, spell, action)
-- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -20,8 +20,5 @@ function onMagicFinish(caster, target, spell, action)
-- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -20,8 +20,5 @@ function onMagicFinish(caster, target, spell, action)
-- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -20,8 +20,5 @@ function onMagicFinish(caster, target, spell, action)
-- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -17,8 +17,5 @@ function onMagicFinish(caster, target, spell, action)
-- magic.HandleAttackMagic(caster, target, spell, action) -- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -17,8 +17,5 @@ function onMagicFinish(caster, target, spell, action)
-- magic.HandleAttackMagic(caster, target, spell, action) -- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -17,8 +17,5 @@ function onMagicFinish(caster, target, spell, action)
-- magic.HandleAttackMagic(caster, target, spell, action) -- magic.HandleAttackMagic(caster, target, spell, action)
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
if target.hateContainer then
target.hateContainer.UpdateHate(caster, damage);
end;
return damage; return damage;
end; end;

View File

@ -1,4 +1,5 @@
require ("global") require ("global")
require ("ally")
require ("modifiers") require ("modifiers")
function onCreate(starterPlayer, contentArea, director) function onCreate(starterPlayer, contentArea, director)
@ -33,6 +34,42 @@ function onCreate(starterPlayer, contentArea, director)
end end
function onUpdate(area, tick)
local players = area:GetPlayers()
local mobs = area:GetMonsters()
local allies = area:GetAllies()
local resumeChecks = true
for player in players do
if player then
local exitLoop = false
for ally in allies do
if ally then
if not ally:IsEngaged() then
if player:IsEngaged() then
ally.neutral = false
ally.isAutoAttackEnabled = true
ally:SetMod(modifiersGlobal.Speed, 8)
allyGlobal.EngageTarget(ally, player.target)
exitLoop = true
break
-- todo: support scripted paths
elseif ally:GetSpeed() > 0 then
end
end
end
end
if exitLoop then
resumeChecks = false
break
end
end
end
if not resumeChecks then
return
end
end
function onDestroy() function onDestroy()
end end

View File

@ -0,0 +1,22 @@
require ("modifiers")
function onSpawn(mob)
mob:SetMod(modifiersGlobal.Speed, 0)
end
function onDamageTaken(mob, attacker, damage)
if not attacker:IsPlayer() and mob:GetHP() - damage < 0 then
mob:addHP(damage)
end
end
function onCombatTick(mob, target, tick, contentGroupCharas)
if mob:GetSpeed() == 0 then
mob:SetMod(modifiersGlobal.Speed, 8)
end
end
function onDisengage(mob)
mob:SetMod(modifiersGlobal.Speed, 0)
mob:Despawn()
end

View File

@ -1,4 +1,5 @@
require ("global") require ("global")
require ("modifiers")
require ("ally") require ("ally")
function onSpawn(ally) function onSpawn(ally)

View File

@ -1,12 +1,12 @@
require ("global") require ("global")
require ("ally") require ("ally")
function onSpawn(ally) function onSpawn(ally)
ally:SetMaxHP(69420) ally:SetMaxHP(69420)
ally:SetHP(ally:GetMaxHP()) ally:SetHP(ally:GetMaxHP())
ally.isAutoAttackEnabled = false ally.isAutoAttackEnabled = false;
ally.neutral = false ally.neutral = false
ally:SetMod(modifiersGlobal.Speed, 0)
end end
function onCombatTick(ally, target, tick, contentGroupCharas) function onCombatTick(ally, target, tick, contentGroupCharas)