mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-24 05:37:46 +00:00
Merge branch 'ai-open' of https://bitbucket.org/skeletonhorn/ffxiv-classic-server-ai-fork into ai
# Conflicts: # data/scripts/modifiers.lua
This commit is contained in:
commit
cd60c571ac
54 changed files with 935 additions and 268 deletions
|
@ -10,7 +10,7 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FFXIVClassic.Common</RootNamespace>
|
||||
<AssemblyName>FFXIVClassic.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
|
@ -38,6 +38,26 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DotNetZip">
|
||||
<HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<remove invariant="MySql.Data.MySqlClient" />
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
|
||||
<remove invariant="MySql.Data.MySqlClient"/>
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
|
||||
</DbProviderFactories>
|
||||
</system.data>
|
||||
</configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/></startup></configuration>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FFXIVClassic_Lobby_Server</RootNamespace>
|
||||
<AssemblyName>FFXIVClassic_Lobby_Server</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
|
@ -28,6 +28,7 @@
|
|||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<NuGetPackageImportStamp>cc1ba6f5</NuGetPackageImportStamp>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
@ -50,6 +51,28 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Cyotek.Collections.Generic.CircularBuffer">
|
||||
<HintPath>..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<remove invariant="MySql.Data.MySqlClient" />
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
|
||||
<remove invariant="MySql.Data.MySqlClient"/>
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
|
||||
</DbProviderFactories>
|
||||
</system.data>
|
||||
</configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/></startup></configuration>
|
||||
|
|
|
@ -40,6 +40,28 @@
|
|||
<PropertyGroup>
|
||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Cyotek.Collections.Generic.CircularBuffer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
|
||||
|
|
|
@ -511,7 +511,6 @@ namespace FFXIVClassic_Map_Server
|
|||
battleNpc.SetMod((uint)Modifier.Defense, reader.GetUInt32("def"));
|
||||
battleNpc.SetMod((uint)Modifier.Evasion, reader.GetUInt32("eva"));
|
||||
|
||||
|
||||
battleNpc.dropListId = reader.GetUInt32("dropListId");
|
||||
battleNpc.spellListId = reader.GetUInt32("spellListId");
|
||||
battleNpc.skillListId = reader.GetUInt32("skillListId");
|
||||
|
@ -644,12 +643,48 @@ namespace FFXIVClassic_Map_Server
|
|||
battleNpc.SetMod((uint)Modifier.Defense, reader.GetUInt32("def"));
|
||||
battleNpc.SetMod((uint)Modifier.Evasion, reader.GetUInt32("eva"));
|
||||
|
||||
if (battleNpc.poolMods != null)
|
||||
{
|
||||
foreach (var a in battleNpc.poolMods.mobModList)
|
||||
{
|
||||
battleNpc.SetMobMod(a.Value.id, (long)(a.Value.value));
|
||||
}
|
||||
foreach (var a in battleNpc.poolMods.modList)
|
||||
{
|
||||
battleNpc.SetMod(a.Key, (long)(a.Value.value));
|
||||
}
|
||||
}
|
||||
|
||||
if (battleNpc.genusMods != null)
|
||||
{
|
||||
foreach (var a in battleNpc.genusMods.mobModList)
|
||||
{
|
||||
battleNpc.SetMobMod(a.Key, (long)(a.Value.value));
|
||||
}
|
||||
foreach (var a in battleNpc.genusMods.modList)
|
||||
{
|
||||
battleNpc.SetMod(a.Key, (long)(a.Value.value));
|
||||
}
|
||||
}
|
||||
|
||||
if(battleNpc.spawnMods != null)
|
||||
{
|
||||
foreach (var a in battleNpc.spawnMods.mobModList)
|
||||
{
|
||||
battleNpc.SetMobMod(a.Key, (long)(a.Value.value));
|
||||
}
|
||||
|
||||
foreach (var a in battleNpc.spawnMods.modList)
|
||||
{
|
||||
battleNpc.SetMod(a.Key, (long)(a.Value.value));
|
||||
}
|
||||
}
|
||||
|
||||
battleNpc.dropListId = reader.GetUInt32("dropListId");
|
||||
battleNpc.spellListId = reader.GetUInt32("spellListId");
|
||||
battleNpc.skillListId = reader.GetUInt32("skillListId");
|
||||
battleNpc.SetMaxHP(1000);
|
||||
battleNpc.SetHP(1000);
|
||||
battleNpc.SetBattleNpcId(reader.GetUInt32("bnpcId"));
|
||||
battleNpc.SetRespawnTime(reader.GetUInt32("respawnTime"));
|
||||
battleNpc.CalculateBaseStats();
|
||||
battleNpc.RecalculateStats();
|
||||
//battleNpc.SetMod((uint)Modifier.ResistFire, )
|
||||
|
@ -679,7 +714,7 @@ namespace FFXIVClassic_Map_Server
|
|||
try
|
||||
{
|
||||
conn.Open();
|
||||
var query = $"SELECT {primaryKey}, modId, modVal, isMobMod FROM {tableName} GROUP BY {primaryKey};";
|
||||
var query = $"SELECT {primaryKey}, modId, modVal, isMobMod FROM {tableName}";
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||
|
||||
|
@ -688,9 +723,9 @@ namespace FFXIVClassic_Map_Server
|
|||
while (reader.Read())
|
||||
{
|
||||
var id = reader.GetUInt32(primaryKey);
|
||||
ModifierList modList = new ModifierList(id);
|
||||
ModifierList modList = list.TryGetValue(id, out modList) ? modList : new ModifierList(id);
|
||||
modList.SetModifier(reader.GetUInt16("modId"), reader.GetInt64("modVal"), reader.GetBoolean("isMobMod"));
|
||||
list.Add(id, modList);
|
||||
list[id] = modList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -438,9 +438,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
updateFlags = ActorUpdateFlags.None;
|
||||
zone.BroadcastPacketsAroundActor(this, packets);
|
||||
|
||||
SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp");
|
||||
hpInfo.AddTarget();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -500,8 +500,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null);
|
||||
|
||||
npc.LoadEventConditions(actorClass.eventConditions);
|
||||
npc.SetMaxHP(300);
|
||||
npc.SetHP(300);
|
||||
//npc.SetMaxHP(30000);
|
||||
//npc.SetHP(30000);
|
||||
|
||||
AddActorToZone(npc);
|
||||
|
||||
|
@ -672,7 +672,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
if ((tick - lastUpdateScript).TotalMilliseconds > 1500)
|
||||
{
|
||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick);
|
||||
//LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick);
|
||||
lastUpdateScript = tick;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,6 +132,18 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
return actor;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (List<PrivateAreaContent> paList in contentAreas.Values)
|
||||
{
|
||||
foreach (PrivateArea pa in paList)
|
||||
{
|
||||
Actor actor = pa.FindActorInArea(id);
|
||||
if (actor != null)
|
||||
return actor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -229,10 +229,10 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public void DoBattleAction(ushort commandId, uint animationId, BattleAction[] actions)
|
||||
{
|
||||
int currentIndex = 0;
|
||||
|
||||
//AoE abilities only ever hit 16 people, so we probably won't need this loop anymore
|
||||
while (true)
|
||||
{
|
||||
if (actions.Length - currentIndex >= 18)
|
||||
if (actions.Length - currentIndex >= 10)
|
||||
zone.BroadcastPacketAroundActor(this, BattleActionX18Packet.BuildPacket(actorId, animationId, commandId, actions, ref currentIndex));
|
||||
else if (actions.Length - currentIndex > 1)
|
||||
zone.BroadcastPacketAroundActor(this, BattleActionX10Packet.BuildPacket(actorId, animationId, commandId, actions, ref currentIndex));
|
||||
|
@ -243,7 +243,9 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
else
|
||||
break;
|
||||
animationId = 0; //If more than one packet is sent out, only send the animation once to avoid double playing.
|
||||
|
||||
//I think aoe effects play on all hit enemies. Firaga does at least
|
||||
//animationId = 0; //If more than one packet is sent out, only send the animation once to avoid double playing.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,7 +300,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
public virtual void OnPath(Vector3 point)
|
||||
{
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onPath", this, point);
|
||||
//lua.LuaEngine.CallLuaBattleFunction(this, "onPath", this, point);
|
||||
|
||||
updateFlags |= ActorUpdateFlags.Position;
|
||||
this.isAtSpawn = false;
|
||||
|
@ -332,7 +334,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0)
|
||||
{
|
||||
var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this);
|
||||
var propPacketUtil = new ActorPropertyPacketUtil("charaWork/stateAtQuicklyForAll", this);
|
||||
|
||||
propPacketUtil.AddProperty("charaWork.parameterSave.mp");
|
||||
propPacketUtil.AddProperty("charaWork.parameterSave.mpMax");
|
||||
|
@ -455,6 +457,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
{
|
||||
// todo: actual despawn timer
|
||||
aiContainer.InternalDie(tick, 10);
|
||||
ChangeSpeed(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public virtual void Despawn(DateTime tick)
|
||||
|
@ -528,6 +531,20 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
}
|
||||
|
||||
public void SetMP(uint mp)
|
||||
{
|
||||
charaWork.parameterSave.mpMax = (short)mp;
|
||||
if (mp > charaWork.parameterSave.hpMax[0])
|
||||
SetMaxMP(mp);
|
||||
|
||||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
}
|
||||
|
||||
public void SetMaxMP(uint mp)
|
||||
{
|
||||
charaWork.parameterSave.mp = (short)mp;
|
||||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
|
@ -547,7 +564,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
}
|
||||
|
||||
public short GetJob()
|
||||
public short GetClass()
|
||||
{
|
||||
return charaWork.parameterSave.state_mainSkill[0];
|
||||
}
|
||||
|
@ -599,8 +616,30 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
public void RecalculateStats()
|
||||
{
|
||||
if (GetMod((uint)Modifier.Hp) != 0)
|
||||
uint hpMod = (uint) GetMod((uint)Modifier.Hp);
|
||||
if (hpMod != 0)
|
||||
{
|
||||
SetMaxHP(hpMod);
|
||||
uint hpp = (uint) GetMod((uint) Modifier.HpPercent);
|
||||
uint hp = hpMod;
|
||||
if(hpp != 0)
|
||||
{
|
||||
hp = (uint) Math.Ceiling(((float)hpp / 100.0f) * hpMod);
|
||||
}
|
||||
SetHP(hp);
|
||||
}
|
||||
|
||||
uint mpMod = (uint)GetMod((uint)Modifier.Mp);
|
||||
if (mpMod != 0)
|
||||
{
|
||||
SetMaxMP(mpMod);
|
||||
uint mpp = (uint)GetMod((uint)Modifier.MpPercent);
|
||||
uint mp = mpMod;
|
||||
if (mpp != 0)
|
||||
{
|
||||
mp = (uint)Math.Ceiling(((float)mpp / 100.0f) * mpMod);
|
||||
}
|
||||
SetMP(mp);
|
||||
}
|
||||
// todo: recalculate stats and crap
|
||||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
|
@ -635,14 +674,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
//var packet = BattleActionX01Packet.BuildPacket(owner.actorId, owner.actorId, target.actorId, (uint)0x19001000, (uint)0x8000604, (ushort)0x765D, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, (byte)0x1);
|
||||
}
|
||||
|
||||
target.OnDamageTaken(this, action, DamageTakenType.Ability);
|
||||
// todo: call onAttack/onDamageTaken
|
||||
target.DelHP(action.amount);
|
||||
if (target is BattleNpc)
|
||||
{
|
||||
((BattleNpc)target).lastAttacker = this;
|
||||
((BattleNpc)target).hateContainer.UpdateHate(this, action.amount);
|
||||
}
|
||||
BattleUtils.DamageTarget(this, target, action, DamageTakenType.Attack);
|
||||
AddTP(115);
|
||||
target.AddTP(100);
|
||||
}
|
||||
|
@ -651,13 +684,14 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
{
|
||||
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
|
||||
var spellCost = spell.CalculateCost((uint)this.GetLevel());
|
||||
this.DelMP(spellCost); // mpCost can be set in script e.g. if caster has something for free spells
|
||||
|
||||
foreach (var action in actions)
|
||||
zone.FindActorInArea<Character>(action.targetId).OnDamageTaken(this, action, DamageTakenType.Magic);
|
||||
foreach (BattleAction action in actions)
|
||||
if (zone.FindActorInArea<Character>(action.targetId) is Character chara)
|
||||
BattleUtils.DamageTarget(this, chara, action, DamageTakenType.Magic);
|
||||
|
||||
if (target is BattleNpc)
|
||||
((BattleNpc)target).lastAttacker = this;
|
||||
lua.LuaEngine.GetInstance().OnSignal("spellUsed");
|
||||
}
|
||||
|
||||
public virtual void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors)
|
||||
|
@ -666,11 +700,11 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
// damage is handled in script
|
||||
this.DelTP(skill.tpCost);
|
||||
|
||||
foreach (var action in actions)
|
||||
zone.FindActorInArea<BattleNpc>(action.targetId)?.OnDamageTaken(this, action, DamageTakenType.Weaponskill);
|
||||
foreach (BattleAction action in actions)
|
||||
if (zone.FindActorInArea<Character>(action.targetId) is Character chara)
|
||||
BattleUtils.DamageTarget(this, chara, action, DamageTakenType.Weaponskill);
|
||||
|
||||
if (target is BattleNpc)
|
||||
((BattleNpc)target).lastAttacker = this;
|
||||
lua.LuaEngine.GetInstance().OnSignal("weaponskillUsed");
|
||||
}
|
||||
|
||||
public virtual void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors)
|
||||
|
@ -756,22 +790,22 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
public bool IsDiscipleOfWar()
|
||||
{
|
||||
return currentJob < CLASSID_THM;
|
||||
return GetClass() < CLASSID_THM;
|
||||
}
|
||||
|
||||
public bool IsDiscipleOfMagic()
|
||||
{
|
||||
return currentJob >= CLASSID_THM && currentJob < CLASSID_CRP;
|
||||
return GetClass() >= CLASSID_THM && currentJob < CLASSID_CRP;
|
||||
}
|
||||
|
||||
public bool IsDiscipleOfHand()
|
||||
{
|
||||
return currentJob >= CLASSID_CRP && currentJob < CLASSID_MIN;
|
||||
return GetClass() >= CLASSID_CRP && currentJob < CLASSID_MIN;
|
||||
}
|
||||
|
||||
public bool IsDiscipleOfLand()
|
||||
{
|
||||
return currentJob >= CLASSID_MIN;
|
||||
return GetClass() >= CLASSID_MIN;
|
||||
}
|
||||
#endregion lua helpers
|
||||
#endregion ai stuff
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.actors.chara.npc;
|
||||
using FFXIVClassic.Common;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
||||
{
|
||||
|
@ -18,34 +19,61 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
this.owner = owner;
|
||||
}
|
||||
|
||||
protected List<Character> GetContentGroupCharas()
|
||||
{
|
||||
List<Character> contentGroupCharas = null;
|
||||
|
||||
if (owner.currentContentGroup != null)
|
||||
{
|
||||
contentGroupCharas = new List<Character>(owner.currentContentGroup.GetMemberCount());
|
||||
foreach (var charaId in owner.currentContentGroup.GetMembers())
|
||||
{
|
||||
var chara = owner.zone.FindActorInArea<Character>(charaId);
|
||||
|
||||
if (chara != null)
|
||||
contentGroupCharas.Add(chara);
|
||||
}
|
||||
}
|
||||
|
||||
return contentGroupCharas;
|
||||
}
|
||||
|
||||
//Iterate over players in the group and if they are fighting, assist them
|
||||
protected override void TryAggro(DateTime tick)
|
||||
{
|
||||
//lua.LuaEngine.CallLuaBattleFunction(owner, "tryAggro", owner, GetContentGroupCharas());
|
||||
|
||||
foreach(Character chara in GetContentGroupCharas())
|
||||
{
|
||||
if(chara.IsPlayer())
|
||||
{
|
||||
if(owner.aiContainer.GetTargetFind().CanTarget((Character) chara.target) && chara.target is BattleNpc && ((BattleNpc)chara.target).hateContainer.HasHateForTarget(chara))
|
||||
{
|
||||
owner.Engage(chara.target.actorId);
|
||||
owner.hateContainer.AddBaseHate((Character) chara.target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//base.TryAggro(tick);
|
||||
}
|
||||
|
||||
// server really likes to hang whenever scripts iterate area's actorlist
|
||||
protected override void DoCombatTick(DateTime tick, List<Character> contentGroupCharas = null)
|
||||
{
|
||||
if (owner.currentContentGroup != null)
|
||||
if (contentGroupCharas == null)
|
||||
{
|
||||
contentGroupCharas = new List<Character>(owner.currentContentGroup.GetMemberCount());
|
||||
foreach (var charaId in owner.currentContentGroup.GetMembers())
|
||||
{
|
||||
var chara = owner.zone.FindActorInArea<Character>(charaId);
|
||||
contentGroupCharas = GetContentGroupCharas();
|
||||
}
|
||||
|
||||
if (chara != null)
|
||||
contentGroupCharas.Add(chara);
|
||||
}
|
||||
}
|
||||
base.DoCombatTick(tick, contentGroupCharas);
|
||||
}
|
||||
|
||||
protected override void DoRoamTick(DateTime tick, List<Character> contentGroupCharas = null)
|
||||
{
|
||||
if (owner.currentContentGroup != null)
|
||||
if (contentGroupCharas == null)
|
||||
{
|
||||
contentGroupCharas = new List<Character>(owner.currentContentGroup.GetMemberCount());
|
||||
foreach (var charaId in owner.currentContentGroup.GetMembers())
|
||||
{
|
||||
var chara = owner.zone.FindActorInArea<Character>(charaId);
|
||||
|
||||
if (chara != null)
|
||||
contentGroupCharas.Add(chara);
|
||||
}
|
||||
contentGroupCharas = GetContentGroupCharas();
|
||||
}
|
||||
base.DoRoamTick(tick, contentGroupCharas);
|
||||
}
|
||||
|
|
|
@ -39,12 +39,20 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
public override void Update(DateTime tick)
|
||||
{
|
||||
lastUpdate = tick;
|
||||
|
||||
// todo: handle aggro/deaggro and other shit here
|
||||
if (owner.aiContainer.IsEngaged())
|
||||
if (!owner.aiContainer.IsEngaged())
|
||||
{
|
||||
DoCombatTick(tick);
|
||||
TryAggro(tick);
|
||||
}
|
||||
else if (!owner.IsDead())
|
||||
|
||||
if(owner.aiContainer.IsEngaged())
|
||||
{
|
||||
//DoCombatTick(tick);
|
||||
}
|
||||
|
||||
//Only move if owner isn't dead and is either too far away from their spawn point or is meant to roam
|
||||
if (!owner.IsDead() && (owner.isMovingToSpawn || owner.GetMobMod((uint) MobModifier.Roams) > 0))
|
||||
{
|
||||
DoRoamTick(tick);
|
||||
}
|
||||
|
@ -63,6 +71,38 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
return false;
|
||||
}
|
||||
|
||||
//If the owner isn't moving to spawn, iterate over nearby enemies and
|
||||
//aggro the first one that is within 10 levels and can be detected, then engage
|
||||
protected virtual void TryAggro(DateTime tick)
|
||||
{
|
||||
if (tick >= neutralTime && !owner.isMovingToSpawn)
|
||||
{
|
||||
if (!owner.neutral && owner.IsAlive())
|
||||
{
|
||||
foreach (var chara in owner.zone.GetActorsAroundActor<Character>(owner, 50))
|
||||
{
|
||||
if (owner.allegiance == chara.allegiance)
|
||||
continue;
|
||||
|
||||
if (owner.aiContainer.pathFind.AtPoint() && owner.detectionType != DetectionType.None)
|
||||
{
|
||||
uint levelDifference = (uint)Math.Abs(owner.GetLevel() - chara.GetLevel());
|
||||
|
||||
if (levelDifference <= 10 || (owner.detectionType & DetectionType.IgnoreLevelDifference) != 0 && CanAggroTarget(chara))
|
||||
{
|
||||
owner.hateContainer.AddBaseHate(chara);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (owner.hateContainer.GetHateList().Count > 0)
|
||||
{
|
||||
Engage(owner.hateContainer.GetMostHatedTarget());
|
||||
}
|
||||
}
|
||||
public override bool Engage(Character target)
|
||||
{
|
||||
var canEngage = this.owner.aiContainer.InternalEngage(target);
|
||||
|
@ -77,6 +117,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
|
||||
|
||||
owner.moveState = 2;
|
||||
//owner.SetMod((uint)Modifier.Speed, 5);
|
||||
lastActionTime = DateTime.Now;
|
||||
battleStartTime = lastActionTime;
|
||||
// todo: adjust cooldowns with modifiers
|
||||
|
@ -127,12 +168,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
|
||||
protected virtual void DoRoamTick(DateTime tick, List<Character> contentGroupCharas = null)
|
||||
{
|
||||
if (owner.hateContainer.GetHateList().Count > 0)
|
||||
{
|
||||
Engage(owner.hateContainer.GetMostHatedTarget());
|
||||
return;
|
||||
}
|
||||
|
||||
if (tick >= waitTime)
|
||||
{
|
||||
neutralTime = tick.AddSeconds(5);
|
||||
|
@ -148,7 +183,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
|
||||
}
|
||||
}
|
||||
waitTime = tick.AddSeconds(10);
|
||||
waitTime = tick.AddSeconds(owner.GetMobMod((uint) MobModifier.RoamDelay));
|
||||
owner.OnRoam(tick);
|
||||
|
||||
if (CanMoveForward(0.0f) && !owner.aiContainer.pathFind.IsFollowingPath())
|
||||
|
@ -157,31 +192,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
owner.aiContainer.pathFind.SetPathFlags(PathFindFlags.None);
|
||||
owner.aiContainer.pathFind.PathInRange(owner.spawnX, owner.spawnY, owner.spawnZ, 1.5f, 50.0f);
|
||||
}
|
||||
lua.LuaEngine.CallLuaBattleFunction(owner, "onRoam", owner, contentGroupCharas);
|
||||
}
|
||||
|
||||
|
||||
if (tick >= neutralTime)
|
||||
{
|
||||
if (!owner.neutral && owner.IsAlive())
|
||||
{
|
||||
foreach (var chara in owner.zone.GetActorsAroundActor<Character>(owner, 50))
|
||||
{
|
||||
if (owner.allegiance == chara.allegiance)
|
||||
continue;
|
||||
|
||||
if (!owner.isMovingToSpawn && owner.aiContainer.pathFind.AtPoint() && owner.detectionType != DetectionType.None)
|
||||
{
|
||||
uint levelDifference = (uint)Math.Abs(owner.GetLevel() - chara.GetLevel());
|
||||
|
||||
if (levelDifference <= 10 || (owner.detectionType & DetectionType.IgnoreLevelDifference) != 0 && CanAggroTarget(chara))
|
||||
{
|
||||
owner.hateContainer.AddBaseHate(chara);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//lua.LuaEngine.CallLuaBattleFunction(owner, "onRoam", owner, contentGroupCharas);
|
||||
}
|
||||
|
||||
if (owner.aiContainer.pathFind.IsFollowingPath() && owner.aiContainer.CanFollowPath())
|
||||
|
@ -200,7 +211,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
Move();
|
||||
|
||||
if ((tick - lastCombatTickScript).TotalSeconds > 2)
|
||||
{
|
||||
lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick), contentGroupCharas);
|
||||
|
|
|
@ -159,6 +159,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||
/// </summary>
|
||||
public void FindWithinArea(Character target, ValidTarget flags, TargetFindAOETarget aoeTarget)
|
||||
{
|
||||
targets.Clear();
|
||||
validTarget = flags;
|
||||
// are we creating aoe circles around target or self
|
||||
if (aoeTarget == TargetFindAOETarget.Self)
|
||||
|
@ -174,6 +175,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||
if (masterTarget != null)
|
||||
targets.Add(masterTarget);
|
||||
|
||||
if (aoeType != TargetFindAOEType.None)
|
||||
{
|
||||
if (IsPlayer(owner))
|
||||
{
|
||||
if (masterTarget is Player)
|
||||
|
@ -226,7 +229,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||
AddAllInHateList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(targets.Count > 16)
|
||||
targets.RemoveRange(16, targets.Count - 16);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -288,7 +293,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||
|
||||
private void AddAllBattleNpcs(Character target, bool withPet)
|
||||
{
|
||||
var actors = owner.zone.GetActorsAroundActor<BattleNpc>(owner, 50);
|
||||
int dist = (int)maxDistance;
|
||||
var actors = owner.zone.GetActorsAroundActor<BattleNpc>(target, dist);
|
||||
|
||||
foreach (BattleNpc actor in actors)
|
||||
{
|
||||
|
@ -375,12 +381,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||
private bool IsWithinCircle(Character target, float maxDistance)
|
||||
{
|
||||
// todo: make y diff modifiable?
|
||||
if (Math.Abs(owner.positionX - target.positionY) > 6.0f)
|
||||
return false;
|
||||
|
||||
//if (Math.Abs(owner.positionX - target.positionY) > 6.0f)
|
||||
// return false;
|
||||
|
||||
if (this.targetPosition == null)
|
||||
this.targetPosition = aoeTarget == TargetFindAOETarget.Self ? owner.GetPosAsVector3() : masterTarget.GetPosAsVector3();
|
||||
return target.GetPosAsVector3().IsWithinCircle(targetPosition, param);
|
||||
return target.GetPosAsVector3().IsWithinCircle(targetPosition, maxDistance);
|
||||
}
|
||||
|
||||
private bool IsPlayer(Character target)
|
||||
|
|
|
@ -129,6 +129,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
|||
|
||||
private bool CanAttack()
|
||||
{
|
||||
return false;
|
||||
if (!owner.isAutoAttackEnabled)
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -15,7 +15,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
|||
: base(owner, null)
|
||||
{
|
||||
owner.Disengage();
|
||||
owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD2);
|
||||
//owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD2);
|
||||
var deathStatePacket = SetActorStatePacket.BuildPacket(owner.actorId, SetActorStatePacket.MAIN_STATE_DEAD, owner.currentSubState);
|
||||
owner.zone.BroadcastPacketAroundActor(owner, deathStatePacket);
|
||||
canInterrupt = false;
|
||||
startTime = tick;
|
||||
despawnTime = startTime.AddSeconds(timeToFadeOut);
|
||||
|
|
|
@ -110,16 +110,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
|||
var i = 0;
|
||||
foreach (var chara in targets)
|
||||
{
|
||||
var action = new BattleAction(target.actorId, spell.worldMasterTextId, spell.battleAnimation, 0, (byte)HitDirection.None, 1);
|
||||
var action = new BattleAction(chara.actorId, spell.worldMasterTextId, spell.battleAnimation, 0, (byte)HitDirection.None, 1);
|
||||
action.amount = (ushort)lua.LuaEngine.CallLuaBattleCommandFunction(owner, spell, "magic", "onMagicFinish", owner, chara, spell, action);
|
||||
actions[i++] = action;
|
||||
}
|
||||
|
||||
// todo: this is fuckin stupid, probably only need *one* error packet, not an error for each action
|
||||
var errors = (BattleAction[])actions.Clone();
|
||||
|
||||
owner.OnCast(this, actions, ref errors);
|
||||
owner.DoBattleAction(spell.id, spell.battleAnimation, actions);
|
||||
|
||||
}
|
||||
|
||||
public override void TryInterrupt()
|
||||
|
|
|
@ -88,7 +88,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
|||
{
|
||||
skill.targetFind.FindWithinArea(target, skill.validTarget, skill.aoeTarget);
|
||||
isCompleted = true;
|
||||
|
||||
var targets = skill.targetFind.GetTargets();
|
||||
|
||||
BattleAction[] actions = new BattleAction[targets.Count];
|
||||
|
@ -100,11 +99,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
|
|||
// evasion, miss, dodge, etc to be handled in script, calling helpers from scripts/weaponskills.lua
|
||||
action.amount = (ushort)lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onSkillFinish", owner, target, skill, action);
|
||||
actions[i++] = action;
|
||||
chara.Engage(chara.actorId, 1);
|
||||
}
|
||||
|
||||
// todo: this is fuckin stupid, probably only need *one* error packet, not an error for each action
|
||||
var errors = (BattleAction[])actions.Clone();
|
||||
|
||||
owner.OnWeaponSkill(this, actions, ref errors);
|
||||
owner.DoBattleAction(skill.id, skill.battleAnimation, actions);
|
||||
}
|
||||
|
|
|
@ -76,18 +76,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils
|
|||
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)
|
||||
{
|
||||
// todo: other stuff too
|
||||
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.OnDamageTaken(attacker, action, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static int CalculateSpellDamage(Character attacker, Character defender, BattleCommand spell)
|
||||
|
|
|
@ -172,7 +172,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
packets = new List<SubPacket>();
|
||||
if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0)
|
||||
{
|
||||
var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this);
|
||||
var propPacketUtil = new ActorPropertyPacketUtil("charaWork/stateAtQuicklyForAll", this);
|
||||
|
||||
propPacketUtil.AddProperty("charaWork.parameterSave.hp[0]");
|
||||
propPacketUtil.AddProperty("charaWork.parameterSave.hpMax[0]");
|
||||
|
@ -272,6 +272,10 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
if (lastAttacker is Player)
|
||||
{
|
||||
//I think this is, or should be odne in DoBattleAction. Packet capture had the message in the same packet as an attack
|
||||
// <actor> defeat/defeats <target>
|
||||
//((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0)));
|
||||
|
||||
if (lastAttacker.currentParty != null && lastAttacker.currentParty is Party)
|
||||
{
|
||||
foreach (var memberId in ((Party)lastAttacker.currentParty).members)
|
||||
|
@ -279,14 +283,9 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
var partyMember = zone.FindActorInArea<Player>(memberId);
|
||||
// onDeath(monster, player, killer)
|
||||
lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, partyMember, lastAttacker);
|
||||
// <actor> defeat/defeats <target>
|
||||
|
||||
if (lastAttacker is Player)
|
||||
((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0)));
|
||||
|
||||
if(partyMember is Player)
|
||||
((Player)partyMember).AddExp(1500, (byte)partyMember.GetJob(), 5);
|
||||
|
||||
if (partyMember is Player)
|
||||
((Player)partyMember).AddExp(1500, (byte)partyMember.GetClass(), 5);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -298,6 +297,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
positionUpdates?.Clear();
|
||||
aiContainer.InternalDie(tick, despawnTime);
|
||||
//this.ResetMoveSpeeds();
|
||||
// todo: reset cooldowns
|
||||
|
||||
lua.LuaEngine.GetInstance().OnSignal("mobkill");
|
||||
|
|
|
@ -32,5 +32,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.npc
|
|||
AbilityScript = 21, // call my script's onAbility whenever i finish using an ability
|
||||
CallForHelp = 22, // actor with this id outside of target's party with this can attack me
|
||||
FreeForAll = 23, // any actor can attack me
|
||||
Roams = 24, // Do I walk around?
|
||||
RoamDelay = 25 // What is the delay between roam ticks
|
||||
}
|
||||
}
|
|
@ -557,6 +557,9 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
if (currentContentGroup != null)
|
||||
currentContentGroup.SendGroupPackets(playerSession);
|
||||
|
||||
if (currentParty != null)
|
||||
currentParty.SendGroupPackets(playerSession);
|
||||
}
|
||||
|
||||
private void SendRemoveInventoryPackets(List<ushort> slots)
|
||||
|
@ -1714,6 +1717,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
//currentParty.members.Remove(this);
|
||||
if (partyGroup.members.Count == 0)
|
||||
Server.GetWorldManager().NoMembersInParty((Party)currentParty);
|
||||
|
||||
currentParty = null;
|
||||
}
|
||||
|
||||
|
@ -1755,7 +1759,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0)
|
||||
{
|
||||
var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this);
|
||||
var propPacketUtil = new ActorPropertyPacketUtil("charaWork/stateAtQuicklyForAll", this);
|
||||
|
||||
// todo: should this be using job as index?
|
||||
propPacketUtil.AddProperty($"charaWork.parameterSave.hp[{0}]");
|
||||
|
@ -1768,9 +1772,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
|
||||
base.PostUpdate(tick, packets);
|
||||
SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp");
|
||||
hpInfo.AddTarget();
|
||||
QueuePacket(hpInfo.BuildPacket(actorId));
|
||||
}
|
||||
|
||||
public override void Die(DateTime tick)
|
||||
|
@ -1801,7 +1802,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public void UpdateHotbarCommands(List<ushort> slotsToUpdate)
|
||||
{
|
||||
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/command", this);
|
||||
ActorPropertyPacketUtil compatibiltyUtil = new ActorPropertyPacketUtil("charaWork/commandDetailForSelf", this);
|
||||
foreach (ushort slot in slotsToUpdate)
|
||||
{
|
||||
propPacketUtil.AddProperty($"charaWork.command[{slot}]");
|
||||
|
@ -2184,9 +2184,9 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
{
|
||||
// todo: update hotbar timers to skill's recast time (also needs to be done on class change or equip crap)
|
||||
base.OnCast(state, actions, ref errors);
|
||||
|
||||
var spell = ((MagicState)state).GetSpell();
|
||||
// todo: should just make a thing that updates the one slot cause this is dumb as hell
|
||||
|
||||
UpdateHotbarTimer(spell.id, spell.recastTimeSeconds);
|
||||
LuaEngine.GetInstance().OnSignal("spellUse");
|
||||
}
|
||||
|
@ -2309,11 +2309,11 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
Database.LoadHotbar(this);
|
||||
}
|
||||
|
||||
//Gets the id of the player's current job. If they aren't a job, gets the id of their class
|
||||
public byte GetCurrentClassOrJob()
|
||||
{
|
||||
if (currentJob != 0)
|
||||
return (byte) currentJob;
|
||||
|
||||
return charaWork.parameterSave.state_mainSkill[0];
|
||||
}
|
||||
|
||||
|
@ -2324,12 +2324,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
mpMaxBase = (ushort)hp;
|
||||
charaWork.parameterSave.mpMax = (short)hp;
|
||||
charaWork.parameterSave.mp = (short)hp;
|
||||
AddTP(0);
|
||||
//SendCharaExpInfo();
|
||||
//ActorPropertyPacketUtil exp = new ActorPropertyPacketUtil("charaWork/exp", this);
|
||||
SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp");
|
||||
hpInfo.AddTarget();
|
||||
QueuePacket(hpInfo.BuildPacket(actorId));
|
||||
AddTP(3000);
|
||||
updateFlags |= ActorUpdateFlags.HpTpMp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -161,6 +161,9 @@ namespace FFXIVClassic_Map_Server.actors.director
|
|||
{
|
||||
members.Add(actor);
|
||||
|
||||
if (actor is Player)
|
||||
((Player)actor).AddDirector(this);
|
||||
|
||||
if (contentGroup != null)
|
||||
contentGroup.AddMember(actor);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace FFXIVClassic_Map_Server.actors.group
|
|||
public void Start()
|
||||
{
|
||||
isStarted = true;
|
||||
|
||||
SendGroupPacketsAll(members);
|
||||
}
|
||||
|
||||
|
@ -50,6 +51,7 @@ namespace FFXIVClassic_Map_Server.actors.group
|
|||
if (actor == null)
|
||||
return;
|
||||
|
||||
if(!members.Contains(actor.actorId))
|
||||
members.Add(actor.actorId);
|
||||
|
||||
if (actor is Character)
|
||||
|
@ -121,7 +123,6 @@ namespace FFXIVClassic_Map_Server.actors.group
|
|||
}
|
||||
|
||||
session.QueuePacket(GroupMembersEndPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
|
||||
|
||||
}
|
||||
|
||||
public override uint GetTypeId()
|
||||
|
|
|
@ -64,11 +64,23 @@ namespace FFXIVClassic_Map_Server.actors.group
|
|||
groupMembers.Add(new GroupMember(id, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(id).customDisplayName));
|
||||
foreach (uint charaId in members)
|
||||
{
|
||||
if (charaId != id)
|
||||
groupMembers.Add(new GroupMember(charaId, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(charaId).customDisplayName));
|
||||
var chara = Server.GetWorldManager().GetActorInWorld(charaId);
|
||||
if (charaId != id && chara != null)
|
||||
groupMembers.Add(new GroupMember(charaId, -1, 0, false, true, chara.customDisplayName));
|
||||
}
|
||||
return groupMembers;
|
||||
}
|
||||
|
||||
public void AddMember(uint memberId)
|
||||
{
|
||||
members.Add(memberId);
|
||||
SendGroupPacketsAll(members);
|
||||
}
|
||||
|
||||
public void RemoveMember(uint memberId)
|
||||
{
|
||||
members.Remove(memberId);
|
||||
SendGroupPacketsAll(members);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
|
||||
public void FlushQueuedSendPackets()
|
||||
{
|
||||
if (!socket.Connected)
|
||||
if (socket == null || !socket.Connected)
|
||||
return;
|
||||
|
||||
while (SendPacketQueue.Count > 0)
|
||||
|
|
|
@ -477,12 +477,20 @@ namespace FFXIVClassic_Map_Server.lua
|
|||
if (script != null)
|
||||
{
|
||||
if (!script.Globals.Get(funcName).IsNil())
|
||||
{
|
||||
try
|
||||
{
|
||||
Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
|
||||
DynValue value = coroutine.Resume(args2);
|
||||
ResolveResume(player, coroutine, value);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
player.SendMessage(0x20, "", e.Message);
|
||||
player.EndEvent();
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!optional)
|
||||
|
|
|
@ -112,7 +112,6 @@ namespace FFXIVClassic_Map_Server.packets.send.actor
|
|||
{
|
||||
string[] split = name.Split('.');
|
||||
int arrayIndex = 0;
|
||||
|
||||
if (!(split[0].Equals("work") || split[0].Equals("charaWork") || split[0].Equals("playerWork") || split[0].Equals("npcWork") || split[0].Equals("guildleveWork")))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -35,27 +35,27 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle
|
|||
binWriter.Write((UInt16)commandId);
|
||||
binWriter.Write((UInt16)0x810); //?
|
||||
|
||||
binWriter.Seek(0x58, SeekOrigin.Begin);
|
||||
binWriter.Seek(0x28, SeekOrigin.Begin);
|
||||
for (int i = 0; i < max; i++)
|
||||
binWriter.Write((UInt32)actionList[listOffset + i].targetId);
|
||||
|
||||
binWriter.Seek(0xA0, SeekOrigin.Begin);
|
||||
binWriter.Seek(0x70, SeekOrigin.Begin);
|
||||
for (int i = 0; i < max; i++)
|
||||
binWriter.Write((UInt16)actionList[listOffset + i].amount);
|
||||
|
||||
binWriter.Seek(0xC4, SeekOrigin.Begin);
|
||||
binWriter.Seek(0x94, SeekOrigin.Begin);
|
||||
for (int i = 0; i < max; i++)
|
||||
binWriter.Write((UInt16)actionList[listOffset + i].worldMasterTextId);
|
||||
|
||||
binWriter.Seek(0xE8, SeekOrigin.Begin);
|
||||
binWriter.Seek(0xB8, SeekOrigin.Begin);
|
||||
for (int i = 0; i < max; i++)
|
||||
binWriter.Write((UInt32)actionList[listOffset + i].effectId);
|
||||
|
||||
binWriter.Seek(0x130, SeekOrigin.Begin);
|
||||
binWriter.Seek(0x100, SeekOrigin.Begin);
|
||||
for (int i = 0; i < max; i++)
|
||||
binWriter.Write((Byte)actionList[listOffset + i].param);
|
||||
|
||||
binWriter.Seek(0x142, SeekOrigin.Begin);
|
||||
binWriter.Seek(0x112, SeekOrigin.Begin);
|
||||
for (int i = 0; i < max; i++)
|
||||
binWriter.Write((Byte)actionList[listOffset + i].unknown);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
|
||||
</startup>
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FFXIVClassic_World_Server</RootNamespace>
|
||||
<AssemblyName>FFXIVClassic World Server</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
|
@ -48,6 +48,26 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Cyotek.Collections.Generic.CircularBuffer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
|
||||
|
@ -190,7 +210,8 @@
|
|||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent></PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
<package id="NLog" version="4.3.5" targetFramework="net452" />
|
||||
<package id="NLog.Config" version="4.3.5" targetFramework="net452" />
|
||||
<package id="NLog.Schema" version="4.3.4" targetFramework="net452" />
|
||||
<package id="RabbitMQ.Client" version="4.0.0" targetFramework="net452" requireReinstallation="True" />
|
||||
<package id="RabbitMQ.Client" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.15
|
||||
VisualStudioVersion = 15.0.27004.2005
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FFXIVClassic Map Server", "FFXIVClassic Map Server\FFXIVClassic Map Server.csproj", "{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
|
@ -23,38 +23,63 @@ EndProject
|
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launcher Editor", "Launcher Editor\Launcher Editor.csproj", "{0FFA9D2F-41C6-443C-99B7-665702CF548F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Debug|x64.Build.0 = Debug|x64
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Release|x64.ActiveCfg = Release|x64
|
||||
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Release|x64.Build.0 = Release|x64
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Debug|x64.Build.0 = Debug|x64
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Release|x64.ActiveCfg = Release|x64
|
||||
{703091E0-F69C-4177-8FAE-C258AC6A65AA}.Release|x64.Build.0 = Release|x64
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Debug|x64.Build.0 = Debug|x64
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Release|x64.ActiveCfg = Release|x64
|
||||
{3A3D6626-C820-4C18-8C81-64811424F20E}.Release|x64.Build.0 = Release|x64
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Debug|x64.Build.0 = Debug|x64
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Release|x64.ActiveCfg = Release|x64
|
||||
{3067889D-8A50-40D6-9CD5-23AA8EA96F26}.Release|x64.Build.0 = Release|x64
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Debug|x64.Build.0 = Debug|x64
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Release|x64.ActiveCfg = Release|x64
|
||||
{0FFA9D2F-41C6-443C-99B7-665702CF548F}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F350E848-7622-48E1-87DC-4C2B1596122B}
|
||||
EndGlobalSection
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
|
|
|
@ -32,6 +32,26 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
|
|
@ -34,24 +34,56 @@ function allyGlobal.onDespawn(ally)
|
|||
|
||||
end
|
||||
|
||||
--tryAggro serves the same purpose for now, keeping this around just in case
|
||||
function allyGlobal.HelpPlayers(ally, contentGroupCharas, pickRandomTarget)
|
||||
if contentGroupCharas then
|
||||
print("assssss")
|
||||
if contentGroupCharas and not ally.IsEngaged() then
|
||||
for chara in contentGroupCharas do
|
||||
if chara then
|
||||
-- probably a player, or another ally
|
||||
-- todo: queue support actions, heal, try pull hate off player etc
|
||||
if chara:IsPlayer() then
|
||||
-- do stuff
|
||||
if not ally:IsEngaged() then
|
||||
if chara:IsEngaged() then
|
||||
print("ass")
|
||||
allyGlobal.EngageTarget(ally, chara.target, nil)
|
||||
return true
|
||||
if not ally.IsEngaged() then
|
||||
if chara.IsEngaged() then
|
||||
allyGlobal.EngageTarget(ally, chara.target, nil);
|
||||
break;
|
||||
end
|
||||
end
|
||||
elseif chara:IsMonster() and chara:IsEngaged() then
|
||||
allyGlobal.EngageTarget(ally, chara, nil)
|
||||
return true
|
||||
elseif chara.IsMonster() and chara.IsEngaged() then
|
||||
if not ally.IsEngaged() then
|
||||
allyGlobal.EngageTarget(ally, chara, nil);
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Iterate over characters in contentGroup, if a player is in combat, assist them.
|
||||
function allyGlobal.tryAggro(ally, contentGroupCharas)
|
||||
local count = 0;
|
||||
if contentGroupCharas and not ally.IsEngaged() then
|
||||
for i = 0, #contentGroupCharas - 1 do
|
||||
if contentGroupCharas[i] and ally then
|
||||
if contentGroupCharas[i].IsPlayer() then
|
||||
-- probably a player, or another ally
|
||||
-- todo: queue support actions, heal, try pull hate off player etc
|
||||
if contentGroupCharas[i].target then
|
||||
if ally.aiContainer:GetTargetFind():CanTarget(contentGroupCharas[i].target) and contentGroupCharas[i].target.IsMonster() and contentGroupCharas[i].target.hateContainer:HasHateForTarget(contentGroupCharas[i]) then
|
||||
-- do stuff
|
||||
allyGlobal.EngageTarget(ally, contentGroupCharas[i].target, nil);
|
||||
break;
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
elseif contentGroupCharas[i].IsMonster() and contentGroupCharas[i].IsEngaged() then
|
||||
if not ally.IsEngaged() then
|
||||
print("Engaging monster that is engaged");
|
||||
allyGlobal.EngageTarget(ally, contentGroupCharas[i], nil);
|
||||
break;
|
||||
end]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -71,12 +103,13 @@ function allyGlobal.EngageTarget(ally, target, contentGroupCharas)
|
|||
for chara in contentGroupCharas do
|
||||
if chara.IsMonster() then
|
||||
if chara.allegiance ~= ally.allegiance then
|
||||
ally:Engage(chara)
|
||||
ally.Engage(chara)
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif target then
|
||||
ally:Engage(target)
|
||||
ally.hateContainer:AddBaseHate(target);
|
||||
ally.Engage(target)
|
||||
ally.hateContainer.AddBaseHate(target);
|
||||
end
|
||||
end
|
|
@ -152,8 +152,11 @@ function onTrigger(player, argc, skillName, level)
|
|||
--local x, y, z = player.GetPos();
|
||||
for i = 1, 1 do
|
||||
|
||||
local actor = player.GetZone().SpawnActor(2207303, 'ass', x, y, z, rot, 0, 0, true );
|
||||
local actor = player.GetZone().SpawnActor(2104001, 'ass', x, y, z, rot, 0, 0, true );
|
||||
|
||||
if player.currentContentGroup then
|
||||
player.currentContentGroup:AddMember(actor.actorId)
|
||||
end
|
||||
--actor.FollowTarget(player, 3.2);
|
||||
end;
|
||||
return;
|
||||
|
|
|
@ -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);
|
||||
|
||||
if target.hateContainer then
|
||||
target.hateContainer.UpdateHate(caster, damage);
|
||||
end;
|
||||
return damage;
|
||||
end;
|
21
data/scripts/commands/magic/blizzard.lua
Normal file
21
data/scripts/commands/magic/blizzard.lua
Normal file
|
@ -0,0 +1,21 @@
|
|||
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);
|
||||
|
||||
return damage;
|
||||
end;
|
24
data/scripts/commands/magic/burst.lua
Normal file
24
data/scripts/commands/magic/burst.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
require("global");
|
||||
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(1000, 2500);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
return damage;
|
||||
end;
|
24
data/scripts/commands/magic/fira.lua
Normal file
24
data/scripts/commands/magic/fira.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
require("global");
|
||||
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);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
return damage;
|
||||
end;
|
24
data/scripts/commands/magic/firaga.lua
Normal file
24
data/scripts/commands/magic/firaga.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
require("global");
|
||||
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(1000, 2500);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
return damage;
|
||||
end;
|
27
data/scripts/commands/magic/fire.lua
Normal file
27
data/scripts/commands/magic/fire.lua
Normal file
|
@ -0,0 +1,27 @@
|
|||
require("global");
|
||||
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);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
if target.hateContainer then
|
||||
target.hateContainer.UpdateHate(caster, damage);
|
||||
end;
|
||||
return damage;
|
||||
end;
|
24
data/scripts/commands/magic/flare.lua
Normal file
24
data/scripts/commands/magic/flare.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
require("global");
|
||||
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(1000, 2500);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
return damage;
|
||||
end;
|
24
data/scripts/commands/magic/freeze.lua
Normal file
24
data/scripts/commands/magic/freeze.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
require("global");
|
||||
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);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
return damage;
|
||||
end;
|
24
data/scripts/commands/magic/holy.lua
Normal file
24
data/scripts/commands/magic/holy.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
require("global");
|
||||
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(1000, 2500);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
return damage;
|
||||
end;
|
21
data/scripts/commands/magic/thundaga.lua
Normal file
21
data/scripts/commands/magic/thundaga.lua
Normal file
|
@ -0,0 +1,21 @@
|
|||
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);
|
||||
|
||||
return damage;
|
||||
end;
|
21
data/scripts/commands/magic/thundara.lua
Normal file
21
data/scripts/commands/magic/thundara.lua
Normal file
|
@ -0,0 +1,21 @@
|
|||
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);
|
||||
|
||||
return damage;
|
||||
end;
|
|
@ -17,8 +17,5 @@ function onMagicFinish(caster, target, spell, action)
|
|||
-- 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;
|
26
data/scripts/commands/weaponskill/simian_thrash.lua
Normal file
26
data/scripts/commands/weaponskill/simian_thrash.lua
Normal file
|
@ -0,0 +1,26 @@
|
|||
require("global");
|
||||
|
||||
function onSkillPrepare(caster, target, skill)
|
||||
return 0;
|
||||
end;
|
||||
|
||||
function onSkillStart(caster, target, skill)
|
||||
return 0;
|
||||
end;
|
||||
|
||||
function onSkillFinish(caster, target, skill, action)
|
||||
local damage = math.random(0, 0);
|
||||
|
||||
-- todo: populate a global script with statuses and modifiers
|
||||
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);
|
||||
--action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636);
|
||||
|
||||
if target.hateContainer then
|
||||
target.hateContainer.UpdateHate(caster, damage);
|
||||
end;
|
||||
return damage;
|
||||
end;
|
|
@ -11,12 +11,12 @@ function onCreate(starterPlayer, contentArea, director)
|
|||
--mob3 = contentArea:SpawnActor(2201407, "mob3", 375.125, 4.4, -703.591, -1.54);
|
||||
yda = GetWorldManager().SpawnBattleNpcById(6, contentArea);
|
||||
papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea);
|
||||
yda:ChangeState(2);
|
||||
--yda:ChangeState(2);
|
||||
mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea);
|
||||
mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea);
|
||||
mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea);
|
||||
starterPlayer.currentParty.members:Add(yda.actorId);
|
||||
starterPlayer.currentParty.members:Add(papalymo.actorId);
|
||||
starterPlayer.currentParty:AddMember(papalymo.actorId);
|
||||
starterPlayer.currentParty:AddMember(yda.actorId);
|
||||
starterPlayer:SetMod(modifiersGlobal.MinimumHpLock, 1);
|
||||
|
||||
|
||||
|
@ -72,6 +72,47 @@ end
|
|||
|
||||
function onDestroy()
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
--Iterating over allies using the for...in syntax throws an except and lags the server.
|
||||
--This function probably isn't needed either way, it does the smae thing as TryAggro in ally
|
||||
function onUpdate(tick, area)
|
||||
if area then
|
||||
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
|
||||
|
||||
if allies then
|
||||
for i = 0, #allies - 1 do
|
||||
if allies[i] then
|
||||
if not allies[i]:IsEngaged() then
|
||||
if player:IsEngaged() and player.target then
|
||||
|
||||
allies[i].neutral = false
|
||||
allies[i].isAutoAttackEnabled = true
|
||||
allies[i]:SetMod(modifiersGlobal.Speed, 8)
|
||||
allyGlobal.EngageTarget(allies[i], player.target)
|
||||
exitLoop = true
|
||||
break
|
||||
-- todo: support scripted paths
|
||||
elseif allies[i]:GetSpeed() > 0 then
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if exitLoop then
|
||||
resumeChecks = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if not resumeChecks then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -10,55 +10,71 @@ function init()
|
|||
return "/Director/Quest/QuestDirectorMan0g001";
|
||||
end
|
||||
|
||||
--Should we be using this to spawn mobs and drop Simplecontent?
|
||||
function onCreateContentArea(players, director, contentArea, contentGroup)
|
||||
director:StartContentGroup();
|
||||
end
|
||||
|
||||
function onEventStarted(player, actor, triggerName)
|
||||
man0g0Quest = player:GetQuest("Man0g0");
|
||||
player:SendMessage(0x20, "", "Starting");
|
||||
startTutorialMode(player);
|
||||
callClientFunction(player, "delegateEvent", player, man0g0Quest, "processTtrBtl001", nil, nil, nil);
|
||||
player:EndEvent();
|
||||
player:SendMessage(0x20, "", "Waiting for player active");
|
||||
waitForSignal("playerActive");
|
||||
player:SendMessage(0x20, "", "player active");
|
||||
wait(1); --If this isn't here, the scripts bugs out. TODO: Find a better alternative.
|
||||
kickEventContinue(player, actor, "noticeEvent", "noticeEvent");
|
||||
callClientFunction(player, "delegateEvent", player, man0g0Quest, "processTtrBtl002", nil, nil, nil);
|
||||
player:SendMessage(0x20, "", "processTtrBtl002 called");
|
||||
player:EndEvent();
|
||||
|
||||
--Combat portion of tutorial
|
||||
if player:IsDiscipleOfWar() then
|
||||
waitForSignal("playerAttack");
|
||||
closeTutorialWidget(player);
|
||||
showTutorialSuccessWidget(player, 9055); --Open TutorialSuccessWidget for attacking enemy
|
||||
wait(3);
|
||||
openTutorialWidget(player, CONTROLLER_KEYBOARD, TUTORIAL_TP);
|
||||
waitForSignal("tpOver1000");
|
||||
closeTutorialWidget(player);
|
||||
openTutorialWidget(player, CONTROLLER_KEYBOARD, TUTORIAL_WEAPONSKILLS);
|
||||
|
||||
if player:IsDiscipleOfWar() then
|
||||
waitForSignal("weaponskillUsed"); --Should be wait for weaponskillUsed signal
|
||||
elseif player:IsDiscipleOfMagic() then
|
||||
waitForSignal("spellUsed")
|
||||
elseif player:IsDiscipleOfHand() then
|
||||
waitForSignal("abilityUsed")
|
||||
elseif player:IsDiscipleOfLand() then
|
||||
waitForSignal("abilityUsed")
|
||||
end
|
||||
waitForSignal("weaponskillUsed");
|
||||
closeTutorialWidget(player);
|
||||
showTutorialSuccessWidget(player, 9065); --Open TutorialSuccessWidget for weapon skill
|
||||
elseif player:IsDiscipleOfMagic() then
|
||||
openTutorialWidget(player, CONTROLLER_KEYBOARD, TUTORIAL_CASTING);
|
||||
waitForSignal("spellUsed");
|
||||
closeTutorialWidget(player);
|
||||
elseif player:IsDiscipleOfHand() then
|
||||
waitForSignal("abilityUsed");
|
||||
elseif player:IsDiscipleOfLand() then
|
||||
waitForSignal("abilityUsed");
|
||||
end
|
||||
|
||||
waitForSignal("mobkill"); --Should be wait for mobkill
|
||||
--Currently this requires the player to pass all the other signals first, need a way for signals to work out of order
|
||||
waitForSignal("mobkill");
|
||||
waitForSignal("mobkill");
|
||||
waitForSignal("mobkill");
|
||||
worldMaster = GetWorldMaster();
|
||||
wait(5);--Debug waits, get rid of these later
|
||||
player:Disengage(0x0000);
|
||||
wait(5);
|
||||
man0g0Quest:NextPhase(10);
|
||||
wait(5);
|
||||
--This doesn't work
|
||||
player:RemoveFromCurrentPartyAndCleanup();
|
||||
player:SendDataPacket("attention", worldMaster, "", 51073, 2);
|
||||
wait(7);
|
||||
wait(5);
|
||||
player:ChangeMusic(7);
|
||||
player:ChangeState(0);
|
||||
wait(5);
|
||||
kickEventContinue(player, actor, "noticeEvent", "noticeEvent");
|
||||
wait(5);
|
||||
callClientFunction(player, "delegateEvent", player, man0g0Quest, "processEvent020_1", nil, nil, nil);
|
||||
|
||||
wait(5);
|
||||
player:GetZone():ContentFinished();
|
||||
player:EndEvent();
|
||||
GetWorldManager():DoZoneChange(player, 155, "PrivateAreaMasterPast", 1, 15, 175.38, -1.21, -1156.51, -2.1);
|
||||
--player:EndEvent();
|
||||
--GetWorldManager():DoZoneChange(player, 155, "PrivateAreaMasterPast", 1, 15, 175.38, -1.21, -1156.51, -2.1);
|
||||
--[[
|
||||
IF DoW:
|
||||
OpenWidget (TP)
|
||||
|
@ -72,10 +88,9 @@ function onEventStarted(player, actor, triggerName)
|
|||
OpenWidget (DEFEAT ENEMY)
|
||||
]]
|
||||
|
||||
--man0g0Quest:NextPhase(10);
|
||||
--player:EndEvent();
|
||||
|
||||
--GetWorldManager():DoZoneChange(player, 155, "PrivateAreaMasterPast", 1, 15, 175.38, -1.21, -1156.51, -2.1);
|
||||
player:EndEvent();
|
||||
wait(5);
|
||||
GetWorldManager():DoZoneChange(player, 155, "PrivateAreaMasterPast", 1, 15, 175.38, -1.21, -1156.51, -2.1);
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -74,4 +74,6 @@ mobModifiersGlobal =
|
|||
AbilityScript = 21, -- call my script's onAbility whenever i finish using an ability
|
||||
CallForHelp = 22, -- actor with this id outside of target's party with this can attack me
|
||||
FreeForAll = 23, -- any actor can attack me
|
||||
Roams = 24, -- Do I walk around?
|
||||
RoamDelay = 25 -- What is the delay between roam ticks
|
||||
}
|
|
@ -7,5 +7,22 @@ function onSpawn(ally)
|
|||
ally:SetHP(ally:GetMaxHP())
|
||||
ally.isAutoAttackEnabled = false;
|
||||
ally.neutral = false
|
||||
ally:SetMod(modifiersGlobal.Speed, 0)
|
||||
end
|
||||
|
||||
function onCombatTick(ally, target, tick, contentGroupCharas)
|
||||
allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas);
|
||||
end
|
||||
|
||||
|
||||
function onRoam(ally, contentGroupCharas)
|
||||
ally.detectionType = 0xFF
|
||||
ally.isMovingToSpawn = false
|
||||
ally.neutral = false
|
||||
ally.animationId = 0
|
||||
allyGlobal.onCombatTick(ally, nil, nil, contentGroupCharas)
|
||||
end
|
||||
|
||||
|
||||
function tryAggro(ally, contentGroupCharas)
|
||||
allyGlobal.tryAggro(ally, contentGroupCharas)
|
||||
end
|
|
@ -8,3 +8,19 @@ function onSpawn(ally)
|
|||
ally.neutral = false
|
||||
ally:SetMod(modifiersGlobal.Speed, 0)
|
||||
end
|
||||
|
||||
function onCombatTick(ally, target, tick, contentGroupCharas)
|
||||
allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas)
|
||||
end
|
||||
|
||||
function tryAggro(ally, contentGroupCharas)
|
||||
allyGlobal.tryAggro(ally, contentGroupCharas)
|
||||
end
|
||||
|
||||
function onRoam(ally, contentGroupCharas)
|
||||
ally.detectionType = 0xFF
|
||||
ally.isMovingToSpawn = false
|
||||
ally.neutral = false
|
||||
ally.animationId = 0
|
||||
--allyGlobal.onCombatTick(ally, contentGroupCharas)
|
||||
end
|
||||
|
|
|
@ -7,10 +7,9 @@ end
|
|||
|
||||
function onEventStarted(player, npc, triggerName)
|
||||
man0g0Quest = player:GetQuest("Man0g0");
|
||||
print("hi");
|
||||
print("Got Quest Man0g0");
|
||||
if (man0g0Quest ~= nil) then
|
||||
|
||||
print("hi2");
|
||||
print("Man0g0Quest is not nil");
|
||||
if (triggerName == "pushDefault") then
|
||||
callClientFunction(player, "delegateEvent", player, man0g0Quest, "processTtrNomal002", nil, nil, nil);
|
||||
elseif (triggerName == "talkDefault") then
|
||||
|
@ -23,8 +22,8 @@ function onEventStarted(player, npc, triggerName)
|
|||
man0g0Quest:SaveData();
|
||||
player:GetDirector("OpeningDirector"):onTalkEvent(player, npc);
|
||||
--Was she talked to after papalymo?
|
||||
print("hi3");
|
||||
else
|
||||
print("Making content area");
|
||||
if (man0g0Quest:GetQuestFlag(MAN0G0_FLAG_MINITUT_DONE1) == true) then
|
||||
|
||||
player:EndEvent();
|
||||
|
@ -43,8 +42,9 @@ function onEventStarted(player, npc, triggerName)
|
|||
player:KickEvent(director, "noticeEvent", true);
|
||||
player:SetLoginDirector(director);
|
||||
|
||||
print("hi5");
|
||||
print("Content area and director made");
|
||||
GetWorldManager():DoZoneChangeContent(player, contentArea, 362.4087, 4, -703.8168, 1.5419, 16);
|
||||
print("Zone Change");
|
||||
return;
|
||||
else
|
||||
callClientFunction(player, "delegateEvent", player, man0g0Quest, "processEvent000_1", nil, nil, nil);
|
||||
|
|
Loading…
Add table
Reference in a new issue