Originally Posted by
spazman6117
Using your code, I managed to actually get Carnage Chieftain monkeys to show up by putting in their metadata string into the added entity list instead of the Spectral Leader for now for testing.
BUT,
they only show up if i kill the mob in the area im standing in and then leave the map and come back. So the entity is loading into the list ok, but the render is not rendering ALL entities in the entire map. If i run away from the area and come back to the same spot, the red circles are still showing up for the dead corpses but in other areas, there is no red circle for those corpses.
Could you please help me to figure out how I would make the render actually render ALL corpses as i kill them and not JUST the ones I killed and then re-entered the map.
It's not even showing the corpses i want to search for as i kill them. Only when leaving the map and only in the current area im standing in when entering the map through the portal.
Cheers
Idk if this is the right place to continue this discussion, you might want to post your own thread somewhere.
I added a cache for the monsters, so they dont get deleted when you change areas. Also added possibility for multiple different corpses. (and a check so monsters that are too far away dont get drawn). Tested it and it should work in most scenarios. If you need help figuring out what the code does, chatgpt gives great explanations.
If you want to draw all the corpses on the minimap (which would be cool), you'll have to figure that out yourself by looking at other plugins. I haven't messed around with that too much.
Code:
public class MonsterPlugin : BaseSettingsPlugin<MonsterPluginSettings>
{
List<string> Paths = new List<string>{
"Scarecrow",
"WarHeroCasterAtlasUber",
};
// Explanation dictionaries inside a dictionary:
//Dictionary<AreaHash, Dictionary<EntityId, Pair(EntityName, GridPos)>>
Dictionary<uint, Dictionary<uint, KeyValuePair<string,Vector2i>>> CachedPos;
public override bool Initialise()
{
CachedPos = new Dictionary<uint, Dictionary<uint, KeyValuePair<string, Vector2i>>>();
return true;
}
public override void AreaChange(AreaInstance area)
{
// Can possibly replace the CachedPos.TryAdd in Tick();
//CachedPos.TryAdd(area.Hash, new Dictionary<uint, KeyValuePair<string, Vector2i>>());
}
public override Job Tick()
{
ICollection<Entity> dd = GameController.EntityListWrapper.Entities;
CachedPos.TryAdd(GameController.IngameState.Data.CurrentAreaHash, new Dictionary<uint, KeyValuePair<string, Vector2i>>());
// Update position of all entities in cache
foreach (var entity in dd)
{
if (CachedPos[GameController.IngameState.Data.CurrentAreaHash].ContainsKey(entity.Id))
{
var old = CachedPos[GameController.IngameState.Data.CurrentAreaHash][entity.Id];
var positioned = entity.GetComponent<Positioned>();
if (positioned == null) continue;
CachedPos[GameController.IngameState.Data.CurrentAreaHash][entity.Id] = new KeyValuePair<string, Vector2i> (old.Key, positioned.GridPosition);
}
}
return null;
}
// taken from beast plugin
private void DrawFilledCircleInWorldPosition(System.Numerics.Vector3 position, float radius, SharpDX.Color color)
{
var circlePoints = new List<Vector2>();
const int segments = 15;
const float segmentAngle = 2f * MathF.PI / segments;
for (var i = 0; i < segments; i++)
{
var angle = i * segmentAngle;
var currentOffset = new Vector2(MathF.Cos(angle), MathF.Sin(angle)) * radius;
var nextOffset = new Vector2(MathF.Cos(angle + segmentAngle), MathF.Sin(angle + segmentAngle)) * radius;
var currentWorldPos = position + new System.Numerics.Vector3(currentOffset, 0);
var nextWorldPos = position + new System.Numerics.Vector3(nextOffset, 0);
circlePoints.Add(GameController.Game.IngameState.Camera.WorldToScreen(currentWorldPos));
circlePoints.Add(GameController.Game.IngameState.Camera.WorldToScreen(nextWorldPos));
}
Graphics.DrawConvexPolyFilled(circlePoints.ToArray(),
color with { A = SharpDX.Color.ToByte((int)((double)0.2f * byte.MaxValue)) });
Graphics.DrawPolyLine(circlePoints.ToArray(), color, 2);
}
// Do graphic draw calls here
public override void Render()
{
var player = GameController.Player.GetComponent<Positioned>();
Vector2i v2 = player.GridPosition;
foreach(var pos in CachedPos[GameController.IngameState.Data.CurrentAreaHash])
{
string name = pos.Value.Key;
Vector2i v = pos.Value.Value;
// only draw if enemy is close enough
int dx = v.X - v2.X;
int dy = v.Y - v2.Y;
double dist = Math.Sqrt(dx * dx + dy * dy);
if (dist > 80) continue;
var v3 = GameController.IngameState.Data.ToWorldWithTerrainHeight(v);
// Draw
Graphics.DrawText(name, GameController.IngameState.Camera.WorldToScreen(v3), SharpDX.Color.White, FontAlign.Center);
DrawFilledCircleInWorldPosition(v3, 50, SharpDX.Color.White);
}
}
// Save entities
public override void EntityAdded(Entity entity)
{
// added multiple paths
for(int i = 0; i < Paths.Count(); i++)
{
if (entity.Path.Contains(Paths[i]))
{
var render = entity.GetComponent<Render>();
var positioned = entity.GetComponent<Positioned>();
// save monster name and position to cache
CachedPos[GameController.IngameState.Data.CurrentAreaHash][entity.Id] = new KeyValuePair<string, Vector2i>(render.Name, positioned.GridPosition);
}
}
}
}