Compare commits
21 Commits
7111e62193
...
master
Author | SHA1 | Date | |
---|---|---|---|
34a83bd71e | |||
2d4257b010 | |||
55c5952258 | |||
652bd5fe1a | |||
14e21b2e4b | |||
88221039bb | |||
e986454f80 | |||
805453d90c | |||
1a417c8bcf | |||
29a54f8e89 | |||
40ce9dcb81 | |||
b7ecc1e6b5 | |||
a6097ae400 | |||
03ea64b021 | |||
334ffbfa48 | |||
f7de2290cb | |||
4957ade96f | |||
db9a4bbe59 | |||
efa20e6421 | |||
89471db285 | |||
24355357ec |
@ -32,15 +32,18 @@ void RefreshBlocks() {
|
||||
auto pluginmaptype = cast<CGameEditorPluginMapMapType>(cast<CGameCtnEditorFree>(GetApp().Editor).PluginMapType);
|
||||
|
||||
for(uint i = 0; i < blocks.Length; i++) {
|
||||
int idifexist = -1;
|
||||
string blockname;
|
||||
string blockname = blocks[i].BlockModel.IdName;
|
||||
int fallbacksize = 0;
|
||||
bool isofficial = true;
|
||||
blockname = blocks[i].BlockModel.IdName;
|
||||
if (blockname.ToLower().SubStr(blockname.Length - 22, 22) == ".block.gbx_customblock") {
|
||||
isofficial = false;
|
||||
blockname = blockname.SubStr(0, blockname.Length - 12);
|
||||
|
||||
auto article = cast<CGameCtnArticle>(blocks[i].BlockInfo.ArticlePtr);
|
||||
fallbacksize = article.BlockItem_ItemModelArticle.CollectorFid.ByteSize;
|
||||
}
|
||||
|
||||
|
||||
if (include_default_objects || blockname.ToLower().SubStr(blockname.Length - 10, 10) == ".block.gbx") {
|
||||
vec3 pos;
|
||||
if (blocks[i].CoordX != 4294967295 && blocks[i].CoordZ != 4294967295) { // Not placed in free mapping
|
||||
@ -52,7 +55,8 @@ void RefreshBlocks() {
|
||||
pos.z = blocks[i].CoordZ * 32 + 16;
|
||||
}
|
||||
} else {
|
||||
pos = Dev::GetOffsetVec3(blocks[i], 0x6c);
|
||||
uint16 offset = Reflection::GetType("CGameCtnBlock").GetMember("Dir").Offset + 0x8;
|
||||
pos = Dev::GetOffsetVec3(blocks[i], offset);
|
||||
// center the coordinates in the middle of the block
|
||||
pos.x += 16;
|
||||
pos.y += 4;
|
||||
@ -66,7 +70,7 @@ void RefreshBlocks() {
|
||||
objects[index].positions.InsertLast(pos);
|
||||
} else {
|
||||
int trigger = blocks[i].BlockModel.EdWaypointType;
|
||||
AddNewObject(blockname, trigger, "Block", pos, 0, isofficial);
|
||||
AddNewObject(blockname, trigger, "Block", pos, fallbacksize, isofficial);
|
||||
objectsindex.InsertLast(blockname);
|
||||
}
|
||||
}
|
||||
@ -83,7 +87,6 @@ void RefreshItems() {
|
||||
// Items
|
||||
auto items = map.AnchoredObjects;
|
||||
for(uint i = 0; i < items.Length; i++) {
|
||||
int idifexist = -1;
|
||||
string itemname = items[i].ItemModel.IdName;
|
||||
int fallbacksize = 0;
|
||||
bool isofficial = true;
|
||||
@ -93,10 +96,9 @@ void RefreshItems() {
|
||||
auto article = cast<CGameCtnArticle>(items[i].ItemModel.ArticlePtr);
|
||||
if (article !is null) {
|
||||
itemname = string(article.PageName) + string(article.Name) + ".Item.Gbx";
|
||||
} else {
|
||||
auto fid = cast<CSystemFidFile@>(GetFidFromNod(items[i].ItemModel));
|
||||
fallbacksize = fid.ByteSize;
|
||||
}
|
||||
auto fid = cast<CSystemFidFile@>(GetFidFromNod(items[i].ItemModel));
|
||||
fallbacksize = fid.ByteSize;
|
||||
}
|
||||
|
||||
if (include_default_objects || itemname.ToLower().SubStr(itemname.Length - 9, 9) == ".item.gbx") {
|
||||
@ -173,10 +175,8 @@ void AddNewObject(const string &in objectname, int trigger, const string &in typ
|
||||
bool FocusCam(const string &in objectname) {
|
||||
auto editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
auto camera = editor.OrbitalCameraControl;
|
||||
auto map = GetApp().RootMap;
|
||||
|
||||
|
||||
if (camera !is null) {
|
||||
if (camera !is null) {
|
||||
int index = objectsindex.Find(objectname);
|
||||
|
||||
camerafocusindex++;
|
||||
@ -187,8 +187,11 @@ bool FocusCam(const string &in objectname) {
|
||||
|
||||
camera.m_TargetedPosition = objects[index].positions[camerafocusindex];
|
||||
// Workaround to update camera TargetedPosition
|
||||
auto m_ParamScrollZoomPowe = camera.m_ParamScrollZoomPower;
|
||||
camera.m_ParamScrollZoomPower = 0;
|
||||
editor.ButtonZoomInOnClick();
|
||||
editor.ButtonZoomOutOnClick();
|
||||
camera.m_ParamScrollZoomPower = m_ParamScrollZoomPowe;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -3,5 +3,5 @@ name = "Blocks & Items Counter"
|
||||
author = "Beu"
|
||||
category = "Map Editor"
|
||||
siteid = 97
|
||||
version = "1.5"
|
||||
version = "1.7"
|
||||
blocks = [ "Plugin_Blocks&ItemsCounter" ]
|
||||
|
9
CountdownMover/info.toml
Normal file
9
CountdownMover/info.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[meta]
|
||||
name = "Countdown Mover"
|
||||
author = "Beu"
|
||||
category = "Overlay"
|
||||
version = "1.3"
|
||||
siteid = 431
|
||||
|
||||
[script]
|
||||
dependencies = ["MLHook"]
|
104
CountdownMover/main.as
Normal file
104
CountdownMover/main.as
Normal file
@ -0,0 +1,104 @@
|
||||
[Setting name="Countdown Position"]
|
||||
vec2 Setting_CountdownOffset = vec2(155. , 4.);
|
||||
|
||||
const string C_Class_UIModules = 'component-cmgame-uimodules-module';
|
||||
const string C_Id_Countdown = 'Race_Countdown';
|
||||
|
||||
const string C_MLID_UIModuleUpdate = 'MLHook_CustomizableModule';
|
||||
const string C_ML_UIModuleUpdate = """
|
||||
main() {
|
||||
declare netread Integer Net_LibUI3_CustomizableModule_PropertiesUpdate for Teams[0];
|
||||
declare Integer Last_PropertiesUpdate;
|
||||
while (True) {
|
||||
yield;
|
||||
|
||||
if (Last_PropertiesUpdate != Net_LibUI3_CustomizableModule_PropertiesUpdate) {
|
||||
Last_PropertiesUpdate = Net_LibUI3_CustomizableModule_PropertiesUpdate;
|
||||
SendCustomEvent("MLHook_CustomizableModule_Update", []);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
class HookCustomizableModuleEvents: MLHook::HookMLEventsByType {
|
||||
HookCustomizableModuleEvents() {
|
||||
super(C_MLID_UIModuleUpdate);
|
||||
}
|
||||
|
||||
void OnEvent(MLHook::PendingEvent@ Event) override {
|
||||
trace("CustomizableModule updated");
|
||||
G_Update = true;
|
||||
}
|
||||
}
|
||||
|
||||
HookCustomizableModuleEvents@ HookEvents = null;
|
||||
string G_Last_ServerLogin = "";
|
||||
uint G_Last_UILayers_Length = 0;
|
||||
CGameManialinkControl@ G_Control;
|
||||
bool G_Update;
|
||||
|
||||
// Search and return the CMlFrame of the Race_Countdown UIModule
|
||||
CGameManialinkControl@ GetControl(CGameManiaAppPlayground@ _ManiaApp) {
|
||||
for (uint Index = 0; Index < _ManiaApp.UILayers.Length; ++Index) {
|
||||
CGameUILayer@ Layer = _ManiaApp.UILayers[Index];
|
||||
CGameManialinkPage@ Page = Layer.LocalPage;
|
||||
|
||||
// Check if we have the main UI module
|
||||
Page.GetClassChildren(C_Class_UIModules, Page.MainFrame, true);
|
||||
|
||||
if (Page.GetClassChildren_Result.Length > 0) {
|
||||
if (Page.GetClassChildren_Result[0].ControlId == C_Id_Countdown) {
|
||||
return Page.GetClassChildren_Result[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
print("Layer not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
void OnSettingsChanged() {
|
||||
trace("Settings updated");
|
||||
G_Update = true;
|
||||
}
|
||||
|
||||
void Main() {
|
||||
@HookEvents = HookCustomizableModuleEvents();
|
||||
MLHook::RegisterMLHook(HookEvents, C_MLID_UIModuleUpdate + "_Update", true);
|
||||
MLHook::InjectManialinkToPlayground(C_MLID_UIModuleUpdate, C_ML_UIModuleUpdate, true);
|
||||
|
||||
while(true) {
|
||||
CTrackMania@ App = cast<CTrackMania>(GetApp());
|
||||
CTrackManiaNetwork@ Network = cast<CTrackManiaNetwork>(App.Network);
|
||||
CTrackManiaNetworkServerInfo@ ServerInfo = cast<CTrackManiaNetworkServerInfo>(Network.ServerInfo);
|
||||
CGameManiaAppPlayground@ ManiaApp = Network.ClientManiaAppPlayground;
|
||||
|
||||
if (Network !is null && ServerInfo !is null && ManiaApp !is null) {
|
||||
if (G_Last_ServerLogin != ServerInfo.ServerLogin || G_Last_UILayers_Length != ManiaApp.UILayers.Length) {
|
||||
trace("Server or UILayers updated");
|
||||
G_Last_ServerLogin = ServerInfo.ServerLogin;
|
||||
G_Last_UILayers_Length = ManiaApp.UILayers.Length;
|
||||
@G_Control = GetControl(ManiaApp);
|
||||
G_Update = true;
|
||||
}
|
||||
|
||||
if (G_Control !is null && G_Update) {
|
||||
G_Update = false;
|
||||
G_Control.RelativePosition_V3 = Setting_CountdownOffset;
|
||||
}
|
||||
} else {
|
||||
G_Last_ServerLogin = "";
|
||||
G_Last_UILayers_Length = 0;
|
||||
@G_Control = null;
|
||||
G_Update = true;
|
||||
}
|
||||
|
||||
sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroyed() { _Unload(); }
|
||||
void OnDisabled() { _Unload(); }
|
||||
void _Unload() {
|
||||
trace('_Unload, unloading all hooks and removing all injected ML');
|
||||
MLHook::UnregisterMLHooksAndRemoveInjectedML();
|
||||
}
|
9
DuplicateFinder/info.toml
Normal file
9
DuplicateFinder/info.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[meta]
|
||||
name = "DuplicateFinder"
|
||||
author = "Beu"
|
||||
category = "Map Editor"
|
||||
version = "1.1"
|
||||
siteid = 220
|
||||
|
||||
[script]
|
||||
timeout = 0
|
302
DuplicateFinder/main.as
Normal file
302
DuplicateFinder/main.as
Normal file
@ -0,0 +1,302 @@
|
||||
class Objects { //Items or Blocks
|
||||
string name;
|
||||
string type;
|
||||
int count;
|
||||
vec3 position;
|
||||
vec3 rotation;
|
||||
Objects(string name, string type, vec3 pos, vec3 rot ) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.count = 2; // Object if added only if duplicate
|
||||
this.position = pos;
|
||||
this.rotation = rot;
|
||||
}
|
||||
}
|
||||
|
||||
enum ESortColumn {
|
||||
ItemName,
|
||||
Count
|
||||
}
|
||||
|
||||
const float pi = 3.14159265359;
|
||||
|
||||
bool include_default_blocks;
|
||||
bool menu_visibility = false;
|
||||
bool refreshobject;
|
||||
|
||||
bool sort_reverse;
|
||||
bool forcesort;
|
||||
string infotext;
|
||||
|
||||
array<Objects@> objects = {};
|
||||
array<Objects@> sortableobjects = {};
|
||||
array<string> objectsindex = {};
|
||||
|
||||
int totalobjects;
|
||||
int computedobjects;
|
||||
|
||||
ESortColumn sortCol = ESortColumn(-1);
|
||||
|
||||
void Main() {
|
||||
while (true) {
|
||||
if (refreshobject) {
|
||||
objects.Resize(0);
|
||||
objectsindex.Resize(0);
|
||||
sortableobjects.Resize(0);
|
||||
RefreshBlocksAndItems();
|
||||
sortableobjects = objects;
|
||||
refreshobject = false;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
// Force to split the refresh functions to bypass the script execution delay on heavy maps
|
||||
void RefreshBlocksAndItems() {
|
||||
auto map = GetApp().RootMap;
|
||||
dictionary singleobjectdico = {};
|
||||
|
||||
if (map !is null) {
|
||||
totalobjects = map.Blocks.Length + map.AnchoredObjects.Length;
|
||||
computedobjects = 0;
|
||||
|
||||
// Blocks
|
||||
auto blocks = map.Blocks;
|
||||
|
||||
// Editor plugin API for GetVec3FromCoord function
|
||||
auto pluginmaptype = cast<CGameEditorPluginMapMapType>(cast<CGameCtnEditorFree>(GetApp().Editor).PluginMapType);
|
||||
|
||||
for(uint i = 0; i < blocks.Length; i++) {
|
||||
if (i % 1000 == 0) yield(); // to avoid timeout
|
||||
computedobjects++;
|
||||
|
||||
string blockname;
|
||||
blockname = blocks[i].BlockModel.IdName;
|
||||
if (blockname.ToLower().SubStr(blockname.Length - 22, 22) == ".block.gbx_customblock") blockname = blockname.SubStr(0, blockname.Length - 12);
|
||||
|
||||
vec3 pos;
|
||||
vec3 rot;
|
||||
if (blocks[i].CoordX != 4294967295 && blocks[i].CoordZ != 4294967295) { // Not placed in free mapping
|
||||
if (!include_default_blocks) continue;
|
||||
if (pluginmaptype !is null) { // Editor plugin is available
|
||||
pos = pluginmaptype.GetVec3FromCoord(blocks[i].Coord);
|
||||
} else {
|
||||
pos.x = blocks[i].CoordX * 32;
|
||||
pos.y = (blocks[i].CoordY - 8) * 8;
|
||||
pos.z = blocks[i].CoordZ * 32;
|
||||
}
|
||||
switch(blocks[i].BlockDir) {
|
||||
case CGameCtnBlock::ECardinalDirections::East:
|
||||
rot.x = 90;
|
||||
break;
|
||||
case CGameCtnBlock::ECardinalDirections::South:
|
||||
rot.x = 180;
|
||||
break;
|
||||
case CGameCtnBlock::ECardinalDirections::West:
|
||||
rot.x = 270;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
uint16 FreeBlockPosOffset = Reflection::GetType("CGameCtnBlock").GetMember("Dir").Offset + 0x8;
|
||||
uint16 FreeBlockRotOffset = FreeBlockPosOffset + 0xC;
|
||||
|
||||
pos = Dev::GetOffsetVec3(blocks[i], FreeBlockPosOffset);
|
||||
rot = Dev::GetOffsetVec3(blocks[i], FreeBlockRotOffset) / pi * 180;
|
||||
}
|
||||
|
||||
string uniqueid = pos.x + ";" + pos.y + ";" + pos.z + ";;" + rot.x + ";" + rot.y + ";" + rot.z + ";;"+ blockname;
|
||||
|
||||
if (singleobjectdico.Exists(uniqueid)) {
|
||||
int index = objectsindex.Find(uniqueid);
|
||||
if (index >= 0) {
|
||||
objects[index].count++;
|
||||
} else {
|
||||
objects.InsertLast(Objects(blockname, "Block", pos, rot));
|
||||
objectsindex.InsertLast(uniqueid);
|
||||
}
|
||||
} else {
|
||||
singleobjectdico.Set(uniqueid, 0);
|
||||
}
|
||||
}
|
||||
singleobjectdico.DeleteAll();
|
||||
|
||||
auto items = map.AnchoredObjects;
|
||||
|
||||
for(uint i = 0; i < items.Length; i++) {
|
||||
if (i % 1000 == 0) yield(); // to avoid timeout
|
||||
computedobjects++;
|
||||
|
||||
string itemname = items[i].ItemModel.IdName;
|
||||
|
||||
vec3 pos = items[i].AbsolutePositionInMap;
|
||||
vec3 rot;
|
||||
rot.x = items[i].Yaw;
|
||||
rot.y = items[i].Pitch;
|
||||
rot.z = items[i].Roll;
|
||||
|
||||
string uniqueid = pos.x + ";" + pos.y + ";" + pos.z + ";;" + rot.x + ";" + rot.y + ";" + rot.z + ";;"+ itemname;
|
||||
|
||||
if (singleobjectdico.Exists(uniqueid)) {
|
||||
int index = objectsindex.Find(uniqueid);
|
||||
if (index >= 0) {
|
||||
objects[index].count++;
|
||||
} else {
|
||||
objects.InsertLast(Objects(itemname, "Item", pos, rot));
|
||||
objectsindex.InsertLast(uniqueid);
|
||||
}
|
||||
} else {
|
||||
singleobjectdico.Set(uniqueid, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FocusCam(vec3 position) {
|
||||
auto editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
auto camera = editor.OrbitalCameraControl;
|
||||
auto map = GetApp().RootMap;
|
||||
|
||||
|
||||
if (camera !is null) {
|
||||
camera.m_TargetedPosition = position;
|
||||
// Workaround to update camera TargetedPosition
|
||||
auto m_ParamScrollZoomPowe = camera.m_ParamScrollZoomPower;
|
||||
camera.m_ParamScrollZoomPower = 0;
|
||||
editor.ButtonZoomInOnClick();
|
||||
camera.m_ParamScrollZoomPower = m_ParamScrollZoomPowe;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GenerateRow(Objects@ object) {
|
||||
if (object.count <= 1) return;
|
||||
UI::TableNextRow();
|
||||
UI::TableNextColumn();
|
||||
if (UI::Button(Icons::Search + "###Search;" + object.position.x + ";" + object.position.y + ";" + object.position.z)) {
|
||||
FocusCam(object.position);
|
||||
}
|
||||
if (UI::IsItemHovered() && cast<CGameEditorPluginMapMapType>(cast<CGameCtnEditorFree>(GetApp().Editor).PluginMapType) is null) infotext = "Editor plugins are disabled, the coordinates of the blocks are estimated and can be imprecise";
|
||||
UI::SameLine();
|
||||
UI::Text(object.name);
|
||||
UI::TableNextColumn();
|
||||
UI::Text(object.type);
|
||||
UI::TableNextColumn();
|
||||
UI::Text("<" + object.position.x + ", " + object.position.y + ", " + object.position.z +">");
|
||||
UI::TableNextColumn();
|
||||
UI::Text("<" + object.rotation.x + ", " + object.rotation.y + ", " + object.rotation.z +">");
|
||||
UI::TableNextColumn();
|
||||
UI::Text(Text::Format("%lld",object.count));
|
||||
}
|
||||
|
||||
void Render() {
|
||||
if (!menu_visibility) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGameCtnEditorFree@ editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().RootMap);
|
||||
|
||||
if (map is null && editor is null) {
|
||||
menu_visibility = false;
|
||||
return;
|
||||
}
|
||||
|
||||
infotext = "";
|
||||
|
||||
UI::SetNextWindowSize(600, 400);
|
||||
UI::SetNextWindowPos(200, 200, UI::Cond::Once);
|
||||
UI::Begin("\\$cf9" + Icons::Table + "\\$z DuplicateFinder###DuplicateFinder", menu_visibility);
|
||||
if (editor !is null) {
|
||||
if (refreshobject) {
|
||||
if (Time::get_Now() % 3000 > 2000) {
|
||||
UI::Button("Loading...");
|
||||
} else if (Time::get_Now() % 3000 > 1000) {
|
||||
UI::Button("Loading.. ");
|
||||
} else {
|
||||
UI::Button("Loading. ");
|
||||
}
|
||||
if (UI::IsItemHovered()) infotext = "Parsing all blocks and items to generate the table. Please wait... (" + computedobjects + "/" + totalobjects + ")";
|
||||
} else {
|
||||
if (UI::Button(Icons::Refresh + " Refresh")) {
|
||||
refreshobject = true;
|
||||
forcesort = true;
|
||||
}
|
||||
}
|
||||
UI::SameLine();
|
||||
include_default_blocks = UI::Checkbox("Include Blocks not placed in Free Mapping", include_default_blocks);
|
||||
UI::Separator();
|
||||
vec2 winsize = UI::GetWindowSize();
|
||||
winsize.x = winsize.x - 10;
|
||||
winsize.y = winsize.y - 105;
|
||||
if (UI::BeginTable("DuplicateBlocksTable", 5, UI::TableFlags(UI::TableFlags::Resizable | UI::TableFlags::Sortable | UI::TableFlags::NoSavedSettings | UI::TableFlags::BordersInnerV | UI::TableFlags::SizingStretchProp | UI::TableFlags::ScrollY),winsize )) {
|
||||
UI::TableSetupScrollFreeze(0, 1);
|
||||
UI::TableSetupColumn("Block Name", UI::TableColumnFlags::None, 40.f, ESortColumn::ItemName);
|
||||
UI::TableSetupColumn("Type", UI::TableColumnFlags::NoSort, 10.f);
|
||||
UI::TableSetupColumn("Position", UI::TableColumnFlags::NoSort, 20.f);
|
||||
UI::TableSetupColumn("Rotation", UI::TableColumnFlags::NoSort, 20.f);
|
||||
UI::TableSetupColumn("Count", UI::TableColumnFlags::DefaultSort, 10.f, ESortColumn::Count);
|
||||
UI::TableHeadersRow();
|
||||
|
||||
UI::TableSortSpecs@ sortSpecs = UI::TableGetSortSpecs();
|
||||
if(sortSpecs !is null && sortSpecs.Specs.Length == 1 && sortableobjects.Length > 1) {
|
||||
if(sortSpecs.Dirty || (forcesort && !refreshobject)) {
|
||||
if(sortCol != ESortColumn(sortSpecs.Specs[0].ColumnUserID) || (forcesort && !refreshobject)) {
|
||||
sortCol = ESortColumn(sortSpecs.Specs[0].ColumnUserID);
|
||||
switch(sortCol) {
|
||||
case ESortColumn::ItemName:
|
||||
sortableobjects.Sort(function(a,b) { return a.name < b.name; });
|
||||
break;
|
||||
case ESortColumn::Count:
|
||||
sortableobjects.Sort(function(a,b) { return a.count < b.count; });
|
||||
break;
|
||||
}
|
||||
if (forcesort && sort_reverse) {
|
||||
sortableobjects.Reverse();
|
||||
} else {
|
||||
sort_reverse = false;
|
||||
}
|
||||
} else if (sortCol == ESortColumn(sortSpecs.Specs[0].ColumnUserID)) {
|
||||
sortableobjects.Reverse();
|
||||
sort_reverse = !sort_reverse;
|
||||
}
|
||||
|
||||
sortSpecs.Dirty = false;
|
||||
forcesort = false;
|
||||
}
|
||||
}
|
||||
if (sortableobjects.Length > 0 ) {
|
||||
for(uint i = 0; i < sortableobjects.Length; i++) {
|
||||
GenerateRow(sortableobjects[i]);
|
||||
}
|
||||
} else {
|
||||
for(uint i = 0; i < objects.Length; i++) {
|
||||
GenerateRow(objects[i]);
|
||||
}
|
||||
}
|
||||
UI::EndTable();
|
||||
UI::Separator();
|
||||
UI::Text(Icons::Info + " " + infotext);
|
||||
}
|
||||
} else {
|
||||
UI::Text("Open this plugin in the map editor");
|
||||
}
|
||||
UI::End();
|
||||
|
||||
}
|
||||
|
||||
void RenderMenu() {
|
||||
CGameCtnEditorFree@ editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().RootMap);
|
||||
|
||||
if (map is null && editor is null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(UI::MenuItem("\\$cf9" + Icons::Table + "\\$z DuplicateFinder", "", menu_visibility)) {
|
||||
menu_visibility = !menu_visibility;
|
||||
refreshobject = true;
|
||||
}
|
||||
}
|
30
MapValidator/Source/Games/MP4.as
Normal file
30
MapValidator/Source/Games/MP4.as
Normal file
@ -0,0 +1,30 @@
|
||||
#if MP4
|
||||
CGameCtnEditorFree@ getEditor() {
|
||||
return cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
}
|
||||
|
||||
CGameCtnChallenge@ getMap() {
|
||||
return cast<CGameCtnChallenge>(GetApp().RootMap);;
|
||||
}
|
||||
|
||||
uint getAuthorTime(CGameCtnChallenge@ _Map) {
|
||||
return _Map.TMObjective_AuthorTime;
|
||||
}
|
||||
|
||||
void setAuthorTime(CGameCtnChallenge@ _Map, uint _AuthorTime) {
|
||||
_Map.TMObjective_AuthorTime = _AuthorTime;
|
||||
|
||||
// Remove the map UID, the game will generate it again when saving
|
||||
_Map.IdName = "";
|
||||
}
|
||||
|
||||
void setValidationStatus(CGameCtnEditorFree@ _Editor) {
|
||||
CGameEditorPluginMapMapType@ pluginmaptype = cast<CGameEditorPluginMapMapType>(_Editor.PluginMapType);
|
||||
if (pluginmaptype is null) return;
|
||||
pluginmaptype.ValidationStatus = CGameEditorPluginMapMapType::EValidationStatus::Validated;
|
||||
}
|
||||
|
||||
string GetWarning() {
|
||||
return "";
|
||||
}
|
||||
#endif
|
27
MapValidator/Source/Games/TMNEXT.as
Normal file
27
MapValidator/Source/Games/TMNEXT.as
Normal file
@ -0,0 +1,27 @@
|
||||
#if TMNEXT
|
||||
CGameCtnEditorFree@ getEditor() {
|
||||
return cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
}
|
||||
|
||||
CGameCtnChallenge@ getMap() {
|
||||
return cast<CGameCtnChallenge>(GetApp().RootMap);;
|
||||
}
|
||||
|
||||
uint getAuthorTime(CGameCtnChallenge@ _Map) {
|
||||
return _Map.TMObjective_AuthorTime;
|
||||
}
|
||||
|
||||
void setAuthorTime(CGameCtnChallenge@ _Map, uint _AuthorTime) {
|
||||
_Map.TMObjective_AuthorTime = _AuthorTime;
|
||||
}
|
||||
|
||||
void setValidationStatus(CGameCtnEditorFree@ _Editor) {
|
||||
CGameEditorPluginMapMapType@ pluginmaptype = cast<CGameEditorPluginMapMapType>(_Editor.PluginMapType);
|
||||
if (pluginmaptype is null) return;
|
||||
pluginmaptype.ValidationStatus = CGameEditorPluginMapMapType::EValidationStatus::Validated;
|
||||
}
|
||||
|
||||
string GetWarning() {
|
||||
return "";
|
||||
}
|
||||
#endif
|
30
MapValidator/Source/Games/TURBO.as
Normal file
30
MapValidator/Source/Games/TURBO.as
Normal file
@ -0,0 +1,30 @@
|
||||
#if TURBO
|
||||
CGameCtnEditorFree@ getEditor() {
|
||||
return cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
}
|
||||
|
||||
CGameCtnChallenge@ getMap() {
|
||||
return cast<CGameCtnChallenge>(GetApp().Challenge);
|
||||
}
|
||||
|
||||
uint getAuthorTime(CGameCtnChallenge@ _Map) {
|
||||
return _Map.TMObjective_AuthorTime;
|
||||
}
|
||||
|
||||
void setAuthorTime(CGameCtnChallenge@ _Map, uint _AuthorTime) {
|
||||
_Map.TMObjective_AuthorTime = _AuthorTime;
|
||||
|
||||
// Remove the map UID, the game will generate it again when saving
|
||||
_Map.IdName = "";
|
||||
}
|
||||
|
||||
void setValidationStatus(CGameCtnEditorFree@ _Editor) {
|
||||
CGameCtnEditorPluginMapType@ pluginmaptype = cast<CGameCtnEditorPluginMapType>(_Editor.EditorMapType);
|
||||
if (pluginmaptype is null) return;
|
||||
pluginmaptype.ValidationStatus = CGameCtnEditorPluginMapType::EValidationStatus::Validated;
|
||||
}
|
||||
|
||||
string GetWarning() {
|
||||
return "Note: your map must have a start and a finish\n(or a multilap + 1CP) to be validated with the plugin";
|
||||
}
|
||||
#endif
|
32
MapValidator/Source/Games/UNITED.as
Normal file
32
MapValidator/Source/Games/UNITED.as
Normal file
@ -0,0 +1,32 @@
|
||||
#if UNITED
|
||||
CTrackManiaEditor@ getEditor() {
|
||||
return cast<CTrackManiaEditor>(cast<CTrackMania>(GetApp()).Editor);
|
||||
}
|
||||
|
||||
CGameCtnChallenge@ getMap() {
|
||||
return cast<CGameCtnChallenge>(GetApp().Challenge);
|
||||
}
|
||||
|
||||
uint getAuthorTime(CGameCtnChallenge@ _Map) {
|
||||
return _Map.ChallengeParameters.AuthorTime;
|
||||
}
|
||||
|
||||
void setAuthorTime(CGameCtnChallenge@ _Map, uint _AuthorTime) {
|
||||
_Map.ChallengeParameters.AuthorTime = _AuthorTime;
|
||||
_Map.ChallengeParameters.AuthorScore = _AuthorTime;
|
||||
_Map.ChallengeParameters.GoldTime = Math::Floor((1000 + _AuthorTime + _AuthorTime * 0.06)/1000)*1000;
|
||||
_Map.ChallengeParameters.SilverTime = Math::Floor((1000 + _AuthorTime + _AuthorTime * 0.2)/1000)*1000;
|
||||
_Map.ChallengeParameters.BronzeTime = Math::Floor((1000 + _AuthorTime + _AuthorTime * 0.5)/1000)*1000;
|
||||
|
||||
// Remove the map UID, the game will generate it again when saving
|
||||
_Map.IdName = "";
|
||||
}
|
||||
|
||||
void setValidationStatus(CTrackManiaEditor@ _Editor) {
|
||||
return; // doesn't exists in UNITED
|
||||
}
|
||||
|
||||
string GetWarning() {
|
||||
return "Note: for an unknown reason, it happens that the times of\nthe medals are not updated, I invite you to check by yourself";
|
||||
}
|
||||
#endif
|
@ -1,128 +1,109 @@
|
||||
// Based on the Moski plugin which is also based on the Miss plugin :)
|
||||
|
||||
bool menu_visibility = false;
|
||||
int author_time;
|
||||
const string C_InvalidValueError = "Invalid value. You can set a human readable value like \\$<\\$aaa1:23.456\\$>\nor a value in milliseconds like \\$<\\$aaa83456\\$>";
|
||||
|
||||
void Main() {}
|
||||
bool G_MenuVisibility = false;
|
||||
string G_AuthorTimeText = "0:00:00.000";
|
||||
|
||||
void validate(int author_time) {
|
||||
// Get editor var
|
||||
#if UNITED
|
||||
CTrackManiaEditor@ editor = cast<CTrackManiaEditor>(cast<CTrackMania>(GetApp()).Editor);
|
||||
#else
|
||||
CGameCtnEditorFree@ editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
#endif
|
||||
|
||||
// Get map & pluginmaptype if possible
|
||||
#if TURBO
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().Challenge);
|
||||
CGameCtnEditorPluginMapType@ pluginmaptype = cast<CGameCtnEditorPluginMapType>(editor.EditorMapType);
|
||||
#elif UNITED
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().Challenge);
|
||||
auto pluginmaptype == null;
|
||||
#else
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().RootMap);
|
||||
CGameEditorPluginMapMapType@ pluginmaptype = cast<CGameEditorPluginMapMapType>(editor.PluginMapType);
|
||||
#endif
|
||||
|
||||
if (editor is null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pluginmaptype !is null) {
|
||||
#if TURBO
|
||||
pluginmaptype.ValidationStatus = CGameCtnEditorPluginMapType::EValidationStatus::Validated;
|
||||
#else
|
||||
pluginmaptype.ValidationStatus = CGameEditorPluginMapMapType::EValidationStatus::Validated;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (map !is null) {
|
||||
#if UNITED
|
||||
map.ChallengeParameters.AuthorTime = author_time;
|
||||
map.ChallengeParameters.AuthorScore = author_time;
|
||||
map.ChallengeParameters.GoldTime = Math::Floor((1000 + author_time + author_time * 0.06)/1000)*1000;
|
||||
map.ChallengeParameters.SilverTime = Math::Floor((1000 + author_time + author_time * 0.2)/1000)*1000;
|
||||
map.ChallengeParameters.BronzeTime = Math::Floor((1000 + author_time + author_time * 0.5)/1000)*1000;
|
||||
#else
|
||||
map.TMObjective_AuthorTime = author_time;
|
||||
#endif
|
||||
|
||||
#if !TMNEXT
|
||||
map.IdName = ""; // Remove the map UID, the game will generate it again when saving
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void Main() {}
|
||||
|
||||
void Render() {
|
||||
if (!menu_visibility) {
|
||||
auto editor = getEditor();
|
||||
if (editor is null) {
|
||||
G_MenuVisibility = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto map = getMap();
|
||||
if (map is null) {
|
||||
G_MenuVisibility = false;
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITED
|
||||
CTrackManiaEditor@ editor = cast<CTrackManiaEditor>(cast<CTrackMania>(GetApp()).Editor);
|
||||
#else
|
||||
CGameCtnEditorFree@ editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
#endif
|
||||
|
||||
#if TMNEXT || MP4
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().RootMap);
|
||||
#else
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().Challenge);
|
||||
#endif
|
||||
|
||||
if (map is null || editor is null) {
|
||||
menu_visibility = false;
|
||||
if (!G_MenuVisibility) {
|
||||
// Store the last Author Time when hidden
|
||||
uint CurrentAuthorTime = getAuthorTime(map);
|
||||
if (CurrentAuthorTime < 4294967295) {
|
||||
G_AuthorTimeText = Time::Format(CurrentAuthorTime);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (UI::Begin("\\$cf9" + Icons::Flag + "\\$z Map Validator###MapValidator", menu_visibility, UI::WindowFlags::NoResize | UI::WindowFlags::AlwaysAutoResize | UI::WindowFlags::NoCollapse)){
|
||||
author_time = UI::InputInt("Author time in ms", author_time ,1);
|
||||
|
||||
if (author_time < 0) author_time = 0;
|
||||
|
||||
if (UI::Button("Validate")) {
|
||||
validate(author_time);
|
||||
menu_visibility = false;
|
||||
}
|
||||
|
||||
// Convert time in ms to humain readable time
|
||||
string display_time = Text::Format('%02d',(author_time / 1000 / 60) % 60) + ":" + Text::Format('%02d',(author_time / 1000) % 60) + "." + Text::Format('%03d',author_time % 1000);
|
||||
if (Math::Floor(author_time / 1000 / 60 / 60) > 0) {
|
||||
display_time = Text::Format('%d',author_time / 1000 / 60 / 60) + ":" + display_time;
|
||||
}
|
||||
UI::SetNextItemWidth(200.0);
|
||||
if (UI::Begin("\\$cf9" + Icons::Flag + "\\$z Map Validator###MapValidator", G_MenuVisibility, UI::WindowFlags::NoResize | UI::WindowFlags::AlwaysAutoResize | UI::WindowFlags::NoCollapse)){
|
||||
UI::SetNextItemWidth(100.0);
|
||||
G_AuthorTimeText = UI::InputText("###AuthorTimeText", G_AuthorTimeText);
|
||||
UI::SameLine();
|
||||
UI::Text("with " + display_time + " of author time");
|
||||
|
||||
#if TURBO
|
||||
UI::Text("Note: your map must have a start and a finish\n(or a multilap + 1CP) to be validated with the plugin");
|
||||
#elif UNITED
|
||||
UI::Text("Note: for an unknown reason, it happens that the times of\nthe medals are not updated, I invite you to check by yourself");
|
||||
#endif
|
||||
const bool IsMilliseconds = IsMillisecondsFormat(G_AuthorTimeText);
|
||||
const bool IsButtonDisabled = (!IsMilliseconds && !IsValidAuthorTime(G_AuthorTimeText));
|
||||
|
||||
UI::End();
|
||||
}
|
||||
// Creating group to be able to display the tooltip even when the button is disabled
|
||||
UI::BeginGroup();
|
||||
UI::BeginDisabled(IsButtonDisabled);
|
||||
if (UI::Button("Validate")) {
|
||||
int AuthorTime = 0;
|
||||
if (IsMilliseconds) AuthorTime = Text::ParseUInt(G_AuthorTimeText);
|
||||
else AuthorTime = Time::ParseRelativeTime(G_AuthorTimeText);
|
||||
|
||||
setAuthorTime(map, AuthorTime);
|
||||
setValidationStatus(editor);
|
||||
G_MenuVisibility = false;
|
||||
}
|
||||
UI::EndDisabled();
|
||||
UI::EndGroup();
|
||||
|
||||
// Time tooltip
|
||||
if (UI::IsItemHovered()) {
|
||||
UI::BeginTooltip();
|
||||
if (IsButtonDisabled) {
|
||||
UI::Text(C_InvalidValueError);
|
||||
} else if (IsMilliseconds) {
|
||||
UI::Text(Time::Format(Text::ParseUInt(G_AuthorTimeText)));
|
||||
} else {
|
||||
UI::Text("" + Time::ParseRelativeTime(G_AuthorTimeText) + " ms");
|
||||
}
|
||||
UI::EndTooltip();
|
||||
}
|
||||
|
||||
// Warning tooltip depending the game
|
||||
const string warning = GetWarning();
|
||||
if (warning != "") {
|
||||
UI::SameLine();
|
||||
UI::Text("\\$fa2" + Icons::Info);
|
||||
if (UI::IsItemHovered()) {
|
||||
UI::BeginTooltip();
|
||||
UI::Text(warning);
|
||||
UI::EndTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
UI::End();
|
||||
}
|
||||
|
||||
|
||||
void RenderMenu() {
|
||||
#if UNITED
|
||||
CTrackManiaEditor@ editor = cast<CTrackManiaEditor>(cast<CTrackMania>(GetApp()).Editor);
|
||||
#else
|
||||
CGameCtnEditorFree@ editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||
#endif
|
||||
auto editor = getEditor();
|
||||
if (editor is null) return;
|
||||
|
||||
#if TMNEXT || MP4
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().RootMap);
|
||||
#else
|
||||
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().Challenge);
|
||||
#endif
|
||||
auto map = getMap();
|
||||
if (map is null) return;
|
||||
|
||||
if (map is null || editor is null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(UI::MenuItem("\\$cf9" + Icons::Flag + "\\$z Map Validator", "", menu_visibility)) {
|
||||
menu_visibility = !menu_visibility;
|
||||
if(UI::MenuItem("\\$cf9" + Icons::Flag + "\\$z Map Validator", "", G_MenuVisibility)) {
|
||||
G_MenuVisibility = !G_MenuVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsMillisecondsFormat(string _AuthorTimeText) {
|
||||
return Regex::IsMatch(_AuthorTimeText, '\\d+');
|
||||
}
|
||||
|
||||
bool IsValidAuthorTime(string _AuthorTimeText) {
|
||||
if (!Regex::IsMatch(_AuthorTimeText, '[\\d\\.:]+')) {
|
||||
return false;
|
||||
}
|
||||
if (!Regex::IsMatch(_AuthorTimeText, '^(((((\\d+:)?[0-5])?\\d:)?[0-5])?\\d)\\.\\d{3}$')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
[meta]
|
||||
name = "Map Validator"
|
||||
author = "Beu"
|
||||
category = "Map Editor"
|
||||
|
||||
siteid = 91
|
||||
version = "1.6"
|
||||
|
||||
blocks = [ "Plugin_MapValidator" ]
|
||||
[meta]
|
||||
name = "Map Validator"
|
||||
author = "Beu"
|
||||
category = "Map Editor"
|
||||
siteid = 91
|
||||
version = "1.8"
|
||||
blocks = [ "Plugin_MapValidator" ]
|
||||
|
||||
|
@ -1,26 +1,98 @@
|
||||
bool menu_visibility = false;
|
||||
string quickURL;
|
||||
[Setting name="Number of links saved in cache"]
|
||||
uint S_NbOfLinksInCache = 5;
|
||||
|
||||
void Main() {}
|
||||
const string C_LinksCache = "LinksCache.txt";
|
||||
|
||||
void Render() {
|
||||
if (!menu_visibility) {
|
||||
return;
|
||||
}
|
||||
UI::Begin("\\$cf9" + Icons::ExternalLinkAlt + "\\$z Quick Link Opener###Quick Link Opener", menu_visibility, UI::WindowFlags::NoResize | UI::WindowFlags::AlwaysAutoResize | UI::WindowFlags::NoCollapse);
|
||||
quickURL = UI::InputText("", quickURL);
|
||||
UI::SameLine();
|
||||
if (UI::Button(Icons::ExternalLinkAlt + " Go !###QuickURL")) {
|
||||
string parsedURL = Regex::Replace(quickURL,'uplay:\\/\\/launch\\/5595\\/0\\/','maniaplanet://');
|
||||
CTrackMania@ app = cast<CTrackMania>(GetApp());
|
||||
app.ManiaPlanetScriptAPI.OpenLink(parsedURL, CGameManiaPlanetScriptAPI::ELinkType::ManialinkBrowser);
|
||||
menu_visibility = false;
|
||||
}
|
||||
UI::End();
|
||||
}
|
||||
bool G_PermissionIssueNotified = false;
|
||||
string G_QuickURL = "";
|
||||
bool G_PressEnter = false;
|
||||
bool G_WasEditing = false;
|
||||
|
||||
void RenderMenu() {
|
||||
if(UI::MenuItem("\\$cf9" + Icons::ExternalLinkAlt + "\\$z Quick Link Opener", "", menu_visibility)) {
|
||||
menu_visibility = !menu_visibility;
|
||||
array<string> G_LinksCache;
|
||||
|
||||
void Main() {
|
||||
if (!hasPermissions()) return;
|
||||
|
||||
trace("Loading links cache");
|
||||
string filepath = IO::FromStorageFolder(C_LinksCache);
|
||||
IO::File file(filepath);
|
||||
|
||||
file.Open(IO::FileMode::Read);
|
||||
while(!file.EOF()) {
|
||||
G_LinksCache.InsertLast(file.ReadLine());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderMenuMain() {
|
||||
if (!hasPermissions()) return;
|
||||
|
||||
if (!G_PressEnter && UI::BeginMenu("\\$cf9" + Icons::ExternalLink + "\\$z Quick Link Opener##QuickLinkOpenerMenu")) {
|
||||
G_QuickURL = UI::InputText("###quickURL", G_QuickURL, G_PressEnter, UI::InputTextFlags::EnterReturnsTrue + UI::InputTextFlags::CallbackAlways, UI::InputTextCallback(ITCB));
|
||||
|
||||
if (G_LinksCache.Length > 0) {
|
||||
UI::Separator();
|
||||
|
||||
for(uint i = 0; i < G_LinksCache.Length; i++ ) {
|
||||
if (UI::MenuItem(G_LinksCache[i] + "###" + i)) {
|
||||
LoadLink(G_LinksCache[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UI::EndMenu();
|
||||
} else if (G_PressEnter || G_WasEditing) {
|
||||
G_PressEnter = false;
|
||||
G_WasEditing = false;
|
||||
LoadLink(G_QuickURL, true);
|
||||
G_QuickURL = "";
|
||||
}
|
||||
}
|
||||
|
||||
void ITCB(UI::InputTextCallbackData@ d) {
|
||||
G_WasEditing = true;
|
||||
}
|
||||
|
||||
void LoadLink(string _Url, bool _NewUrl) {
|
||||
if (!hasPermissions()) return;
|
||||
if (_Url == "") return;
|
||||
|
||||
string parsedURL = "";
|
||||
if (_NewUrl) {
|
||||
parsedURL = Regex::Replace(_Url,'uplay:\\/\\/launch\\/5595\\/0\\/','maniaplanet://');
|
||||
|
||||
G_LinksCache.InsertAt(0, parsedURL);
|
||||
|
||||
// Clear cache if too long
|
||||
if (G_LinksCache.Length > S_NbOfLinksInCache) {
|
||||
G_LinksCache.RemoveRange(S_NbOfLinksInCache, G_LinksCache.Length - S_NbOfLinksInCache);
|
||||
}
|
||||
|
||||
// Compute text for the cache file
|
||||
string content;
|
||||
for(uint i = 0; i < G_LinksCache.Length; i++ ) {
|
||||
content = content + G_LinksCache[i] + "\n";
|
||||
}
|
||||
|
||||
trace("Writing links cache");
|
||||
string filepath = IO::FromStorageFolder(C_LinksCache);
|
||||
IO::File file(filepath, IO::FileMode::Write);
|
||||
file.Write(content);
|
||||
} else {
|
||||
parsedURL = _Url;
|
||||
}
|
||||
|
||||
CTrackMania@ app = cast<CTrackMania>(GetApp());
|
||||
app.ManiaPlanetScriptAPI.OpenLink(parsedURL, CGameManiaPlanetScriptAPI::ELinkType::ManialinkBrowser);
|
||||
}
|
||||
|
||||
bool hasPermissions() {
|
||||
if (Permissions::PlayPublicClubRoom()) return true;
|
||||
|
||||
if (!G_PermissionIssueNotified) {
|
||||
G_PermissionIssueNotified = true;
|
||||
string msg = "Missing permissions: you need to be able to play on public room to use this plugin.";
|
||||
warn(msg);
|
||||
UI::ShowNotification(Meta::ExecutingPlugin().Name, msg, vec4(.9, .5, .3, .2), 15000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
ݹ<><DDB9><EFBFBD>g<EFBFBD><67><EFBFBD> ǁ<EFBFBD><EFBFBD>ӛ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>J<06>%<1A>]<06>J_<4A>P<EFBFBD><50>ah<61><68><0F>5<08>'NN<4E>Z<EFBFBD>2<><32>r<EFBFBD><72>T<EFBFBD>
|
@ -4,11 +4,6 @@ author = "Beu"
|
||||
category = "Utilities"
|
||||
|
||||
siteid = 101
|
||||
version = "1.1"
|
||||
|
||||
perms = "paid"
|
||||
version = "2.0"
|
||||
|
||||
blocks = [ "Plugin_QuickLinkOpener" ]
|
||||
|
||||
[script]
|
||||
imports = [ "Icons.as" ]
|
Binary file not shown.
@ -1,4 +1,6 @@
|
||||
[meta]
|
||||
name = "TMWT Interfaces Remover"
|
||||
category = "TMWT"
|
||||
version = "1.1"
|
||||
[meta]
|
||||
name = "TMWT Interfaces Remover"
|
||||
category = "TMWT"
|
||||
version = "1.4"
|
||||
siteid = 318
|
||||
|
||||
|
@ -1,16 +1,31 @@
|
||||
bool InterfacesAreHidden;
|
||||
bool HideInterfaces;
|
||||
string Last_ServerLogin;
|
||||
CGameUILayer@ UILayer_LiveRanking;
|
||||
CGameUILayer@ UILayer_TeamsScores;
|
||||
const string C_Class_UIModules = 'component-cmgame-uimodules-module';
|
||||
const string C_Id_TMWT_LiveRanking = 'TMWTCommon_LiveRanking';
|
||||
const string C_Id_TMWT_Header = 'TMWTCommon_Header';
|
||||
const string C_Id_TMWC2023_LiveRanking = 'TMWC2023_LiveRanking';
|
||||
const string C_Id_TMWC2023_Header = 'TMWC2023_Header';
|
||||
|
||||
|
||||
bool G_InterfacesAreHidden;
|
||||
bool G_HideInterfaces;
|
||||
string G_Last_ServerLogin;
|
||||
CGameUILayer@ G_UILayer_LiveRanking;
|
||||
CGameUILayer@ G_UILayer_TeamsScores;
|
||||
|
||||
void OnSettingsChanged() {
|
||||
trace("Settings updated");
|
||||
@G_UILayer_LiveRanking = null;
|
||||
@G_UILayer_TeamsScores = null;
|
||||
G_InterfacesAreHidden = false;
|
||||
}
|
||||
|
||||
|
||||
void RenderMenu() {
|
||||
if(UI::MenuItem("\\$77d" + Icons::User + " \\$fffTMWT Interfaces Remover", "", HideInterfaces)) {
|
||||
if(UI::MenuItem("\\$77d" + Icons::User + " \\$fffTMWT Interfaces Remover", "", G_HideInterfaces)) {
|
||||
auto app = cast<CTrackMania>(GetApp());
|
||||
auto network = cast<CTrackManiaNetwork>(app.Network);
|
||||
auto serverinfo = cast<CTrackManiaNetworkServerInfo>(network.ServerInfo);
|
||||
if (network !is null && serverinfo !is null && serverinfo.ServerLogin != "") {
|
||||
HideInterfaces = !HideInterfaces;
|
||||
G_HideInterfaces = !G_HideInterfaces;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -32,17 +47,20 @@ bool IsPlaying() {
|
||||
}
|
||||
|
||||
CGameUILayer@ findUILayer(const MwFastBuffer<CGameUILayer@> _UILayers, string _ManialinkId) {
|
||||
for (uint i = 0; i < _UILayers.Length; i++) {
|
||||
string manialink = _UILayers[i].ManialinkPage;
|
||||
auto firstlines = manialink.Split("\n", 5);
|
||||
if (firstlines.Length > 0) {
|
||||
for (uint j = 0; j < firstlines.Length - 1; j++) {
|
||||
if (firstlines[j].Contains(_ManialinkId)) {
|
||||
return _UILayers[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint Index = 0; Index < _UILayers.Length; ++Index) {
|
||||
CGameUILayer@ Layer = _UILayers[Index];
|
||||
CGameManialinkPage@ Page = Layer.LocalPage;
|
||||
|
||||
// Check if we have the main UI module
|
||||
Page.GetClassChildren(C_Class_UIModules, Page.MainFrame, true);
|
||||
|
||||
if (Page.GetClassChildren_Result.Length > 0) {
|
||||
if (Page.GetClassChildren_Result[0].ControlId == _ManialinkId) {
|
||||
return _UILayers[Index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -54,55 +72,58 @@ void Main() {
|
||||
auto serverinfo = cast<CTrackManiaNetworkServerInfo>(network.ServerInfo);
|
||||
|
||||
if (network !is null && serverinfo !is null) {
|
||||
if (Last_ServerLogin != serverinfo.ServerLogin) {
|
||||
Last_ServerLogin = serverinfo.ServerLogin;
|
||||
@UILayer_LiveRanking = null;
|
||||
@UILayer_TeamsScores = null;
|
||||
HideInterfaces = false;
|
||||
InterfacesAreHidden = false;
|
||||
if (G_Last_ServerLogin != serverinfo.ServerLogin) {
|
||||
G_Last_ServerLogin = serverinfo.ServerLogin;
|
||||
@G_UILayer_LiveRanking = null;
|
||||
@G_UILayer_TeamsScores = null;
|
||||
G_HideInterfaces = false;
|
||||
G_InterfacesAreHidden = false;
|
||||
}
|
||||
|
||||
// Prevent to continue the loop when not needed
|
||||
if (!HideInterfaces && !InterfacesAreHidden) continue;
|
||||
if (!G_HideInterfaces && !G_InterfacesAreHidden) continue;
|
||||
|
||||
CGameManiaAppPlayground@ ManiaApp = cast<CGameManiaAppPlayground>(network.ClientManiaAppPlayground);
|
||||
if (ManiaApp !is null) {
|
||||
if (UILayer_LiveRanking is null) {
|
||||
@UILayer_LiveRanking = findUILayer(ManiaApp.UILayers, "UIModule_TMWTCommon_LiveRanking");
|
||||
if (G_UILayer_LiveRanking is null) {
|
||||
if (Setting_GameMode == GameMode::TMWT) @G_UILayer_LiveRanking = findUILayer(ManiaApp.UILayers, C_Id_TMWT_LiveRanking);
|
||||
else if (Setting_GameMode == GameMode::TMWC2023) @G_UILayer_LiveRanking = findUILayer(ManiaApp.UILayers, C_Id_TMWC2023_LiveRanking);
|
||||
}
|
||||
if (UILayer_TeamsScores is null) {
|
||||
@UILayer_TeamsScores = findUILayer(ManiaApp.UILayers, "UIModule_TMWTCommon_Header");
|
||||
if (G_UILayer_TeamsScores is null) {
|
||||
if (Setting_GameMode == GameMode::TMWT) @G_UILayer_TeamsScores = findUILayer(ManiaApp.UILayers, C_Id_TMWT_Header);
|
||||
else if (Setting_GameMode == GameMode::TMWC2023) @G_UILayer_TeamsScores = findUILayer(ManiaApp.UILayers, C_Id_TMWC2023_Header);
|
||||
}
|
||||
if (UILayer_TeamsScores is null && UILayer_LiveRanking is null) {
|
||||
if (G_UILayer_TeamsScores is null && G_UILayer_LiveRanking is null) {
|
||||
UI::ShowNotification("\\$77d" + Icons::User + " \\$fffTMWT Interfaces Remover", "Can't find Interfaces to hide, disabling the plugin");
|
||||
HideInterfaces = false;
|
||||
InterfacesAreHidden = false;
|
||||
G_HideInterfaces = false;
|
||||
G_InterfacesAreHidden = false;
|
||||
}
|
||||
if (HideInterfaces && !InterfacesAreHidden && IsPlaying() ) {
|
||||
if (HideLiveRanking && UILayer_LiveRanking !is null) {
|
||||
UILayer_LiveRanking.IsVisible = false;
|
||||
if (G_HideInterfaces && !G_InterfacesAreHidden && IsPlaying() ) {
|
||||
if (HideLiveRanking && G_UILayer_LiveRanking !is null) {
|
||||
G_UILayer_LiveRanking.IsVisible = false;
|
||||
}
|
||||
if (HideTeamsScores && UILayer_TeamsScores !is null) {
|
||||
UILayer_TeamsScores.IsVisible = false;
|
||||
if (HideTeamsScores && G_UILayer_TeamsScores !is null) {
|
||||
G_UILayer_TeamsScores.IsVisible = false;
|
||||
}
|
||||
InterfacesAreHidden = true;
|
||||
} else if (InterfacesAreHidden && (!HideInterfaces || !IsPlaying())) {
|
||||
if (UILayer_LiveRanking !is null) {
|
||||
UILayer_LiveRanking.IsVisible = true;
|
||||
G_InterfacesAreHidden = true;
|
||||
} else if (G_InterfacesAreHidden && (!G_HideInterfaces || !IsPlaying())) {
|
||||
if (G_UILayer_LiveRanking !is null) {
|
||||
G_UILayer_LiveRanking.IsVisible = true;
|
||||
}
|
||||
if (UILayer_TeamsScores !is null) {
|
||||
UILayer_TeamsScores.IsVisible = true;
|
||||
if (G_UILayer_TeamsScores !is null) {
|
||||
G_UILayer_TeamsScores.IsVisible = true;
|
||||
}
|
||||
InterfacesAreHidden = false;
|
||||
G_InterfacesAreHidden = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Last_ServerLogin = "";
|
||||
HideInterfaces = false;
|
||||
InterfacesAreHidden = false;
|
||||
@UILayer_LiveRanking = null;
|
||||
@UILayer_TeamsScores = null;
|
||||
G_Last_ServerLogin = "";
|
||||
G_HideInterfaces = false;
|
||||
G_InterfacesAreHidden = false;
|
||||
@G_UILayer_LiveRanking = null;
|
||||
@G_UILayer_TeamsScores = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,13 @@
|
||||
enum GameMode {
|
||||
TMWT,
|
||||
TMWC2023,
|
||||
}
|
||||
|
||||
[Setting category="Interfaces" name="Game mode"]
|
||||
GameMode Setting_GameMode = GameMode::TMWT;
|
||||
|
||||
[Setting category="Interfaces" name="Hide Live Ranking"]
|
||||
bool HideLiveRanking = true;
|
||||
|
||||
[Setting category="Interfaces" name="Hide Teams Scores"]
|
||||
bool HideTeamsScores = true;
|
||||
bool HideTeamsScores = true;
|
||||
|
@ -1,5 +1,6 @@
|
||||
[meta]
|
||||
name = "TMWT Screen Remover"
|
||||
category = "TMWT"
|
||||
version = "1.2"
|
||||
siteid = 183
|
||||
[meta]
|
||||
name = "TMWT Screen Remover"
|
||||
category = "TMWT"
|
||||
version = "1.4"
|
||||
siteid = 183
|
||||
|
||||
|
@ -42,7 +42,7 @@ void Main() {
|
||||
auto firstlines = manialink.Split("\n", 5);
|
||||
if (firstlines.Length > 0) {
|
||||
for (uint j = 0; j < firstlines.Length - 1; j++) {
|
||||
if (firstlines[j].Contains("UIModule_TMWTTeams_Sign")) {
|
||||
if (firstlines[j].Contains("UIModule_TMWTCommon_Sign")) {
|
||||
maniaapp.UILayerDestroy(uilayers[i]);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user