Jump to content

Tailcoat

Members
  • Posts

    118
  • Joined

  • Last visited

Reputation

72 Excellent

About Tailcoat

  • Birthday 01/01/1004

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Thanks! I just learned how to manually fix that. I chose version 0.1.1 as the default download since it was the last stable version. However, the unfinished newer version's files are still available on the Files page to help with the development of the newer bind manager app "BindControl".
  2. Does your directory look like the image below? There is no install prompt and I'm not sure if the original v0.76 app even had one. Installation is just unzipping the files to your desired folder and double-clicking on CityBinder.exe. Also, there's a similar app also based on CityBinder v.0.76 called "BindControl". Since I don't have time to keep up with my version of CB, I gave my notes to that author. I don't know if it has the same functionality since I haven't played CoH in over a year, but here's a link to the thread about it in case you find it useful:
  3. I think it would be really great and useful for a bind app to gain as much traction as Mid's Reborn.
  4. Thank you! I wish I could've gotten more done on updating this, but I started working full-time and couldn't keep up. The LUA language wasn't handling all the stuff that I wanted it to do, and as a hobbyist, I couldn't be as efficient and knowledgeable as a trained programmer. If it helps, another user has taken up the mantle and made a similar app with Python called "BindControl". I don't know what the status of it is (I've been away from COH for a while), but it works on other systems besides Win10 and I sent over my various notes and ideas for the project to continue. Here is a link to the thread for that:
  5. Ooh, it'd be nice if the Naga tray had 12 power spaces instead of just 10. I don't know if 12 thumb-side buttons is standard for MMO mice, but I could imagine that adding more spaces could break things in the code. If it's possible to open multiple Naga trays, that could help. When I've got a character fully stocked with powers, the 3 default trays end up full of buttons, so I need to see a lot more than just 10 spaces at a time.
  6. Ok, I see that the weird tray alignment of not being in an even grid was the issue. It's been a while since I played. I wish I could have a power tray of 12 buttons in a grid, but I do like A.I.D.A.'s idea.
  7. I don't know if this has been looked at since I haven't played in a while, but I'd love an option to arrange the power tray in a 3x4 configuration. I wanted to jump into the game again, but since I started using one of those MMO mice with the 12 side buttons, I can't go back to clicking on the power tray buttons or hunting-and-pecking number keys. I tried arranging the trays in the same way as those buttons so I could learn to use my MMO mouse with it, but I couldn't replicate that 3x4 grid, so I thought I'd suggest it as an option here.
  8. If it helps, here are the basics of what CB did using a complex bind I set up that makes the character do a different dance every time the user presses "Y". The Complex Bind button pulls up a table (I'd recommend adding a pale background color to every other row to make it clearer to the user that each row is associated with the keybind at the start of it). I entered "Y" for the bind and added a different dance emote command to each space in that row. I chose 8 that I felt segued decently into each other (In CB, you can add up to 599 commands to a row, which I think is overkill!). Pressing the ">>" button lets the user view any other user-defined Complex Binds that may've been imported into the profile (in this case, there are 4 Complex Binds loaded and the dance cycle is the first). You can have one "page" with multiple Complex Binds on it too by using more than one row. Here's a screencap of how the dance bind cycle looks in CB: When the user hits the Generate Bindfiles button, CB makes TXT files for the game to read which include the "bindloadfilesilent" command after the dance command. CB generates numerical number names for them in a subfolder called "cbinds". I'm thinking that the first number in the file name is taken from the "page" number of the Complex Bind, then the second number comes from the "Cycle" column. This is in the folder for the default profile I set up for CB, which contains multiple Complex Binds. Here's a screen of how those look in file explorer, plus the opened TXT files: CB uses its own file extension ".cbm" for imported/exported binds. The extension ".cbp" is for profiles. The .cbm files can be opened in Notepad. Here's what the exported dance cycle Complex Bind looks like: I wasn't aware of all the workings of how CB generated binds, but skimming through some files, I think a lot of that stuff is in the file "cbutility.lua" if you want to check it out. EDIT: If you do check out the CB files I worked on, just be aware that there will be differences between the files contained in the last stable version of CB4H and the unfinished v0.2 version. "cbutilityUI.lua" contains code related to import/export buttons, which must link back to cbutility.lua. The Complex Bind module file, "complexbinds.lua" could be especially useful for ideas. Here's the code for that: local module = {} local function addCBind(cbinds,n,profile) -- this returns an IUP vbox/hbox to be inserted into the CBind Dialog box local cbind = cbinds[n] local bindtext = iup.label{title = ""; SIZE = "100X"} local function matrix_value(_,l,c) if l == 0 then -- return the titles of columns if c == 0 then return "" elseif c == 1 then return "Bindkey" else return "Cycle "..(c - 1) end elseif c > 0 then -- return the values of the bindkeys if cbind[l] == nil then return "" end if c == 1 then return cbind[l].bindkey or nil else return cbind[l][c-1] or nil end end end local function matrix_value_edit(_,l,c,newval) cbind[l] = cbind[l] or {} if newval == "" then newval = nil end if c == 1 then cbind[l].bindkey = newval else cbind[l][c-1] = newval end profile.modified = true return iup.DEFAULT end local function matrix_entercell(_,l,c) if cbind[l] == nil then bindtext.title = "" else if c == 1 then bindtext.title = cbind[l].bindkey or "" else bindtext.title = cbind[l][c-1] or "" end end return iup.DEFAULT end local altBGcolor = 50, 50, 50 local matrix = iup.matrix{numcol="600";numlin="50";numcol_visible="5";numlin_visible="10"; height0=8;value_cb = matrix_value; value_edit_cb = matrix_value_edit; enteritem_cb = matrix_entercell} for i = 2,600 do matrix["alignment"..i] = "ALEFT" end local delbtn = cbButton("Delete This Bind",function() if iup.Alarm("Confirm Deletion","Are you sure you want to delete this bind?","Yes","No") == 1 then table.remove(cbinds,n) cbinds.curbind = cbinds.curbind - 1 if cbinds.curbind == 0 then cbinds.curbind = 1 end cbinds.dlg:hide() --cbinds.dlg:destroy() cbinds.dlg = nil module.createDialog(cbinds,profile) cbShowDialog(cbinds.dlg,nil,nil,profile,cbinds.dlg_close_cb) profile.modified = true end end,125) local exportbtn = cbButton("Export...",function() cbExportModuleSettings(profile,n,cbinds,"ComplexBind") end,125) return iup.frame{iup.vbox{bindtext,matrix,iup.fill{rastersize="x10"},iup.hbox{delbtn,exportbtn,margin="0x0"},iup.fill{rastersize="x10"},alignment="ACENTER"},cx = 0, cy = 65 * (n-1)} end local function newCBind() -- this returns the default empty Simple Bind table to be inserted into SBinds local t = {} return t end function module.createDialog(cbinds,profile) local box = {} for i = 1,table.getn(cbinds) do table.insert(box,addCBind(cbinds,i,profile)) end cbinds.curbind = cbinds.curbind or 1 local newbindbtn = cbButton("New Complex Bind", function() table.insert(cbinds,newCBind()) cbinds.curbind = table.getn(cbinds) cbinds.dlg:hide() --cbinds.dlg:destroy() cbinds.dlg = nil module.createDialog(cbinds,profile) cbShowDialog(cbinds.dlg,nil,nil,profile,cbinds.dlg_close_cb) profile.modified = true end,125) local importbtn = cbButton("Import Complex Bind",function() local newcbind = newCBind() -- we will be filling this new BBind up. table.insert(cbinds,newcbind) local newcbind_n = table.getn(cbinds) if cbImportModuleSettings(profile,newcbind_n,cbinds,"ComplexBind") then cbinds.curbind = table.getn(cbinds) cbinds.dlg:hide() cbinds.dlg = nil -- Resolve Key COnflicts. cbResolveKeyConflicts(profile,true) module.createDialog(cbinds,profile) cbShowDialog(cbinds.dlg,nil,nil,profile,cbinds.dlg_close_cb) profile.modified = true else -- user cancelled, remove the new table from bbinds. table.remove(cbinds) end end,125) local sbEnablePrev = "NO" local sbEnableNext = "NO" local okbtn = cbOKbutton() if cbinds.curbind > 1 then sbEnablePrev = "YES" end cbinds.prevbind = cbButton("<<",function(self) cbinds.curbind = cbinds.curbind - 1 cbinds.zbox.value = box[cbinds.curbind] cbinds.poslabel.title = cbinds.curbind.."/"..table.getn(cbinds) local sbEnablePrev = "NO" if cbinds.curbind > 1 then sbEnablePrev = "YES" end cbinds.prevbind.active=sbEnablePrev local sbEnableNext = "NO" if cbinds.curbind < table.getn(cbinds) then sbEnableNext = "YES" end cbinds.nextbind.active=sbEnableNext end,25,nil,{active=sbEnablePrev}) if cbinds.curbind < table.getn(cbinds) then sbEnableNext = "YES" end cbinds.nextbind = cbButton(">>",function(self) cbinds.curbind = cbinds.curbind + 1 cbinds.zbox.value = box[cbinds.curbind] cbinds.poslabel.title = cbinds.curbind.."/"..table.getn(cbinds) local sbEnablePrev = "NO" if cbinds.curbind > 1 then sbEnablePrev = "YES" end cbinds.prevbind.active=sbEnablePrev local sbEnableNext = "NO" if cbinds.curbind < table.getn(cbinds) then sbEnableNext = "YES" end cbinds.nextbind.active=sbEnableNext end,25,nil,{active=sbEnableNext}) cbinds.poslabel = iup.label{title = cbinds.curbind.."/"..table.getn(cbinds);rastersize="50x";alignment="ACENTER"} box.value = box[cbinds.curbind] cbinds.zbox = iup.zbox(box) cbinds.dlg = iup.dialog{iup.vbox{cbinds.zbox,iup.fill{rastersize="10x"},iup.hbox{cbinds.prevbind;newbindbtn;importbtn;cbinds.poslabel;cbinds.nextbind;alignment="ACENTER",margin="0x0"};iup.fill{rastersize="10x"};okbtn;alignment="ACENTER"};title = "General : Complex Binds",maxbox="NO",resize="YES",icon = appicon,parentdialog=cbdlg,mdichild="YES",margin=dlgMargins} okbtn.action = function() cbinds.dlg:hide() end cbinds.dlg_close_cb = function(self) cbinds.dlg = nil end end function module.bindsettings(profile) local cbinds = profile.cbinds if cbinds == nil then cbinds = {} profile.cbinds = cbinds end if cbinds.dlg then cbinds.dlg:show() else module.createDialog(cbinds,profile) cbShowDialog(cbinds.dlg,nil,nil,profile,cbinds.dlg_close_cb) end end local function maxKeys(cbind) local maxK = 0 for n = 1,600 do if cbind[n] then if cbind[n].bindkey and not (cbind[n].bindkey == "") then maxK = n end end end return maxK end local function maxCycles(cbind,maxK) local maxC = 0 for m = 1,maxK do for n = 2,600 do if cbind[m][n] and not (cbind[m][n] == "") then if n > maxC then maxC = n end end end end return maxC+1 end local function writeBind(file,cbinds,key,cycle,bindset,maxC,profile) local nextCycle = cycle+1 if nextCycle > maxC then nextCycle = 1 end local k = cbinds[bindset][key].bindkey local cmd = '' if cbinds[bindset][key][cycle] and not (cbinds[bindset][key][cycle] == "") then cmd = cbinds[bindset][key][cycle].."$$" end cmd = cmd.."bindloadfilesilent "..profile.base.."\\cbinds\\"..bindset.."-"..nextCycle..'.txt' cbWriteBind(file,k,cmd) end function module.makebind(profile) local resetfile = profile.resetfile local cbinds = profile.cbinds local cbindfile local maxK local maxC cbMakeDirectory(profile.base.."\\cbinds") for k = 1, table.getn(cbinds) do -- for each complex bind set maxK = maxKeys(cbinds[k]) maxC = maxCycles(cbinds[k],maxK) --print("maxK = "..maxK..", maxC = "..maxC) for j = 1, maxC do -- for each cycle in this bindset, counting the first one twice --create a new bindfile if cycle is 2+ if j > 1 then cbindfile = cbOpen(profile.base.."\\cbinds\\"..k.."-"..(j-1)..".txt","w") --print("created "..profile.base.."\\cbinds\\"..k.."-"..(j-1)..".txt") end for i = 1,maxK do -- for each key in the bindset if j == 1 then writeBind(resetfile,cbinds,i,j,k,maxC-1,profile) else writeBind(cbindfile,cbinds,i,j-1,k,maxC-1,profile) end end if j > 1 then cbindfile:close() --print("closed "..profile.base.."\\cbinds\\"..k.."-"..(j-1)..".txt") end end end end function module.findconflicts(profile) local resetfile = profile.resetfile local cbinds = profile.cbinds for k = 1, table.getn(cbinds) do -- for each complex bind set local maxK = maxKeys(cbinds[k]) for i = 1,maxK do -- for each key in the bindset cbCheckConflict(cbinds[k][i],"bindkey","Complex Bind "..k) end end end function module.bindisused(profile) if profile.cbinds == nil then return nil end return table.getn(profile.cbinds) > 0 end cbAddModule(module,"Complex Binds","General")
  9. When updating CityBinder, I considered a couple of ways of making it easier for players to add and share modules. As mentioned, I did include a bunch of snippets, although those files only work with CityBinder, but could provide useful material to adapt for BindControl. They're in the "Sample_Binds" folder included in my SourceForge uploads, which only work with CityBinder's modules for Simple (in the "Custom Binds" section), Complex (binds requiring multiple txt files), and Ultra binds. I never figured out Ultra binds and it wasn't documented much, so that file is just what was included in the original CityBinder just in case anyone else could figure it out. I think Ultra binds were meant to help people make more complex modules w/o needing to know coding? It's an interesting idea. Below, I've included some screenshots of the kinds of binds I included. Several are movement related, so would best be incorporated into a movement module if that hasn't been done already. I can explain what they are if anything interesting jumps out. The other thing I started to make modules shareable (but wasn't able to finish in the last stable version of CB. However, it should work in the unfinished v0.2 files I uploaded to SourceForge.) was instead of hard-coding the modules into the script that loads them up, I had it check its current directory for a subfolder called "modules" and load up the .lua files in there. Within that folder was another called "inactive" so files can easily be taken out of rotation without deleting them (it was useful for bug testing). In those LUA files, I added some more variables to help categorize the modules into a tree and also generate credit info in a popup if the user clicks the button for that. Including the last update as a variable could also help authors (should they change how their code works) find and update things used in previous versions of the app (or it may make more sense to focus on versions of the module itself instead). I pasted an image of the text next to the popup to illustrate my attempt at improving user-friendliness to encourage people to make and share their own modules. I even worked on trying to de-hard-code the interface colors and turn them into variables in an attempt to create a dark mode option (and down the road, potentially programming in customization options for interface colors), but I just couldn't get Lua to do what I wanted consistently!
  10. The citybinder.lua file should be in the same directory as the .exe file. If it still gives you trouble, I've since passed on my work to a more-experienced developer. I don't know how far the app has progressed, but the thread about the "BindControl" app is here:
  11. I meant allow the user to specify a full path for the profiles anywhere. Personally, I never save anything to the default C:\Documents folder and I keep gaming stuff in a separate folder. I've been keeping my binds and profiles in character-specific subfolders like this: The idea about subfolders I had was separate from that but similar to your first idea. If I made a new profile for my character Erasyerhead (or a general profile called Warshade Binds) and entered that as the profile's name then hit "Save As", if the app didn't detect a pre-existing folder called "Erasyerhead" in my chosen directory, it could ask to create one, then save the binds or profiles inside.
  12. I've been wondering if it would be useful if users could choose separate paths for saving profiles vs. generated files. It'd be convenient for an app to be able to take the profile's name and create a folder with that name when the profile is saved. It could be an optional setting.
  13. I don't know if this helps anything, but I made pop-up menus for a handful of my characters to help manage their teleport (and related things like jaunt, translocate, and mystic flight) and targeted AOE powers. Then I bound that menu to the E key. Here's the content of one of the files: // Menu Erasyerhead { Title "Teleport" Divider Option "&A Combat TP to Target" <&powexec_location target Combat Teleport&> Option "&S Retreat" <&powexec_location back:60 Combat Teleport$$face&> // Since I plan on using this in combat, // I want the bonus that Combat Teleport gives. This is for when you port right to an enemy, execute a melee attack like Sands of Mu, then want to jump back to use ranged attacks. "Face" is necessary to keep toon facing same direction. // Without it, character will turn 180 degrees, which would be disorienting, unless you plan on running away. Option "&D TP Target to Self" <&tell $target, I'm teleporting you to my location...$$powexec_location forward:10 Teleport Target&> Option "&F TP to Target" <&powexec_location target Teleport&> Option "&R TP Ring" <&powexecname Teleport&> Divider Option "&W Up And Away!" <&powexec_location up:max Teleport&> Option "&E BUG OUT!" <&powexec_location back:max Teleport&> // When you want to turn and run in opposite direction. Turn 180 degrees and teleport far away. } I found it useful to make the character-specific pop menu key and "BUG OUT!" key the same since if I'm panicking and need to get away ASAP, I can't always remember which menu key to press. This way, I don't have to since I just have to hit "E" twice to try escaping certain death. I couldn't get the turn-around command to work with (IIRC... been a while) teleport-adjacent powers like Jaunt. I also made a bunch of .cbm simple bind files for CityBinder containing various commands like that. If you don't want to grab them from a .zip file, you can find the loose files here: https://sourceforge.net/projects/citybinder-for-homecoming/files/unfinished_CB4H_v0.2/Sample_Binds/Simple/ I didn't really use CityBinder's SoD module since it was clunky and confusing, so I can't say how useful or not it'd still be since the travel power update, but maybe the module could have separate tabs for each type of movement (especially if you'd like to offer different uses like in the menu above). I wonder if having Kheldian settings as its own module would make more sense than how CityBinder did it as a section that only appears in SoD if you select one of those Archetypes.
  14. @emersonrp Ok, I've uploaded my unfinished CityBinder for Homecoming v0.2 files here: https://sourceforge.net/projects/citybinder-for-homecoming/files/unfinished_CB4H_v0.2/ I added a bunch of notes in the Documentation folder on changes I made since 0.76, some issues to resolve, and ideas I wanted to implement. My LUA files contain various notes explaining things I did, keeping in mind helping potential programmers (or my future self) looking at them. I suffixed them with "-TC". Some of the original author notes are in there too (they're unlabeled). A couple of files in my project folders relate to an unsuccessful attempt to build a 32-bit version of it in order to reach a wider audience, but that stuff got waaaay too technical for me. The version my .exe file works for is Win10, 64-bit. If you find any of the info in my SourceForge project's help files useful for explaining features, feel free to recycle it! I'd hoped in the future to perhaps create a how-to video on using it. The tooltips are kind of weird and don't always pop up over sections that would intuitively make sense. Let me know if you have any questions!
×
×
  • Create New...