Custom Elite Ranking and Legal Status system from dictionary
Posted: Wed Feb 05, 2014 9:14 pm
It's been asked a few times on the forums about making the Elite Ranking and Legal Statuses editable via an OXP. I had originally posted up in a different thread how this could be accomplished by adding extra arrays into the descriptions.plist file, but I have now discovered a much easier and tidier way of doing this - by creating a new ratings.plist file and having the data stored in there.
So, let's start at the beginning. First, open the file PlayerEntity.h in the source and go to line 1029 and replace that line with the following: Now open the NSStringOOExtensions.h file and add this at line 61: Now open the OOConstToString.h file and add this at line 106: Now open up the Universe.h file and first insert the following around line 248: And insert the following at around line 609: This takes care of the header files. Now, open the NSStringOOExtensions.m file and add the following at line 151: Now open the Universe.m file and first insert the following at around line 352: Then insert the following at around line 431: Then insert the following at around line 7154: And then insert the following at around line 9863: Now open the OOConstToString.m file and go to line 470. Insert the following here (do not replace anything yet, just insert this function): Now, go to line 589 and replace the section/function there with the following: Go down to line 604 and the replace the section/function there with the following: This takes care of the source files. Now, go to the resources folder and create a new plist file called ratings.plist and make sure it looks like the following: Finally, open up logcontrol.plist and add the following two lines: And there you have it, a way of creating new elite rankings and legal statuses via a new plist file. The line numbers quoted above may not be exact, but anyone with a small amount of knowledge of the source will be able to figure out what I mean!
There are limitations, such as they both have to start at 0 and cannot contain negative values (this will cause the game to fall back to the original system, which is now hardcoded). Also, there are certain commands (I'm thinking of the new Priority AI in particular here) that assume there are only three legal statuses. But for all intents and purposes this is how this could be accomplished...
So, let's start at the beginning. First, open the file PlayerEntity.h in the source and go to line 1029 and replace that line with the following:
Code: Select all
NSString *OODisplayStringFromLegalStatus(unsigned legalStatus);
Code: Select all
- (NSComparisonResult)oo_compareNumerically:(NSString *)str;
Code: Select all
NSString *OODisplayRatingsFromNumericalValue(NSString *context, unsigned inputNum);
Code: Select all
NSDictionary *ratings; // holds data for the elite rankings and legal status systems
Code: Select all
- (NSDictionary *) ratings;
Code: Select all
- (NSComparisonResult)oo_compareNumerically:(NSString *)str
{
NSNumber * num1 = [NSNumber numberWithInt:[self intValue]];
NSNumber * num2 = [NSNumber numberWithInt:[str intValue]];
return [num1 compare:num2];
}
Code: Select all
ratings = [[ResourceManager dictionaryFromFilesNamed:@"ratings.plist" inFolder:@"Config" andMerge:YES] retain];
Code: Select all
[ratings release];
Code: Select all
- (NSDictionary *) ratings
{
return ratings;
}
Code: Select all
[ratings autorelease];
ratings = [[ResourceManager dictionaryFromFilesNamed:@"ratings.plist" inFolder:@"Config" andMerge:YES] retain];
Code: Select all
NSString *OODisplayRatingsFromNumericalValue(NSString *context, unsigned inputNum)
{
NSMutableDictionary *ratingDict = [[NSMutableDictionary alloc] init];
NSString *ratingString;
NSArray *ratingKeys;
NSMutableArray *mutableRatingKeys = [[NSMutableArray alloc] init];
NSArray *sortedRatingKeys;
unsigned i;
int numInt;
BOOL customStringInvalid;
NSString *logKey;
[ratingDict addEntriesFromDictionary:[[UNIVERSE ratings] oo_dictionaryForKey:context]];
ratingKeys = [ratingDict allKeys];
customStringInvalid = NO;
numInt = 0;
logKey = @"_default";
if ([context isEqualToString:@"rankings"]) logKey = @"new.rankings.error";
if ([context isEqualToString:@"legal_status"]) logKey = @"new.legal.status.error";
for (i = 0; i < [ratingKeys count]; ++i)
{
ratingString = [NSString stringWithFormat:@"%u", [ratingKeys oo_intAtIndex:i]];
numInt = [ratingString integerValue];
if (numInt < 0)
{
customStringInvalid = YES;
OOLog(logKey, @"The '%@' dictionary in ratings.plist contains a negative value key - reverting to original system.", context);
break;
}
ratingString = [NSString stringWithFormat:@"%u", [ratingKeys oo_intAtIndex:i]];
[mutableRatingKeys addObject:ratingString];
}
sortedRatingKeys = [mutableRatingKeys sortedArrayUsingSelector:@selector(oo_compareNumerically:)];
if ([sortedRatingKeys oo_unsignedIntAtIndex:0] != 0 && !customStringInvalid)
{
customStringInvalid = YES;
OOLog(logKey, @"The value keys in the '%@' dictionary in ratings.plist do not start at 0 - reverting to original system.", context);
}
if (!customStringInvalid)
{
for (i = 0; i < [sortedRatingKeys count]; ++i)
{
if (inputNum < [sortedRatingKeys oo_unsignedIntAtIndex:i])
{
ratingString = [NSString stringWithFormat:@"%u", [sortedRatingKeys oo_unsignedIntAtIndex:i-1]];
if ([ratingDict objectForKey:ratingString] != nil)
{
return [ratingDict objectForKey:ratingString];
}
else
{
customStringInvalid = YES;
OOLog(logKey, @"'nil' value returned when trying to display %@ - reverting to original system.", context);
break;
}
}
}
}
if (customStringInvalid)
{
if ([context isEqualToString:@"rankings"])
{
enum { kRatingCount = 9 };
const unsigned killThresholds[kRatingCount - 1] =
{
0x0008,
0x0010,
0x0020,
0x0040,
0x0080,
0x0200,
0x0A00,
0x1900
};
NSString *eliteRating = [NSString stringWithUTF8String:"★★★ E L I T E ★★★"];
NSString *deadlyRating = [NSString stringWithUTF8String:"☆ Deadly ☆"];
NSArray *stringArray = [NSArray arrayWithObjects:@"Harmless",@"Mostly Harmless",@"Poor",@"Average",@"Above Average",@"Competent",@"Dangerous",deadlyRating,eliteRating,nil];
for (i = 0; i < kRatingCount - 1; ++i)
{
if (inputNum < killThresholds[i]) return [stringArray oo_stringAtIndex:i];
}
return [stringArray oo_stringAtIndex:kRatingCount - 1];
}
if ([context isEqualToString:@"legal_status"])
{
enum { kStatusCount = 3 };
const int statusThresholds[kStatusCount - 1] =
{
1,
51
};
NSArray *stringArray = [NSArray arrayWithObjects:@"Clean",@"Offender",@"Fugitive",nil];
for (i = 0; i != kStatusCount - 1; ++i)
{
if (inputNum < statusThresholds[i]) return [stringArray oo_stringAtIndex:i];
}
return [stringArray oo_stringAtIndex:kStatusCount - 1];
}
}
i = [sortedRatingKeys count] - 1;
ratingString = [NSString stringWithFormat:@"%u", [sortedRatingKeys oo_unsignedIntAtIndex:i]];
return [ratingDict objectForKey:ratingString];
}
Code: Select all
NSString *OODisplayRatingStringFromKillCount(unsigned kills)
{
NSString *contextType = @"rankings";
return [NSString stringWithFormat:@"%@", OODisplayRatingsFromNumericalValue(contextType, kills)];
}
Code: Select all
NSString *OODisplayStringFromLegalStatus(unsigned legalStatus)
{
NSString *contextType = @"legal_status";
return [NSString stringWithFormat:@"%@", OODisplayRatingsFromNumericalValue(contextType, legalStatus)];
}
Code: Select all
{
"rankings" =
{
"0" = "Harmless";
"8" = "Mostly Harmless";
"16" = "Poor";
"32" = "Average";
"64" = "Above Average";
"128" = "Competent";
"512" = "Dangerous";
"2560" = "☆ Deadly ☆";
"6400" = "★★★ E L I T E ★★★";
};
"legal_status" =
{
"0" = "Clean";
"1" = "Offender";
"51" = "Fugitive";
};
}
Code: Select all
new.rankings.error = yes;
new.legal.status.error = yes;
There are limitations, such as they both have to start at 0 and cannot contain negative values (this will cause the game to fall back to the original system, which is now hardcoded). Also, there are certain commands (I'm thinking of the new Priority AI in particular here) that assume there are only three legal statuses. But for all intents and purposes this is how this could be accomplished...