Jump to content
  • 0

ACT EDITOR: Mob Name & Element Script help


Question

Posted

Hello, i'm not sure if this is the right place to ask but is there anyone who has a script for putting mob name on top of the monster sprite on all layers and then putting the Element they're most vulnerable to- on top of the mobname?(refer to pic #1 for example)

or even just the Element the mob is most vulnerable to? (refer to pic #2 for example)

I did find a script made by Tokeiburu himself regarding putting mobname on top of the monster sprite on all layers, but i haven't found any clue about putting elemental vulnerability of the monster instead. So if anyone has an idea, it'd be much appreciated!

Screenshot 2024-12-10 020053.png

Screenshot 2024-12-10 020358.png

2 answers to this question

Recommended Posts

  • 0
Posted (edited)

This was resolved through PMs a while back; here was the final script for anyone interested:

// Act Editor Script - v1.0.5.1
// By Tokeiburu
GrfColor textForeground = "0xffffff";
var fontType = "Minecraftia";
var fontSize = 14;
var fontBold = true;
var dataGrfName = @"C:\mobWithNames\data.grf";
var newGrfName = @"C:\mobWithNames\mobsWithName.grf";
var mobDbPath = @"C:\mobWithNames\mob_db.yml";
var attrFixDbPath = @"C:\mobWithNames\attr_fix.yml";
var jobnamePath = @"C:\mobWithNames\jobname.lub";
var npcIdentityPath = @"C:\mobWithNames\npcidentity.lub";
var oldEncoding = EncodingService.DisplayEncoding;
var displayMobNames = false;
var maxElementShown = 3;
var showFirstElementDamage = true;
//var elementTextColors = false;

// Fixed settings
var mobFolder = @"data\sprite\¸ó½ºÅÍ\";
//jobnamePath = @"C:\Gravity Ragnarok - Copy\data\luafiles514\lua files\datainfo\jobname.lub";
//npcIdentityPath = @"C:\Gravity Ragnarok - Copy\data\luafiles514\lua files\datainfo\npcidentity.lub";
//dataGrfName = @"C:\Gravity Ragnarok - Copy\data.grf";
//newGrfName = @"C:\test\mobsWithName.grf";
//mobDbPath = @"C:\Users\Tokei\Desktop\SVN\rathena4\db\re\mob_db.yml";
//attrFixDbPath = @"C:\Users\Tokei\Desktop\SVN\rathena4\db\re\attr_fix.yml";

var jobname = new JobnameLubData(jobnamePath, npcIdentityPath);

int[,,] attr_fix = new int[4, 10, 10];
StringBuilder b = new StringBuilder();
var ele2id = new Dictionary<string, int>();
ele2id["Neutral"] = 0;
ele2id["Water"] = 1;
ele2id["Earth"] = 2;
ele2id["Fire"] = 3;
ele2id["Wind"] = 4;
ele2id["Poison"] = 5;
ele2id["Holy"] = 6;
ele2id["Dark"] = 7;
ele2id["Ghost"] = 8;
ele2id["Undead"] = 9;

var id2ele = new Dictionary<int, string>();
foreach (var entry in ele2id)
	id2ele[entry.Value] = entry.Key;

try {
	EncodingService.DisplayEncoding = EncodingService.ANSI;
	int ival;
	string[] values;
	var mobId2ServerName = new Dictionary<int, string>();
	var mobId2ServerElement = new Dictionary<int, int>();
	var mobId2ServerElementLevel = new Dictionary<int, int>();
	
	{
		// Load the attr_fix file
		var parser = new YamlParser(attrFixDbPath);
		var body = parser.Output["Body"];
		
		foreach (var entry in body) {
			int level = Int32.Parse(entry["Level"]) - 1;
			
			foreach (var ele2id_entry in ele2id) {
				var element_name = ele2id_entry.Key;
				var element_id = ele2id_entry.Value;
				
				var def_elements = entry[element_name];
			
				foreach (ParserKeyValue def_ele in def_elements) {
					attr_fix[level, element_id, ele2id[def_ele.Key]] = Int32.Parse(def_ele.Value);
				}
			}
		}
	}
	
	{
		// Load the mob_db file
		var parser = new YamlParser(mobDbPath);
		var body = parser.Output["Body"];
		
		foreach (var entry in body) {
			int mobId = Int32.Parse(entry["Id"]);
			mobId2ServerName[mobId] = entry["Name"];
			
			int eleId = 0;
			int eleLevel = 0;
			
			if (entry["Element"] != null) {
				eleId = ele2id[entry["Element"]];
			}
			
			if (entry["ElementLevel"] != null) {
				eleLevel = Int32.Parse(entry["ElementLevel"]) - 1;
			}
			
			mobId2ServerElement[mobId] = eleId;
			mobId2ServerElementLevel[mobId] = eleLevel;
		}
	}
	
	Func<Act, string, int, Act> addNameAbove = (actI, display, offset) => {
		var pixels = new byte[256 * 20 * 4];
		BitmapSource bitmapSource = BitmapSource.Create(256, 20, 96, 96, PixelFormats.Bgra32, null, pixels, 256 * 4);
		var visual = new DrawingVisual();
		using (DrawingContext drawingContext = visual.RenderOpen()) {
			var ft = new FormattedText(display, CultureInfo.InvariantCulture, FlowDirection.LeftToRight,
				new Typeface(fontType), fontSize, new SolidColorBrush(textForeground.ToColor()));
			
			if (fontBold)
				ft.SetFontWeight(FontWeights.Bold);
			drawingContext.DrawImage(bitmapSource, new Rect(0, 0, 256, 20));
			drawingContext.DrawText(ft, new Point(2, 2));
		}
 
		var image = new DrawingImage(visual.Drawing);
		var im = new Image { Source = image };
		im.Measure(new Size(image.Width, image.Height));
		im.Arrange(new Rect(0.0, 0.0, image.Width, image.Height));
		im.UpdateLayout();
 
		var grfImage = GrfToWpfBridge.Imaging.ConvertToBitmapSource(im);
		var transparent = new GrfColor(0, 0, 0, 0);
 
		for (int i = 0; i < grfImage.NumberOfPixels; i++) {
			Buffer.BlockCopy((grfImage.Pixels[4 * i + 3] > 0x80 ? textForeground : transparent).ToBgraBytes(), 0, grfImage.Pixels, 4 * i, 4);
		}
 
		grfImage.Convert(GrfImageType.Indexed8); grfImage.Trim(); grfImage.Margin(2);
		Buffer.BlockCopy(GrfColor.Black.ToBgraBytes(), 0, grfImage.Palette, 2 * 4, 4);
 
		for (int y = 1; y < grfImage.Height - 1; y++) {
			for (int x = 1; x < grfImage.Width - 1; x++) {
				if (grfImage.Pixels[y * grfImage.Width + x] == 1) continue;
 
				if (grfImage.Pixels[(y - 1) * grfImage.Width + (x)] == 1 || grfImage.Pixels[(y + 1) * grfImage.Width + (x)] == 1 ||
					grfImage.Pixels[(y) * grfImage.Width + (x - 1)] == 1 || grfImage.Pixels[(y) * grfImage.Width + (x + 1)] == 1)
					grfImage.Pixels[y * grfImage.Width + x] = 2;
			}
		}
		
		act = actI;
		
		// Doesn't support Bgra32 only sprites
		if (act.Sprite.Palette == null) return act;
 
		var unused = act.Sprite.GetUnusedPaletteIndexes().ToList();
		if (unused.Count <= 1) return act;
		if (!act.Sprite.Palette.Contains(textForeground)) Buffer.BlockCopy(textForeground.ToBgraBytes(), 0, act.Sprite.Palette.BytePalette, 4 * unused[0], 4);
		if (!act.Sprite.Palette.Contains(GrfColor.Black)) Buffer.BlockCopy(GrfColor.Black.ToBgraBytes(), 0, act.Sprite.Palette.BytePalette, 4 * unused[1], 4);
 
		var colors = act.Sprite.Palette.Colors.ToList();
		var whiteIndex = (byte)colors.IndexOf(textForeground);
		var blackIndex = (byte)colors.IndexOf(GrfColor.Black);
 
		for (int i = 0; i < grfImage.NumberOfPixels; i++) {
			if (grfImage.Pixels[i] == 1) grfImage.Pixels[i] = whiteIndex;
			else if (grfImage.Pixels[i] == 2) grfImage.Pixels[i] = blackIndex;
		}
 
		var index = act.Sprite.InsertAny(grfImage);
		var max = 0;
 
		act.AnimationExecute(0, a => a.AllLayers(p => {
			if ((ival = ((int)(p.ScaleY * p.Height) / 2 - p.OffsetY)) > max)
				max = ival;
		}));
 
		max += 15;
 
		var layer = new Layer(index, grfImage) { OffsetY = -(max + fontSize / 2) + offset };
		ival = 0;
 
		foreach (var action in act) {
			// Don't show for the death animation
			if (ival >= 32 && ival < 40)
				continue;
 
			foreach (var frame in action) {
				frame.Layers.Add(layer);
			}
 
			ival++;
		}
 
		return act;
	};
	
	string displayName;
	int from = -1;
	var processed = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
 
	using (var dataGrf = new GrfHolder(dataGrfName))
	using (var outputGrf = new GrfHolder(newGrfName, GrfLoadOptions.New)) {
		int count = jobname.Id2Sprite.Count;
 
		TaskManager.DisplayTaskC("Adding text label", "Processing...", () => from / (float) count * 100f, isCancelling => {
			try {
				foreach (var mobEntry in jobname.Id2Sprite.OrderBy(p => p.Key)) {
					if (isCancelling()) return;
					
					var mobResourceName = mobEntry.Value;
					var mobId = mobEntry.Key;
					
					//b.AppendLine(mobId + "\t" + mobResourceName + "\t" + processed.Contains(mobResourceName));
					
					if (processed.Contains(mobResourceName)) {
						from++;
						continue;
					}
					
					if (mobId2ServerName.ContainsKey(mobId)) {
						displayName = mobId2ServerName[mobId];//.ToUpper();
						processed.Add(mobResourceName);
					}
					else {
						displayName = jobname.Id2Job[mobId].Replace("JT_", "").Replace("_", " ");//.ToUpper();
					}
					
					var actEntry = dataGrf.FileTable.TryGet(GrfPath.Combine(mobFolder, mobResourceName + ".act"));
					var sprEntry = dataGrf.FileTable.TryGet(GrfPath.Combine(mobFolder, mobResourceName + ".spr"));
					
					if (actEntry == null || sprEntry == null) {
						from++;
						continue;
					}
 
					var mobAct = new Act(actEntry, new Spr(sprEntry));
					
					StringBuilder e_builder = new StringBuilder();
					
					if (mobId2ServerName.ContainsKey(mobId)) {
						int eleLevel = mobId2ServerElementLevel[mobId];
						int eleId = mobId2ServerElement[mobId];
						var dmgElements = new Dictionary<int, int>();
						
						for (int i = 0; i < 9; i++) {
							dmgElements[i] = attr_fix[eleLevel, i, eleId];
						}
						
						int highest = -1;
						int max = maxElementShown;
						
						foreach (var dmgElement in dmgElements.OrderByDescending(p => p.Value)) {
							if (dmgElement.Value < highest)
								break;
							
							max--;
							
							if (max < 0) {
								e_builder.Append("...");
								break;
							}
							
							highest = dmgElement.Value;
							
							if (e_builder.Length == 0)
								e_builder.Append(id2ele[dmgElement.Key] + (showFirstElementDamage ? " (" + dmgElement.Value + "%)" : ""));
							else
								e_builder.Append(" - " + id2ele[dmgElement.Key]);
						}
						
						mobAct = addNameAbove(mobAct, e_builder.ToString(), 0);
						
						if (displayMobNames)
							mobAct = addNameAbove(mobAct, displayName, 15);
					}
					else {
						if (!displayMobNames) {
							from++;
							continue;
						}
						
						mobAct = addNameAbove(mobAct, displayName, 0);
					}
					
					MemoryStream actStream = new MemoryStream();
					MemoryStream sprStream = new MemoryStream();
 
					try {
						mobAct.SaveWithSprite(actStream, sprStream);
					}
					catch {
						from++;
						continue;
					}
					
					outputGrf.Commands.AddFile(actEntry.RelativePath, actStream);
					outputGrf.Commands.AddFile(sprEntry.RelativePath, sprStream);
 
					if (from % 200 == 0) {
						GC.Collect();
						outputGrf.QuickSave();
						outputGrf.Reload();
					}
 
					from++;
				}
			}
			catch (Exception err) {
				ErrorHandler.HandleException(err);
			}
			finally {
				outputGrf.QuickSave();
				from = count;
			}
		});
		
		//ErrorHandler.HandleException(b.ToString());
	}
}
catch (Exception err) {
	ErrorHandler.HandleException(err);
}
finally {
	EncodingService.DisplayEncoding = oldEncoding;
}

 

Edited by Tokei
  • Upvote 2
  • Like 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...