ROItem Plugin: Display item names based on the RO client

Other plugins for extending OpenKore's functionality. This forum is only for posting new plugins and commenting on existing plugins. For support, use the Support forum.

Moderator: Moderators

Message
Author
hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

ROItem Plugin: Display item names based on the RO client

#1 Post by hakore »

ROItem Plugin: Display item names based on the RO client.
Licensed by hakore (hakore@users.sourceforge.net) under GPL


Version / Compatibility:
2.0.0 - first public release, compatible with Openkore v.2.0


Description:

This is a cosmetic plugin that modifies Openkore's item naming style based on the Ragnarok Online Client. This also enables Openkore to display the name of the item creator (or forger/brewer) for easy item sorting and identification.

Note, however, that by using this plugin, you must use the modified item display names on all of your configuration files (i.e. config.txt, items_control.txt, pickupitems.txt).


Required Files:
  • plugins\roitem.pl - the plugin file (see attachment below)
  • plugins\roitem\cardpostfixnametable.txt - extract from data.grf using GRFTool (see instructions below)
  • plugins\roitem\cardprefixnametable.txt - extract from data.grf using GRFTool (see instructions below)
  • plugins\roitem\idnum2itemdisplaynametable.txt - extract from data.grf using GRFTool (see instructions below)
  • plugins\roitem\itemslotcounttable.txt - extract from data.grf using GRFTool (see instructions below)
  • plugins\roitem\translations.txt - translation file for non-English item naming convention (see attachment below)

Extracting data files - GRF Tool
  1. Download GRFTool
  2. Find data.grf in your RagnarokOnline folder and open it using GRFTool
  3. In the GRFTool's search box, type "*.txt". (Alternatively, you can type the exact names of the required files)
  4. Select the files cardpostfixnametable.txt, cardprefixnametable.txt, idnum2itemdisplaynametable.txt, and itemslotcounttable.txt, and then extract them.
  5. Place all four files in a folder named "roitem" in your plugins folder.

Configuration Options (config.txt):
  • roItem_showCreatorNames <boolean>
    - set this option to 1 to enable displaying of creator names.
  • roItem_nameFormat <string>
    - set this to "bRO" to display item names based on bRO's item name format (experimental, thanks to --Roger--).
    - note: currently, there is only one format (bRO) besides the default international convention.

Code

roitem.pl

Code: Select all

# ============================
# ROItem v.2.0.0
# ============================
# Licensed by hakore (hakore@users.sourceforge.net) under GPL
#
package ROItem;

use strict;
use Globals;
use Exporter;
use base qw(Exporter);
use Settings;
use Log qw(message);
use Translation qw(TF);
#use encoding 'utf8';

our @EXPORT = qw(
	itemNameSimple
	itemName
);

my $datafolder = "$Plugins::current_plugin_folder\\roitem";

my @tables;
my %itemdisplayname;
my %itemslotcount;
my %cardprefixname;
my %cardpostfixname;
my %translations;
my %elementdisplay = (
	1 => 'Ice',
	2 => 'Earth',
	3 => 'Fire',
	4 => 'Wind'#,
	#5 => 'Poison',
	#6 => 'Holy',
	#7 => 'Dark',
	#8 => 'Spirit',
	#9 => 'Undead'
);
my %starcrumbdisplay = (
	1 => 'Very Strong',
	2 => 'Very Very Strong',
	3 => 'Very Very Very Strong'
);
my %cardmultiplier = (
	2 => 'Double',
	3 => 'Triple',
	4 => 'Quadruple'
);

push @tables, Settings::addTableFile(
	"$datafolder\\idnum2itemdisplaynametable.txt",
	loader => [\&parseROLUT, \%itemdisplayname],
	autoSearch => 0);
push @tables, Settings::addTableFile(
	"$datafolder\\itemslotcounttable.txt",
	loader => [\&parseROLUT, \%itemslotcount],
	autoSearch => 0);
push @tables, Settings::addTableFile(
	"$datafolder\\cardprefixnametable.txt",
	loader => [\&parseROLUT, \%cardprefixname],
	autoSearch => 0);
push @tables, Settings::addTableFile(
	"$datafolder\\cardpostfixnametable.txt",
	loader => [\&parseROLUT, \%cardpostfixname],
	autoSearch => 0);
push @tables, Settings::addTableFile(
	"$datafolder\\translations.txt",
	loader => [\&parseTranlations, \%translations],
	autoSearch => 0);

if (defined %config) {
	my $progressHandler = sub {
		my ($filename) = @_;
		Log::message Translation::TF("Loading %s...\n", $filename);
	};
	Settings::loadByRegexp(qr/roitem/, $progressHandler);
}

Plugins::register('ROItem', 'Display item names based on the Ragnarok Online client', \&unload);

my %creators;
my $creators = 0;
my %creatorsX;
my $creatorsX = 0;

my $hooks = Plugins::addHooks(
				['packet/character_name', \&processCharName],
				['packet/received_character_ID_and_Map', \&clearCharNameCache]
);

sub unload {
	Plugins::delHooks($hooks);
	foreach (@tables) {
		Settings::removeFile($_);
	}
}

sub parseROLUT {
	my ($file, $r_hash) = @_;

	undef %{$r_hash};
	open FILE, "< $file";
	#open FILE, "<:utf8", $file;
	foreach (<FILE>) {
		s/[\r\n]//g;
		next if (length($_) == 0 || /^\/\//);

		my ($id, $name) = split /#/, $_, 3;
		if ($id) {
			if ($name) {
				$name =~ s/_/ /g;
				$name =~ s/^\s+|\s+$//g;
				$name =~ s/\s+/ /g;
			}
			$r_hash->{$id} = $name;
		}
	}
	close FILE;
	return 1;
}

sub parseTranlations {
	my ($file, $r_hash) = @_;

	%{$r_hash} = ();
	open FILE, "< $file";
	#open FILE, "<:utf8", $file;
	foreach (<FILE>) {
		next if (/^#/);
		s/[\r\n]//g;
		next if (length($_) == 0);

		my ($key, $value) = split /\t+/, $_, 2;
		$r_hash->{$key} = $value;
	}
	close FILE;
	return 1;
}

sub getTranslation {
	my ($str) = @_;
	return $translations{$str} || $str;
}

sub getCreatorName {
	my ($ID, $item) = @_;
	return '' if (!$config{'roItem_showCreatorNames'});
	if (!exists $creators{$ID}) {
		if (!exists $creatorsX{$ID}) {
			$messageSender->sendGetCharacterName($ID);
			$timeout{ai_getInfo}{time} = time;
			$creatorsX{$ID}{time} = time;
			$creatorsX{$ID}{items} = ();
			$creatorsX++;
		}
		$item->{nameless} = 1;
		push @{$creatorsX{$ID}{items}}, $item;
		return getTranslation('Nameless');
	} else {
		return $creators{$ID};
	}
}

sub processCharName {
	my (undef, $args) = @_;
	if (exists $creatorsX{$args->{ID}}) {
		my $nameless = quotemeta getTranslation('Nameless');
		foreach (@{$creatorsX{$args->{ID}}{items}}) {
			if ($config{'roItem_nameFormat'} eq 'bRO') {
				$_->{name} =~ s/ $nameless$/ $args->{name}/;
			} else {
				$_->{name} =~ s/(^| )${nameless}'s /$1$args->{name}'s /;
			}
			delete $_->{nameless};
		}
		delete $creatorsX{$args->{ID}};
		$creatorsX--;
	}
	$creators++ if (!exists $creators{$args->{ID}});
	$creators{$args->{ID}} = $args->{name};
}

sub clearCharNameCache {
	undef %creators;
	$creators = 0;
	undef %creatorsX;
	$creatorsX = 0;
}

# Resolve the name of a simple item
sub itemNameSimple {
	my $ID = shift;
	return 'Unknown' unless defined($ID);
	return 'None' unless $ID;
	return $itemdisplayname{$ID} || "Unknown #$ID";
}

##
# itemName($item)
#
# Resolve the name of an item. $item should be a hash with these keys:
# nameID  => integer index into %items_lut
# cards   => 8-byte binary data as sent by server
# upgrade => integer upgrade level
sub itemName {
	my $item = shift;

	my $name = $itemdisplayname{$item->{nameID}};
	return "Unknown #$item->{nameID}" if (!$name);

	# Resolve item prefix/suffix (carded or forged)
	my $prefix = '';
	my $suffix = '';
	my $type = unpack('v1', $item->{cards});
	my $numSlots = 0;

	if ($type == 254) {
		# Brewed potion
		my $creator = getCreatorName(substr($item->{cards}, 4, 4), $item);
		if ($config{'roItem_nameFormat'} eq 'bRO') {
			$suffix .= (($creator) ? " $creator" : '');
		} else {
			$prefix .= (($creator) ? "${creator}'s " : '');
		}
	} elsif ($type == 255) {
		# Forged weapon
		my ($starcrumb, $creator, $element);
		my $forge = unpack('v1', substr($item->{cards}, 2, 2));
		if (exists $starcrumbdisplay{my $starCrumbs = ($forge >> 8) / 5}) {
			$starcrumb = getTranslation($starcrumbdisplay{$starCrumbs});
		}
		$creator = getCreatorName(substr($item->{cards}, 4, 4), $item);
		if (exists $elementdisplay{my $elementID = $forge % 10}) {
			$element = getTranslation($elementdisplay{$elementID});
		}
		if ($config{'roItem_nameFormat'} eq 'bRO') {
			$suffix .= (($element ne '') ? " $element" : '') .
					(($starcrumb ne '') ? " $starcrumb" : '') .
					(($creator ne '') ? " $creator" : '');
		} else {
			$prefix .= (($starcrumb ne '') ? "$starcrumb " : '') .
					(($creator ne '') ? "${creator}'s " : '') .
					(($element ne '') ? "$element " : '');
		}
	} else {
		my %cards;
		my @cards;
		my $cards = 0;
		for (my $i = 0; $i < 4; $i++) {
			my $cardID = unpack("v1", substr($item->{cards}, $i*2, 2));
			last unless $cardID;
			$cards++;
			push @cards, $cardID if (!$cards{$cardID});
			($cards{$cardID} ||= 0) += 1;
		}
		if ($cards) {
			# Carded item
			foreach (@cards) {
				if (exists $cardprefixname{$_}) {
					if (exists $cardpostfixname{$_} || $cardprefixname{$_} =~ /^of /) {
						$suffix .= ' ' . $cardprefixname{$_};
						$suffix .= ' ' . getTranslation($cardmultiplier{$cards{$_}}) if ($cards{$_} > 1);
					} else {
						$prefix .= getTranslation($cardmultiplier{$cards{$_}}) . ' ' if ($cards{$_} > 1);
						$prefix .= $cardprefixname{$_} . ' ';
					}
				}
			}
		} elsif ($item->{type} == 4 && unpack('v1', substr($item->{cards}, 6, 2)) == 1) {
			$prefix .= getTranslation('Beloved') . ' ';
		}
		$numSlots = $itemslotcount{$item->{nameID}};
	}


	my $display = "";
	$display .= getTranslation('BROKEN') . ' ' if ($item->{broken});
	$display .= "+$item->{upgrade} " if ($item->{upgrade});
	$display .= $prefix . $name . $suffix;
	$display .= " [$numSlots]" if ($numSlots);

	return $display;
}

# ============================
# Misc.pm Override Functions
# ============================
# Licensed by hakore (hakore@users.sourceforge.net) under GPL
#
package Misc;

use strict;

sub itemNameSimple {
	return ROItem::itemNameSimple(shift);
}

sub itemName {
	return ROItem::itemName(shift);
}
# re use Misc everywhere so the new function is used

package main;
use Misc;
package Commands;
use Misc;
package Network::Receive;
use Misc;

return 1;
translations.txt

Code: Select all

# This file contains translation constants
# to be used by the 'rodata' plugin
# format: <constant> TAB(S) <replacement>

# Starcrumb display
Very Strong					Very Strong
Very Very Strong			Very Very Strong
Very Very Very Strong		Very Very Very Strong

# Element display
Ice							Ice
Earth						Earth
Fire						Fire
Wind						Wind

# Temporary name used while creator names
# are not yet received from the server
Nameless					Nameless

# Card multiplier display
Double						Double
Triple						Triple
Quadruple					Quadruple

# Description used for named pet eggs
Beloved						Beloved

# Broken status
BROKEN						BROKEN
Whatever...

h4rry84
Moderators
Moderators
Posts: 234
Joined: 04 Apr 2008, 09:30
Noob?: Yes
Location: My House
Contact:

Re: ROItem Plugin: Display item names based on the RO client

#2 Post by h4rry84 »

anyone still have this plugin for backup ?

t3quila
Noob
Noob
Posts: 4
Joined: 11 May 2009, 05:31
Noob?: Yes

Re: ROItem Plugin: Display item names based on the RO client

#3 Post by t3quila »

Yes Right! Need for re-upload this plugins..
This is more important for me and all about separate Alchemist's Potion names..
Thx before to mr.hakore for re-upload great idea things
~~~
Above all power above all kings
Above all nature and All Created things
Above all wisdom and all the ways a man
You were her before The World begin
~~~

hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

Re: ROItem Plugin: Display item names based on the RO client

#4 Post by hakore »

We're lucky someone used this plugin and uploaded it to a public svn repository. Updated the first post.
Whatever...

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: ROItem Plugin: Display item names based on the RO client

#5 Post by EternalHarvest »

hakore wrote:a public svn repository
Where is it?

hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

Re: ROItem Plugin: Display item names based on the RO client

#6 Post by hakore »

Googled "roitem.pl svn"
Whatever...

Post Reply