Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加插件: Economics.Projectile 自定义弹幕 #141

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Economics.Projectile/Economics.Projectile.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<Import Project="..\template.targets" />

<ItemGroup>
<ProjectReference Include="..\Economics.RPG\Economics.RPG.csproj" />
<ProjectReference Include="..\EconomicsAPI\EconomicsAPI.csproj" />
</ItemGroup>

Expand Down
14 changes: 14 additions & 0 deletions Economics.Projectile/Internet/ItemData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Newtonsoft.Json;

namespace Economics.Projectile;
public class ItemData
{
[JsonProperty("弹幕数据")]
public List<ProjectileReplace> ProjData { get; set; } = new();

[JsonProperty("物品使用弹药")]
public bool UseAmmo { get; set; } = false;

[JsonProperty("备注")]
public string Name { get; set; } = string.Empty;
}
13 changes: 13 additions & 0 deletions Economics.Projectile/Internet/ProjConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Newtonsoft.Json;

namespace Economics.Projectile;

public class ProjConfig
{
[JsonProperty("弹幕触发")]
public Dictionary<int, ProjectileData> ProjectileReplace { get; set; } = new();

[JsonProperty("物品触发 ")]
public Dictionary<int, ItemData> ItemReplace { get; set; } = new();

}
25 changes: 25 additions & 0 deletions Economics.Projectile/Internet/ProjectileData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Newtonsoft.Json;

namespace Economics.Projectile;

public class ProjectileData
{
[JsonProperty("弹幕数据")]
public List<ProjectileReplace> ProjData { get; set; } = new();

[JsonProperty("使用物品时触发")]
public bool useItem = true;

[JsonProperty("来自于召唤物")]
public bool fromMinion = false;

[JsonProperty("本身就是召唤物")]
public bool IsMinion = false;

[JsonProperty("召唤物攻击间隔")]
public int CD = 15;

[JsonProperty("备注")]
public string Name { get; set; } = string.Empty;
}

26 changes: 26 additions & 0 deletions Economics.Projectile/Internet/ProjectileReplace.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Newtonsoft.Json;

namespace Economics.Projectile;
public class ProjectileReplace
{
[JsonProperty("弹幕ID")]
public int ID = 0;

[JsonProperty("弹幕击退动态跟随")]
public bool KnockBackFollow = false;

[JsonProperty("弹幕伤害动态跟随")]
public bool DamageFollow = false;

[JsonProperty("弹幕伤害")]
public float Damage = 0f;

[JsonProperty("弹幕击退")]
public float KnockBack = 0f;

[JsonProperty("弹幕射速")]
public float speed = 0f;

[JsonProperty("限制等级")]
public List<string> Limit { get; set; } = new();
}
243 changes: 231 additions & 12 deletions Economics.Projectile/Plugin.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Reflection;
using EconomicsAPI.Extensions;
using System.Reflection;
using Terraria;
using TerrariaApi.Server;
using TShockAPI;
using TShockAPI.Configuration;

namespace Economics.Projectile;

Expand All @@ -18,31 +20,248 @@ public class Plugin : TerrariaPlugin

internal static string PATH = Path.Combine(EconomicsAPI.Economics.SaveDirPath, "Projectile.json");

private ProjConfig Config = new();

private readonly int[] useCD = new int[Main.maxPlayers];

private readonly int[] MiniCD = new int[Main.maxPlayers];


public Plugin(Main game) : base(game)
{
Order = 6;
}

public override void Initialize()
{
LoadConfig();
TShockAPI.Hooks.GeneralHooks.ReloadEvent += (_) => LoadConfig();
GetDataHandlers.NewProjectile.Register(OnProj);
ServerApi.Hooks.NetGetData.Register(this, GetData);

GetDataHandlers.PlayerUpdate.Register(OnDate);
ServerApi.Hooks.GameUpdate.Register(this, Onupdate);
On.Terraria.Projectile.Damage += Projectile_Damage;
On.Terraria.Projectile.Minion_FindTargetInRange += Projectile_Minion_FindTargetInRange;
}

private void Projectile_Damage(On.Terraria.Projectile.orig_Damage orig, Terraria.Projectile self)
{
if (self.minion && Config.ProjectileReplace.TryGetValue(self.type, out ProjectileData? data) && data != null && data.IsMinion)
{
if (MiniCD[self.whoAmI] == 0)
{
int id = -1;
self.Minion_FindTargetInRange(300, ref id, false);
MiniCD[self.whoAmI] += data.CD;
}
}
}

private void Projectile_Minion_FindTargetInRange(On.Terraria.Projectile.orig_Minion_FindTargetInRange orig, Terraria.Projectile self, int startAttackRange, ref int attackTarget, bool skipIfCannotHitWithOwnBody, Func<Entity, int, bool> customEliminationCheck)
{
if (Config.ProjectileReplace.TryGetValue(self.type, out ProjectileData? data) && data != null)
{
float num = startAttackRange;
float num2 = num;
float num3 = num;
NPC ownerMinionAttackTargetNPC = self.OwnerMinionAttackTargetNPC;
if (ownerMinionAttackTargetNPC != null && ownerMinionAttackTargetNPC.CanBeChasedBy(self) && self.IsInRangeOfMeOrMyOwner(ownerMinionAttackTargetNPC, num, out var _, out var _, out var _))
{
attackTarget = ownerMinionAttackTargetNPC.whoAmI;
}
else
{
if (attackTarget >= 0)
{
return;
}
for (int i = 0; i < 200; i++)
{
NPC nPC = Main.npc[i];
if (nPC.damage > 0 && nPC.CanBeChasedBy(this) && self.IsInRangeOfMeOrMyOwner(nPC, num, out var myDistance2, out var playerDistance2, out var closerIsMe2) && (!skipIfCannotHitWithOwnBody || self.CanHitWithOwnBody(nPC)) && (customEliminationCheck == null || customEliminationCheck(nPC, attackTarget)))
{
attackTarget = i;
num = closerIsMe2 ? myDistance2 : playerDistance2;
if (num2 > myDistance2)
{
num2 = myDistance2;
}
if (num3 > playerDistance2)
{
num3 = playerDistance2;
}
num = Math.Max(num2, num3);
}
}
}
if (attackTarget >= 0)
{
for (int i = 0; i < data.ProjData.Count; i++)
{
var proj = data.ProjData[i];
if (RPG.RPG.InLevel(Main.player[self.owner].name, proj.Limit))
{
//伤害
float damage = proj.Damage;
//击退
float knockback = proj.KnockBack;
//速度
var speed = self.position.RotatedBy(self.position.AngleTo(Main.npc[attackTarget].position)).ToLenOf(proj.speed);

int index = EconomicsAPI.Utils.Projectile.NewProjectile(Terraria.Projectile.GetNoneSource(), self.position, speed, proj.ID, (int)damage, knockback, self.owner);

TSPlayer.All.SendData(PacketTypes.ProjectileNew, "", index);

}
}
}
}
}

private void Onupdate(EventArgs args)
{
for (int i = 0; i < Main.maxPlayers; i++)
{
if (useCD[i] > 0)
{
useCD[i]--;
}
if (MiniCD[i] > 0)
{
MiniCD[i]--;
}
}
}

private void GetData(GetDataEventArgs args)
private void OnDate(object? sender, GetDataHandlers.PlayerUpdateEventArgs e)
{
if(args.MsgID == PacketTypes.MinionAttackTargetUpdate)
if (e.Player.IsLoggedIn && !e.Player.Dead && e.Player.TPlayer.controlUseItem && useCD[e.PlayerId] == 0 && Config.ItemReplace.TryGetValue(e.Player.TPlayer.HeldItem.netID, out ItemData? data) && data != null)
{
var reader = new BinaryReader(new MemoryStream(args.Msg.readBuffer, args.Index, args.Length));
var who = reader.ReadByte();
var npcid = reader.ReadInt16();
Console.WriteLine(npcid);
Console.WriteLine(Main.npc[npcid].FullName);
if (data.UseAmmo)
return;
for (int i = 0; i < data.ProjData.Count; i++)
{
var proj = data.ProjData[i];
if (RPG.RPG.InLevel(e.Player.Name, proj.Limit))
{
//伤害
float damage = proj.Damage;
//击退
float knockback = proj.KnockBack;
//速度
var speed = e.Player.TPlayer.ItemOffSet().ToLenOf(proj.speed);

int index = EconomicsAPI.Utils.Projectile.NewProjectile(e.Player.TPlayer.GetItemSource_OpenItem(e.Player.SelectedItem.netID), e.Player.TPlayer.position, speed, proj.ID, (int)damage, knockback, e.PlayerId);
Main.projectile[index].active = true;
Main.projectile[index].type = proj.ID;
TSPlayer.All.SendData(PacketTypes.ProjectileNew, null, index);
useCD[e.Player.Index] += e.Player.SelectedItem.useTime;
}
}
}
}

private void OnProj(object? sender, GetDataHandlers.NewProjectileEventArgs e)
{
throw new NotImplementedException();
Main.projectile[e.Identity].active = true;
Main.projectile[e.Identity].owner = e.Player.Index;
if (e.Player.TPlayer.controlUseItem && e.Player.SelectedItem.useAmmo != 0)
{
if (Config.ItemReplace.TryGetValue(e.Player.SelectedItem.netID, out var pr) && pr != null)
{
if (pr.UseAmmo)
{
for (int i = 0; i < pr.ProjData.Count; i++)
{
var proj = pr.ProjData[i];
if (RPG.RPG.InLevel(e.Player.Name, proj.Limit))
{
//伤害
float damage = proj.DamageFollow ? (e.Damage - e.Player.SelectedItem.damage) / e.Damage * proj.Damage : proj.Damage;
//击退
float knockback = proj.KnockBackFollow ? (e.Knockback - e.Player.SelectedItem.knockBack) / e.Knockback * proj.KnockBack : proj.KnockBack;
//速度
var speed = proj.speed > 0f ? e.Velocity.ToLenOf(proj.speed) : e.Velocity;

int index = EconomicsAPI.Utils.Projectile.NewProjectile(e.Player.TPlayer.GetItemSource_OpenItem(e.Player.SelectedItem.netID), e.Position, speed, proj.ID, (int)damage, knockback, e.Owner);

e.Player.SendData(PacketTypes.ProjectileNew, "", index);

}
}
}
}
}
else
{
if (e.Player.IsLoggedIn && Config.ProjectileReplace.TryGetValue(e.Type, out ProjectileData? data) && data != null)
{
if (!data.useItem || e.Player.TPlayer.controlUseItem)
{
if ((e.Player.SelectedItem.shoot == e.Type && !data.IsMinion) || data.fromMinion)
{
for (int i = 0; i < data.ProjData.Count; i++)
{
var proj = data.ProjData[i];
if (RPG.RPG.InLevel(e.Player.Name, proj.Limit))
{
//伤害
float damage = proj.DamageFollow ? (e.Damage - e.Player.SelectedItem.damage) / e.Damage * proj.Damage : proj.Damage;
//击退
float knockback = proj.KnockBackFollow ? (e.Knockback - e.Player.SelectedItem.knockBack) / e.Knockback * proj.KnockBack : proj.KnockBack;
//速度

var speed = proj.speed > 0f ? e.Velocity.ToLenOf(proj.speed) : e.Velocity;

int index = EconomicsAPI.Utils.Projectile.NewProjectile(e.Player.TPlayer.GetItemSource_OpenItem(e.Player.SelectedItem.netID), e.Position, speed, proj.ID, (int)damage, knockback, e.Owner);

e.Player.SendData(PacketTypes.ProjectileNew, "", index);

}
}
}
}
}
}

}



public void LoadConfig()
{
if (!File.Exists(PATH))
{
Config.ProjectileReplace.Add(274, new ProjectileData()
{
ProjData = new List<ProjectileReplace>()
{
new()
{
ID = 132,
speed = 15,
Damage=80,
KnockBack = 10,
Limit = new()
}
}
});

Config.ItemReplace.Add(1327, new()
{
ProjData = new List<ProjectileReplace>()
{
new()
{
ID = 132,
speed = 15,
Damage=80,
KnockBack = 10,
Limit = new()
}
}
});
}
Config = EconomicsAPI.Configured.ConfigHelper.LoadConfig(PATH, Config);
}
}

}
Loading
Loading