So I have a feeling my Lua knowledge has a SIGNIFICANT number of gaps. I was under the assumption that you can write functions but they're pretty useless without having something to call them. But the way Blizzard integrates Addons, it seems like the client automatically calls them and so I don't have to write in anything about it, which is incredibly confusing.
For example, here's an old addon I have that basically does nothing but /laughs at anyone who dies. Either I'm bad at Lua (which is probable), or this is entirely local functions with nothing to call them.
[code]-- Saved Variables
bAutoLaugh = true -- Indicates whether the addon should automatically laugh at morons
-- Globalish Variables
local nLastLaughTime = 0 -- Stores the time we last laughed at someone
-- Create an invisible frame to handle events
local frmEventFrame = CreateFrame("Frame")
-------------------------------------------------------------------------------------------------------------
-- Hook relevant events to the frame
-------------------------------------------------------------------------------------------------------------
frmEventFrame:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)
frmEventFrame:RegisterEvent("ADDON_LOADED")
frmEventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
frmEventFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
-------------------------------------------------------------------------------------------------------------
-- Event fired when an addon is loaded, any addon!
-------------------------------------------------------------------------------------------------------------
function frmEventFrame:ADDON_LOADED(event, ...)
-- Grab which addon was loaded
sAddonName = ...
-- If it was our addon save the current time
if (sAddonName == "AutoLaugh") then
nLastLaughTime = GetTime()
end
end
-------------------------------------------------------------------------------------------------------------
-- Event fired when the player enters combat
-------------------------------------------------------------------------------------------------------------
function frmEventFrame:PLAYER_REGEN_DISABLED(event, ...)
-- Begin monitoring the combat log for death events if the player has auto laughing turned on
if (bAutoLaugh == true) then
frmEventFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
end
-------------------------------------------------------------------------------------------------------------
-- Event fired when the player leaves combat
-------------------------------------------------------------------------------------------------------------
function frmEventFrame:PLAYER_REGEN_ENABLED(event, ...)
-- Stop monitoring the combat log for death events
frmEventFrame:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
end
-------------------------------------------------------------------------------------------------------------
-- Laugh at a newly dead player if the cooldown time has expired
-------------------------------------------------------------------------------------------------------------
function Laugh(sPlayerName)
-- Make sure at least ten seconds have passed and then laugh at the moron
local nCurrentTime = GetTime();
if (nCurrentTime - nLastLaughTime >= 10) then
DoEmote("laugh", sPlayerName)
nLastLaughTime = nCurrentTime
end
end
-------------------------------------------------------------------------------------------------------------
-- Event fired when a combat log entry is recieved
-------------------------------------------------------------------------------------------------------------
-- Predefine a bunch of useful variables so we aren't redefining them hundreds of times a second
_, sEventType, sDestName = 0, 0, 0
function frmEventFrame:COMBAT_LOG_EVENT_UNFILTERED(event, ...)
-- Grab information about the combat event
-- The type of event and the poor bastard it happened to is all we care about
_, sEventType, _, _, _, _, _, _, sDestName = ...
-- Figure out if the event is someone getting pasted
if (sEventType == "UNIT_DIED") then
-- Check to see if the unit that died is a player in our party or raid group and laugh at them
if (UnitInParty(sDestName) ~= nil) then
Laugh(sDestName)
elseif (UnitInRaid(sDestName) ~= nil) then
Laugh(sDestName)
end
end
end
-------------------------------------------------------------------------------------------------------------
-- Slash command to turn auto laughing on or off
-------------------------------------------------------------------------------------------------------------
SLASH_AUTOLAUGH1, SLASH_AUTOLAUGH2 = "/al", "/autolaugh"
local function AutoLaughSlash(msg, editbox)
if (msg == "on") then
bAutoLaugh = true
DEFAULT_CHAT_FRAME:AddMessage("Auto Laugh is On!")
elseif (msg == "off") then
bAutoLaugh = false
DEFAULT_CHAT_FRAME:AddMessage("Auto Laugh is Off!")
frmEventFrame:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
else
DEFAULT_CHAT_FRAME:AddMessage("Unknown Option! Use \"/al on\" or \"/al off\"")
end
end
SlashCmdList["AUTOLAUGH"] = AutoLaughSlash
[/code]
This works perfectly but I have no idea WHY.
I have a feeling I'm in over my head here.
Blizzard works with hooks. These are functions the client calls in scripts when something happened.
First, you register the hook to your addon's frame:
[code]frmEventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")[/code]
In this case, we're telling the client to alert us (and thus call the relevant function) when regeneration is disabled (and thus: combat is entered). More information on these events can be found on WoWwiki: [url]http://www.wowwiki.com/Events/Player[/url]
You define the relevant function in your code, the client calls it for you.
[code]function frmEventFrame:PLAYER_REGEN_ENABLED(event, ...)[/code]
I think I get it. So in the case of frmeventFrame:RegisterEvent("EVENT"), when that event occurs it will call frmEventFrame? That's...reasonable.
My biggest problem with shit like this is actually getting it started. Once I can get a barebones framework it's pretty quick. I don't even know if Blizzard will let me scan incoming whispers for keywords, but I suppose I can give it a shot.
[editline]15th July 2013[/editline]
Okay I think I'm starting to understand this. It's a little confusing but I'm not in much of a rush, so I'll get it.
[code]
-- a filter to hide all yelled messaged containing certain text
function noGoldSpam(self,event,msg)
local badWords = {"gold","%$","www","%.com","%.net","%.org"}
local matchCount = 0;
for _, word in ipairs(badWords) do
if (string.match(msg, word)) then
matchCount = matchCount + 1;
end
end
if (matchCount > 1) then
return true;
else
return false;
end
end
ChatFrame_AddMessageEventFilter("CHAT_MSG_YELL",noGoldSpam)
[/code]
^ The above should help.
That might help, yeah. Looks like it just checks for one instance of a word (and it doesn't seem like the best way to do it, actually), but yeah I bet it would work. At least it'd give me a basic footing to work with from there. Thanks.
[QUOTE=Thumbtacks;41471211]That might help, yeah. Looks like it just checks for one instance of a word (and it doesn't seem like the best way to do it, actually), but yeah I bet it would work. At least it'd give me a basic footing to work with from there. Thanks.[/QUOTE]
It counts the number of times "gold", the '$' character, or any of the most common TLDs shows up, and if more than one shows up in a single message it prunes it.
"I'm charging 50 gold for it." is shown, whereas
"Selling gold at www.buywowgoldnow.org" does not, because both "gold" and "*.org" shows up.
You can adjust the number of words needed from the list to be considered "spam" at the line
[code]
if (matchCount > 1) then
[/code]
Oh. Shit, that actually does make sense. Thanks. I didn't catch that.
man, I should just post my whole code once I'm done so you guys can look through it and find the inevitable mistakes I will make.
[QUOTE=ZeekyHBomb;41469122]There's no pastebin link there :v:
Anyway, I don't have any experience with plugin development myself, but the documentation seems to suggest, that you can just call ExecuteCommand("Tools.Attach to process", pid.toString()); or something like that.
I have a rough idea what it should look like though, so I might be able to point you in the right direction, assuming my hunch is correct.
Assuming you are writing a Visual Studio Add-in...
[/QUOTE]
Shit I'm an idiot I didn't add the paste bin code.
[url]http://pastebin.com/pcJk4WS5[/url]
Thats the code there.
I will try what you said tomorrow in work.
Let me know if checking the code changed your mind on anything please!
This is starting to come together pretty well, actually. There's one thing I want to do, though, and I'm not entirely sure how.
I can store variables server-side and then just load them when the addon loads, which is nice. Problem is, I want a counter that will keep track of how many users have set me to Ignore. The only way I could think to do it was like this:
[code]local NumberIgnored
RegisterForSave("NumberIgnored")[/code]
And then just use NumberIgnored whenever I'd use it. Problem is, I can't figure out where to initialize it. If I initialize it in the declaration, then it'll reset to zero every time.
..actually, lua doesn't need me to declare variables, does it?
I think I know how to do it.
[editline]15th July 2013[/editline]
[code] if NumberIgnored == nil then -- first time NumberIgnored has been used
NumberIgnored = 0
else
NumberIgnored = NumberIgnored + 1
end
[/code]
That should work, right?
In ReturnProcessToAttach you could just return the Process itself, instead of its ID and then getting the Process again via GetProcessById.
You could make it more terse like this:
[code]var process = System.Array.Find(System.Diagnostics.Process.GetProcessesByName("w3wp")
,x => x.GetProcessOwner().Contains("Administrator"));[/code]
It would look a bit more concise if you do using System; and using System.Diagnostics;.
But so far it's what I had in mind.
Just store a reference to the DTE when OnConnection is called and then hopefully you will be able to attach the debugger with DTE.ExecuteCommand.
[del]So, I'm making a Source 2013 mod, but I've run into a slight annoyance. Does anybody know how to remove the MOTD? Just, not even have it appear? I'm really pretty new to C++ and I figure this is a great way to learn.[/del]
Nvm, worked around it with something that's to my advantage.
[QUOTE=ZeekyHBomb;41472216]In ReturnProcessToAttach you could just return the Process itself, instead of its ID and then getting the Process again via GetProcessById.
You could make it more terse like this:
[code]var process = System.Array.Find(System.Diagnostics.Process.GetProcessesByName("w3wp")
,x => x.GetProcessOwner().Contains("Administrator"));[/code]
It would look a bit more concise if you do using System; and using System.Diagnostics;.
But so far it's what I had in mind.
Just store a reference to the DTE when OnConnection is called and then hopefully you will be able to attach the debugger with DTE.ExecuteCommand.[/QUOTE]
I can't seem to get the x => x.GetProcessOwner() working. It won't pick up the GetProcessOwner method :(
If I did it the other way and just returned the process, how do I attach the process using the .ExecuteCommand?
Would it just be DTe.ExecuteCommand(process) or what?
So confused with this :(
[code]x => GetProcessOwner(x).Contains("Administrator")[/code]
Thought that was a method of the Process class.
[code]DTe.ExecuteCommand("Tools.Attach to process", process.Id.ToString());[/code]
I think.
You see, [url=http://msdn.microsoft.com/en-us/library/vstudio/envdte._dte.executecommand.aspx]ExecuteCommand[/url] takes a command as first argument. The example uses "File.NewFile", so I imagine that "Tools.Attach to process" might work.
The second argument specifies arguments for the command. To quote the documentation:
[quote=http://msdn.microsoft.com/en-us/library/vstudio/envdte._dte.executecommand.aspx]A string containing the same arguments you would supply if you were invoking the command from the Command window.[/quote]
I'm just guessing that "ToolsAttach to process" can be supplied with a process ID.
I'm trying to make a save-game system for my game in unity and I've been looking at BinaryReader and BinaryWriter but I don't get how BinaryReader works. On [URL="http://msdn.microsoft.com/en-us/library/system.io.binaryreader.readstring.aspx"]this page on the msdn[/URL], in the example, there's the following method:
[code]public static void DisplayValues()
{
float aspectRatio;
string tempDirectory;
int autoSaveTime;
bool showStatusBar;
if (File.Exists(fileName))
{
using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
{
aspectRatio = reader.ReadSingle();
tempDirectory = reader.ReadString();
autoSaveTime = reader.ReadInt32();
showStatusBar = reader.ReadBoolean();
}
Console.WriteLine("Aspect ratio set to: " + aspectRatio);
Console.WriteLine("Temp directory is: " + tempDirectory);
Console.WriteLine("Auto save time set to: " + autoSaveTime);
Console.WriteLine("Show status bar: " + showStatusBar);
}
}[/code]
If you have say 12 different Int32's or 5 different strings saved, how does the reader know that [I]autoSaveTime[/I] is some int rather than one of the other 11? If I have multiple strings and I want the reader to get the string for [I]tempDirectory[/I], how would it know which string to read? Would I have to somehow specify?
You need to read them in the same order you write.
[editline]16th July 2013[/editline]
You might be able to use the [url=http://msdn.microsoft.com/en-us/library/Vstudio/system.runtime.serialization.formatters.binary.binaryformatter.aspx]SerializableAttribute[/url] with the [url=http://msdn.microsoft.com/en-us/library/Vstudio/system.runtime.serialization.formatters.binary.binaryformatter.aspx]BinaryFormatter[/url] instead of hand-writing the functions, but I've only scratched the surface of C#, so I have no idea what the implications are (if it even just works automatically like that, but it seems to).
[QUOTE=ZeekyHBomb;41479625][code]x => GetProcessOwner(x).Contains("Administrator")[/code]
Thought that was a method of the Process class.
[code]DTe.ExecuteCommand("Tools.Attach to process", process.Id.ToString());[/code]
I think.
You see, [url=http://msdn.microsoft.com/en-us/library/vstudio/envdte._dte.executecommand.aspx]ExecuteCommand[/url] takes a command as first argument. The example uses "File.NewFile", so I imagine that "Tools.Attach to process" might work.
The second argument specifies arguments for the command. To quote the documentation:
I'm just guessing that "ToolsAttach to process" can be supplied with a process ID.[/QUOTE]
I'm still having trouble with the X => GetProcessOwner.
When I write GetProcessOwner it doesn't come up or anything? I'm not sure what X => does either. I've never used that before.
Would it be easier if I added you on Steam or something to have you help me or?
It's the [url=http://msdn.microsoft.com/en-us/library/vstudio/bb311046.aspx]lambda operator[/url].
If we discuss it in public, anyone facing the same (or a similar) problem can see the solution.
The X should either be a lower case x, or the argument to GetProcessOwner should also be an upper case X.
[editline]16th July 2013[/editline]
Oh, and if anyone with real C# and/or VS Add-In development experience chimes in, (s)he can probably give you more adequate help. I'm just making guesses.
Ah okay thanks!
When I Type GetProcessOwner, it doesn't come up as a usable method for some reason :S
Like do I need variables or anything for X? Or is it just going through the array checking for "Administrator"?
And when I type DTE I don't see any ExecuteCommand so I'm not sure what to do.
Thanks for the help btw
When you write
[code]x => GetProcessOwner(x).Contains("Administrator")[/code]
You should get a [url=http://msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx]lambda expression[/url]. You can think of it as a fancy name for an anonymous (=unnamed) function.
Basically it means "take an argument named x (type will be inferred by the compiler) and return GetProcessOwner(...)... (return-type will be inferred by the compiler)".
I'm not 100% sure if it is inferred or uses generics or something, but in any case it should work syntactically.
You should then be able to pass this as second argument to [url=http://msdn.microsoft.com/en-us/library/d9hy2xwa.aspx]Array.Find[/url], which is of type [url=http://msdn.microsoft.com/en-us/library/bfcke1bz.aspx]Predicate[/url], which is a delegate taking T returning bool.
Lambdas can be automatically converted to delegates. T in this case is Process and the return-type of bool matches also.
What is the specific error the compiler gives you when you try to use the x => something syntax?
And what type is your DTE?
Ah okay thanks.
Since I couldn't do that I just went ahead and made the ReturnProcessToAttach method return the process.
I'm not too sure on what the whole DTE thing is, however in my OnConnection method, it looks like this:
[CODE] public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
if (connectMode == ext_ConnectMode.ext_cm_UISetup)
{
object[] contextGUIDS = new object[] { };
Commands2 commands = (Commands2)_applicationObject.Commands;
Microsoft.VisualStudio.CommandBars.CommandBar standardToolBar =
((Microsoft.VisualStudio.CommandBars.CommandBars)
_applicationObject.CommandBars)["Project"];[/CODE]
So does that mean my DTE is DTE2? I must sound so dumb ha but I have never wrote a plugin so all of this generated code is new to me.
That code does not show your DTE variable, so I can't see what type it is in your context.
If it is of type DTE2, it should have the ExecuteCommand method, since [url=http://msdn.microsoft.com/en-us/library/vstudio/envdte80.dte2.aspx]DTE2 inherits from _DTE[/url], of which [url=http://msdn.microsoft.com/en-us/library/vstudio/envdte._dte.executecommand.aspx]ExecuteCommand[/url] is a member of.
At the bottom of my code there is private DTE2 _applicationObject; if that's any help?
If not where should I be looking for it?
How exactly should it be phrased? I tried DTE2 test = new DTE2(); but it said "cannot create interface of abstract class Envdte80.dte2"
This is so I can try the ExecuteCommand method
Then you can probably use _applicationObject, as in _applicationObject.ExecuteCommand(...);.
I would need help starting with Lua.
I got some experience codding and modifying codes for my own usages but there was nothing really advanced.
I Learned lua for Computer Craft. (minecraft mod) and i liked to mess around. I would like to know which program i can get to run or execute simple scripts easily. on a screen.
Right now I use notepad++ when i code but i didn't saw where i can test the script.
Is there a good software cheap/free I can use for experimental scripts?
Okay thanks.
I tried this _applicationObject.ExecuteCommand("Tools.Attach to process", proc.Id.ToString());
And I got this error when my code reached that part in the code
"Error HRESULT E_FAIL has been returned from a call to a COM component."
[QUOTE=pac0master;41481013]I would need help starting with Lua.
I got some experience codding and modifying codes for my own usages but there was nothing really advanced.
I Learned lua for Computer Craft. (minecraft mod) and i liked to mess around. I would like to know which program i can get to run or execute simple scripts easily. on a screen.
Right now I use notepad++ when i code but i didn't saw where i can test the script.
Is there a good software cheap/free I can use for experimental scripts?[/QUOTE]
You can just run the lua interpreter stand-alone.
[editline]16th July 2013[/editline]
In fact, if you just run lua(.exe) without any arguments, you get a [url=https://en.wikipedia.org/wiki/Read-eval-print_loop]REPL[/url].
[code]$ cat test.lua
print("Hi!")
$ lua test.lua
Hi![/code]
On Windows you'll probably use cmd.exe for that. You might need to copy the lua.exe to the same directory where your script is and write lua.exe <file> instead of just lua.
For Notepad++ there seems to be a plugin called [url=http://sourceforge.net/projects/npp-plugins/files/NppExec/]NppExec[/url], which provides an embedded terminal, which you could use instead of the separate cmd.exe and might have the nice feature of not needing to manually browse to your project directory (maybe, don't know).
[QUOTE=Over-Run;41481089]Okay thanks.
I tried this _applicationObject.ExecuteCommand("Tools.Attach to process", proc.Id.ToString());
And I got this error when my code reached that part in the code
"Error HRESULT E_FAIL has been returned from a call to a COM component."[/QUOTE]
You can try printing each element of the [url=http://msdn.microsoft.com/en-us/library/vstudio/41fz650t.aspx]Commands[/url]-collection, although I'm unsure if that represents all available commands for ExecuteCommand.
If that doesn't help you, try some Google-fu for ExecuteCommand and your error or ExecuteCommand and Debugger. Or try some asking some Visual Studio community.
I asked already at the Visual Studio community and they said I would have to have a serious understanding of memory management and how processes work.
I'll never get this done ha
Are you sure they didn't misunderstand you and thought that you wanted to write a debugger or something?
I can't imagine that you need an in-depth understanding of memory management and processes in Windows to attach the in VS integrated debugger to a process - a functionality that already exists (and you just need automated).
Worst-case scenario is that they absolutely do not expose this functionality in their Add-In interface, in which case I also don't think an understanding of memory management and processes would be of any help.
Actually they did misunderstand me, guy just replied saying I can use the Process.Attach() method.
And with you help of making me understand what the DTE was I managed to make it not break.
I used this:
[CODE] EnvDTE.Processes pp = _applicationObject.Debugger.LocalProcesses;
foreach (EnvDTE.Process proc in pp)
{
if (proc.Name.IndexOf("w3wp.exe") != -1 && proc.ProcessID.)
proc.Attach();
}[/CODE]
The only thing is, I'm not sure how to make it check for the Administrator Username part. It doesn't seem EnvDTE.Process has a username attribute.
Any ideas?
EDIT
Shit after checking it turns out that it has a ProcessID attribute instead of just ID.
Just going to test now
[editline]16th July 2013[/editline]
Okay the code seemed to of compiled and ran through.
Only thing now is, I'm not sure if it's definitly attached?
Usually when you go to Tools/Attach to process/w3wp it is greyed out when it's attached.
However when I check it now, it's not greyed out and both of the w3wp processes are still there
Any ideas on if it is definitly attached or not?
[editline]16th July 2013[/editline]
Okay the code seemed to of compiled and ran through.
Only thing now is, I'm not sure if it's definitely attached?
Usually when you go to Tools/Attach to process/w3wp it is grayed out when it's attached.
However when I check it now, it's not grayed out and both of the w3wp processes are still there
Any ideas on if it is definitely attached or not?
Try setting a breakpoint in a line you know is being executed periodically.
Sorry, you need to Log In to post a reply to this thread.