Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Earthfiredrake committed Mar 14, 2017
2 parents 7616780 + 704ed81 commit 63279f9
Show file tree
Hide file tree
Showing 12 changed files with 764 additions and 112 deletions.
8 changes: 7 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017 Earthfiredrake
LoreHound copyright (c) 2017 Earthfiredrake

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -19,3 +19,9 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

TSW-AddonUtils library & UITweaks mod
Copyright (c) 2015 eltorqiro
Released under the MIT license
https://github.com/eltorqiro/TSW-Utils
https://github.com/eltorqiro/TSW-UITweaks
Binary file modified LoreHound.fla
Binary file not shown.
44 changes: 37 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,31 @@ Notifications for each group can be output to either the System Chat, or as FIFO
Any packaged releases can be installed by copying the contents into [Game Directory]\Data\Gui\Flash\Customized, and restarting the client.
If upgrading from v0.1.1.alpha, a clean reinstall is recommended. Remove the existing mod entirely and login to the game to clear any existing settings before installing a more recent version.

## Changelog
Version 0.5.0-beta
+ New responses to lore pickups that don't connect to anything (formerly "Unable to identify")
+ Partially intialized drops will be poked until they shape up
+ Disabled event lore flagged as such
+ Told to ignore inactive event lore (new option: default ignores)
+ Icon no longer superglued to screen without topbar mod, works with GUI edit mode
+ Refuses to hide, but can be made into a very small puppy
+ Now more vocal, notification on icon when tracking lore drops or when a debug report is ready
+ Topbars cause shrinkage, but it's still there
+ Unknown lore id count: 10

Version 0.4.0-beta
+ First open beta release
+ Learned a new trick, now identifies lore with topic and entry #
+ Suborned the postal service into serving as an automated bug report system (opt-in)
+ Settings GUI added w/ Topbar integration, disillusioning debug menu of its supposed popularity
+ Unknown lore id count: 15

Version 0.1.1-alpha
+ Proof of concept
+ Grumpy dog has unfriendly info format and no GUI access to settings
+ Unknown lore id count: 26

## Known Issues
+ If not using a topbar replacement, the icon cannot be moved or hidden
+ In the player account settings file, the IconPosition record in the LoreHoundConfig archive can be manually changed while the game is not running to change this location.
+ Setting both x and y values to -32 should position the icon completely off the screen
+ Drop lores may not have the topic and entry # immediately available.
+ Stepping away (more than 20m) and reapproaching the lore should cause it to be properly identified
+ German users may see a number of false positive detections, due to wide use of "Wissen" in names
+ Disabling the unknown lore category will remove the spam (as well as any accurate detections)

Expand All @@ -41,7 +60,18 @@ Copyright (c) 2017 Earthfiredrake

Software and source released under the MIT License

Uses the TSW-AddonUtils library and graphical elements from the UI_Tweaks mod

Both Copyright (c) 2015 eltorqiro and used under the terms of the MIT License

https://github.com/eltorqiro/TSW-Utils

https://github.com/eltorqiro/TSW-UITweaks

TSW, the related API, and most graphics elements are products of Funcom
LoreHound icon developed from game graphics (sourced from TSWDB) and http://www.iconninja.com/basset-hound-dog-head-icon-843075

Special Thanks to Vomher for help identifying some magic numbers
LoreHound icon developed from game graphics (sourced from TSWDB) and http://www.iconninja.com/basset-hound-dog-head-icon-843075

Special Thanks to:
The TSW modder community for neglecting to secure various tutorials, code and other commentary in their faction vault
Vomher for help identifying some magic numbers
119 changes: 82 additions & 37 deletions efd/LoreHound/LoreHound.as
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
// Released under the terms of the MIT License
// https://github.com/Earthfiredrake/TSW-LoreHound

import flash.geom.Point;

import gfx.utils.Delegate;

import com.GameInterface.Chat;
import com.GameInterface.Dynels;
import com.GameInterface.Game.Character;
Expand Down Expand Up @@ -59,9 +63,10 @@ class efd.LoreHound.LoreHound extends Mod {
/// General mod overrides

public function LoreHound(hostMovie:MovieClip) {
super("LoreHound", "v0.4.0.beta", "ReleaseTheLoreHound", hostMovie);
super("LoreHound", "0.5.0.beta", "ReleaseTheLoreHound", hostMovie);
// DebugTrace = true;
m_AutoReport = new AutoReport(ModName, Version, DevName); // Initialized first so that its Config is available to be nested
m_AutoReport.SignalReportsSent.Connect(this, UpdateIcon);

LoadConfig();
UpdateInstall();
Expand All @@ -82,8 +87,6 @@ class efd.LoreHound.LoreHound extends Mod {
// Character teleported also triggers on anima leaps and agartha teleports, while character destructed seems to only trigger when changing zones
// (of course teleports often trigger out of range destructions.)
Character.GetClientCharacter().SignalCharacterDestructed.Connect(ClearTracking, this);

ChatMsg("Is on the prowl.");
}

private function InitializeConfig():Void {
Expand Down Expand Up @@ -124,6 +127,16 @@ class efd.LoreHound.LoreHound extends Mod {
var autoRepConfig:ConfigWrapper = Config.GetValue("AutoReport");
autoRepConfig.SetValue("ReportsSent", CleanReportArray(autoRepConfig.GetValue("ReportsSent"), function(id) { return id; }));
autoRepConfig.SetValue("ReportQueue", CleanReportArray(autoRepConfig.GetValue("ReportQueue"), function(report) { return report.id; }));

// Version specific updates
if (oldVersion == "v0.4.0.beta") {
// Point support added to ConfigWrapper, and position settings were updated accordingly
// Also the last version to have the "v" embedded in the version string
var oldPoint = Config.GetValue("ConfigWindowPosition");
Config.SetValue("ConfigWindowPosition", new Point(oldPoint.x, oldPoint.y));
oldPoint = Config.GetValue("IconPosition");
Config.SetValue("IconPosition", new Point(oldPoint.x, oldPoint.y));
}
}

private function CleanReportArray(array:Array, extractor:Function):Array {
Expand Down Expand Up @@ -151,6 +164,21 @@ class efd.LoreHound.LoreHound extends Mod {
super.Deactivate();
}

private function UpdateIcon():Void {
if (Enabled) {
for (var key:String in m_TrackedLore) {
// Only need to know if there are one or more items being tracked
ModIcon.gotoAndStop("alerted");
return;
}
if (m_AutoReport.IsEnabled() && m_AutoReport.HasReportsPending()) {
ModIcon.gotoAndStop("reporting");
return;
}
}
super.UpdateIcon();
}

// Notes on Dynel API:
// GetName() - Actually a remoteformat xml tag, for the LDB localization system
// Has a type attribute with a value usually 50200 and an id value which is used for categorization
Expand Down Expand Up @@ -182,8 +210,10 @@ class efd.LoreHound.LoreHound extends Mod {
// Testing unclaimed lore with alts did not demonstrate any notable differences in the reported stats

/// Lore detection (callback for dynel detection)
private function LoreSniffer(dynelId:ID32):Void {
private function LoreSniffer(dynelId:ID32, repeat:Number):Void {
if (dynelId.m_Type != e_DynelType_Object && !m_DebugVerify) { return; }
if (repeat == undefined) { repeat = 0; }
else { TraceMsg("In repeat: " + repeat + " Dynel: " + dynelId); }

var dynel:Dynel = Dynel.GetDynel(dynelId);
var dynelName:String = dynel.GetName();
Expand All @@ -198,25 +228,35 @@ class efd.LoreHound.LoreHound extends Mod {
if (loreType == ef_LoreType_Unknown || dynelId.m_Type != e_DynelType_Object) {
loreType = CheckLocalizedName(dynelName) ? ef_LoreType_Unknown : ef_LoreType_None;
}
var loreId:Number = dynel.GetStat(e_Stats_LoreId, 2);
if (loreType == ef_LoreType_Drop) { // Track dropped lore so that notifications can be made on despawn
if (m_TrackedLore[dynelId.toString()] == undefined) {
// Don't care about the value, but the request enables DynelGone triggers
Dynels.RegisterProperty(dynelId.m_Type, dynelId.m_Instance, _global.enums.Property.e_ObjPos);
}
// Refresh this, in case it failed to identify at first
m_TrackedLore[dynelId.toString()] = loreId;
TraceMsg("Now tracking lore drop: " + AttemptIdentification(loreId, loreType, categorizationId, dynelName));
}
if ((loreType == ef_LoreType_Common || categorizationId == c_ShroudedLoreCategory) && (loreId == undefined || loreId == 0) && Config.GetValue("IgnoreOffSeasonLore")) {
loreType = ef_LoreType_None;
TraceMsg("Off season lore ignored.")
}
if (loreType != ef_LoreType_Unknown && loreId != undefined && loreId != 0 && Lore.IsLocked(loreId) && Config.GetValue("IgnoreUnclaimedLore")) {
loreType = ef_LoreType_None;
TraceMsg("Unclaimed lore ignored.");
}
if (loreType != ef_LoreType_None) {
var loreId:Number = dynel.GetStat(e_Stats_LoreId, 2);
if (loreId == 0) {
TraceMsg("ID == 0");
}
if (loreType == ef_LoreType_Drop) {
// Drops without a valid loreId should correct themselves quickly, retest after a short delay
if (repeat < 5 && loreId == 0) {
TraceMsg("Repeat for dynel: " + dynelId);
setTimeout(Delegate.create(this, LoreSniffer), 1, dynelId, repeat + 1);
return;
}
// Track dropped lore so that notifications can be made on despawn
if (m_TrackedLore[dynelId.toString()] == undefined) {
// Don't care about the value, but the request is required to get DynelGone events
Dynels.RegisterProperty(dynelId.m_Type, dynelId.m_Instance, _global.enums.Property.e_ObjPos);
m_TrackedLore[dynelId.toString()] = loreId;
UpdateIcon();
TraceMsg("Now tracking lore drop: " + AttemptIdentification(loreId, loreType, categorizationId, dynelName));
}
}
if ((loreType == ef_LoreType_Common || categorizationId == c_ShroudedLoreCategory) && loreId == 0 && Config.GetValue("IgnoreOffSeasonLore")) {
TraceMsg("Off season lore ignored.");
return;
}
if (loreType != ef_LoreType_Unknown && loreId != 0 && Lore.IsLocked(loreId) && Config.GetValue("IgnoreUnclaimedLore")) {
TraceMsg("Unclaimed lore ignored.");
return;
}
SendLoreNotifications(loreType, categorizationId, dynel);
}
}
Expand All @@ -238,7 +278,8 @@ class efd.LoreHound.LoreHound extends Mod {
);
DispatchMessages(ef_LoreType_Drop, -instance, messageStrings);
}
m_TrackedLore[despawnedId] = undefined;
delete m_TrackedLore[despawnedId];
UpdateIcon();
}
}

Expand All @@ -248,6 +289,7 @@ class efd.LoreHound.LoreHound extends Mod {
Dynels.UnregisterProperty(id[0], id[1], _global.enums.Property.e_ObjPos);
}
m_TrackedLore = new Object();
UpdateIcon();
TraceMsg("Player changed zones, tracked lore has been cleared.");
}

Expand All @@ -264,11 +306,11 @@ class efd.LoreHound.LoreHound extends Mod {
// - Lore in boardroom inaccessible (does not appear?) until after penthouse fight
// - Lore on penthouse balcony (spawns after fight)
return ef_LoreType_Common;
case 7648084: // Pol (Hidden zombie, after #1)
case 7648084: // Pol (Hidden zombie after #1)
// Pol (Drone spawn) is ??
case 7661215: // DW6 (Post boss lore spawn)
case 7648451: // Ankh (Orochi adds, after #1)
case 7648450: // Ankh (Mummy adds, after #3)
case 7648451: // Ankh (Orochi agent after #1)
case 7648450: // Ankh (Mummy adds after #3) (was this Ankh #5 or #8?)
case 7648449: // Ankh (Pit dwellers)
case 7647988: // HF6 (Post boss lore spawn)
case 7647983: // Fac6 (Post boss lore spawn)
Expand All @@ -277,6 +319,8 @@ class efd.LoreHound.LoreHound extends Mod {
case 7573298: // HE6 (Post boss lore spawn)
case 8507997: // CK carpark (HiE BS #1) spawns (on top floor) upon reaching bottom floor
case 8508000: // CK carpark (HiE BS #2) spawns after picking up the evidence
case 9125445: // MFA (Smiler mech after #5)
case 9125570: // MFA6 (Post boss lore spawn)
return ef_LoreType_Triggered;
case 8499259: // Hyper-Infected Citizen drop (Kaiden BS #3), very short timeout
case 8508040: // Behemoth of the Devouring Plague drop (The Wall BS#4) in KD, very short timeout
Expand All @@ -288,22 +332,21 @@ class efd.LoreHound.LoreHound extends Mod {
return ef_LoreType_Special;
default:
//Suspect IDs (from string dumps):
//7648452
//7653135
//8437788
//8437793
//8508014
//8508217
//8587691
//9125445
//9125570
//9241297
//7648452 // Likely Ankh #5 or #8
//7653135 // HR after machine tyrant?
//8437788 // Tokyo somewhere?
//8437793 // Tokyo somewhere?
//8508014 // Tokyo somewhere?
//8508217 // Tokyo somewhere?
//8587691 // Scrappy's deathspawn lore?
//9241297 // Somehow museum related?
// Am reasonably confident these two are Christmas event ones
// Probably the two in Niflheim (tree and boss death)
//8397678
//8397708
// Potential candidates to investigate:
// The Jinn and the First Age 1 (Faust Omega, "Knowledge" room)
// Ankh (5|8) and HR
// One or more IDs might be related to the full sets of event lore missing entirely
return ef_LoreType_Unknown;
}
Expand Down Expand Up @@ -407,7 +450,7 @@ class efd.LoreHound.LoreHound extends Mod {
}
// Shrouded Lore, amusingly, uniformly lacks the loreId field (due to being out of season?) and is the only type known to have an informative localized string.
if (categorizationId == c_ShroudedLoreCategory) {
return dynelName;
return "Inactive " + dynelName;
}
// Deal with the rest of the missing data
switch (loreType) {
Expand All @@ -421,6 +464,7 @@ class efd.LoreHound.LoreHound extends Mod {
return "Inactive event lore";
case ef_LoreType_Drop:
// Lore drops occasionally fail to completely load before they're detected, but usually succeed on second detection
// The only reason to see this now is if the automatic redetection system failed
return "Incomplete data, redetect";
default:
// Just in case
Expand Down Expand Up @@ -485,6 +529,7 @@ class efd.LoreHound.LoreHound extends Mod {
report += "\n" + detailStrings.join("\n");
}
m_AutoReport.AddReport({ id: categorizationId, text: report });
UpdateIcon();
}
}

Expand Down
12 changes: 10 additions & 2 deletions efd/LoreHound/lib/AutoReport.as
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
// Released under the terms of the MIT License
// https://github.com/Earthfiredrake/TSW-LoreHound

import gfx.utils.Delegate;

import com.GameInterface.DistributedValue;
import com.GameInterface.Game.Character;
import com.GameInterface.Tradepost;
import com.GameInterface.Utils;
import com.Utils.Signal;

import efd.LoreHound.lib.ConfigWrapper;

Expand Down Expand Up @@ -40,6 +43,9 @@ class efd.LoreHound.lib.AutoReport {
}
}

public function get HasReportsPending():Boolean { return m_Config.GetValue("QueuedReports").length > 0; }
public var SignalReportsSent:Signal;

// Mailing information
private var m_ModName:String;
private var m_ModVersion:String;
Expand All @@ -61,6 +67,7 @@ class efd.LoreHound.lib.AutoReport {
m_Config.NewSetting("QueuedReports", new Array());
m_Config.NewSetting("PriorReports", new Array());

SignalReportsSent = new Signal();
m_MailTrigger = DistributedValue.Create("tradepost_window");
IsEnabled = true;
}
Expand Down Expand Up @@ -114,7 +121,7 @@ class efd.LoreHound.lib.AutoReport {
// Failed to send, will delay and retry up to max attempts
m_ReportsSent = 0;
if (attempt < c_MaxRetries) {
setTimeout(SendReport, c_RetryDelay, attempt + 1);
setTimeout(Delegate.create(this, SendReport), c_RetryDelay, attempt + 1);
} else {
Utils.PrintChatText("<font color='#00FFFF'>" + m_ModName + "</font>: One or more automated reports failed to send and will remain queued.");
}
Expand All @@ -138,9 +145,10 @@ class efd.LoreHound.lib.AutoReport {
// Continue sending reports as needed
if (queue.length > 0) {
// Delay to avoid triggering flow restrictions
setTimeout(SendReport, c_RetryDelay, 0);
setTimeout(Delegate.create(this, SendReport), c_RetryDelay, 0);
} else {
Utils.PrintChatText("<font color='#00FFFF'>" + m_ModName + "</font>: All queued reports have been sent. Thank you for your assistance.");
SignalReportsSent.Emit();
}
} else {
// Reset index, and keep remaining reports to retry later
Expand Down
Loading

0 comments on commit 63279f9

Please sign in to comment.