Jump to content

Amun

Contributor
  • Posts

    199
  • Joined

  • Last visited

  • Days Won

    1
  • Feedback

    100%

Everything posted by Amun

  1. You said if you close the safebox and open it again, you'll have the last item put in that place. I'm a bit confused, so help me out a little. When the item disappears, can you put another item in its place? If you CAN'T(which should be expected), does your stack appear back after you close and open the safebox again? If you CAN(which you shouldn't be able to, because that slot SHOULD be marked as NOT empty), what do you get left in the safebox when opening and closing it again? The items that disappeared or the new item that you put in their place after they disappeared? Your problem is coming from somewhere else, I don't see why your little stacking thingy would break the safebox. Also, you have logs, see what the logs say when an item disappears and just trace that shit down.. ez
  2. @BadGrecee don't worry about it, he probably fucked up some tabs(as usual) or pasted that function outside of InventoryWindow(the benefits of not bothering to even learn the basics of Python). @Tuckii please search "def HighlightSlot" in uiInventory.py, then fix the damn tabs/spaces. If you really don't have that function(which I doubt), then here, extend "class InventoryWindow(ui.ScriptWindow):" with these methods: if app.WJ_ENABLE_PICKUP_ITEM_EFFECT: def HighlightSlot(self, slot): if slot>player.INVENTORY_PAGE_SIZE*player.INVENTORY_PAGE_COUNT: return if not slot in self.listHighlightedSlot: self.listHighlightedSlot.append (slot) def DelHighlightSlot(self, inventorylocalslot): if inventorylocalslot in self.listHighlightedSlot: if inventorylocalslot >= player.INVENTORY_PAGE_SIZE: self.wndItem.DeactivateSlot(inventorylocalslot-player.INVENTORY_PAGE_SIZE) else: self.wndItem.DeactivateSlot(inventorylocalslot) self.listHighlightedSlot.remove(inventorylocalslot)
  3. I don't have the system, but I'm pretty sure it sends the pet's data through some packet. You could add that stuff in the packet as well, pass it down to the window and show it to your users.
  4. def OnPressEscapeKey(self): pass or just delete it..
  5. To declare a method you just have to add its return type and name in the corresponding class body. ex: class CItem { public: // access void someMethod(); // your method's declaration } Defining it: void CItem::someMethod() { // do work } Also, you should probably try using Google before asking about shit like this.
  6. Yeah, it seems like the already compiled exe files are marked as viruses. Should I update the archive and remove them? I mean, it takes 5 seconds to compile dump_proto, so I don't think they really need to be there. Check your client's TItemTable, they have to be identical for it to work(server-side as well). In dump_proto's source you'll find the table in data.h, in the client I think it's in gameLib/GameType.h or ItemData.h(can't remember, I don't have them there anymore). Edit: Archive updated, virustotal passed: [Hidden Content]
  7. It doesn't have one. Maybe m2 downloads added one for some reason. Here's from mega: [Hidden Content]
  8. I already gave you all the clues in the topic. Now, to answer your question, assuming you've updated your dump proto, just add a new item in item_proto.txt, add the name in item_names.txt, then put both of them in the same folder with your dump_proto.exe and run it. After the proto is combined and compressed, put it in client/locale/xx, encrypt and run the client to test the changes. Adding the same changes to your server's proto and restarting it is already implied. Edit: Here's the source for dump_proto(I'm using it for my source). It's already updated to v22.0.8(I didn't bother checking for other proto updates). [Hidden Content]
  9. Thanks for sharing, love! If anyone needs the code: Lazy(and avoidable) version: Dump_proto+binary version with MrQuin's mobs list: [Hidden Content] [Hidden Content] If anyone needs a version with the data being loaded from locale, let me know, I've only done it this way cause that was the first idea I had.
  10. That's because you added an extra tab to 'curList', just delete that extra tab and the error will go away. Yeah, so the dict IS actually built and loaded properly. I'll take a look at how it retrieves it and I'll edit this post to let you know. Try replacing it with this: def __LoadInformation_Drops(self, race): self.AppendSeperator() if (race not in constInfo.MONSTER_INFO_DATA) or (len(constInfo.MONSTER_INFO_DATA[race]["items"]) == 0) : self.AppendTextLine(localeInfo.TARGET_INFO_NO_ITEM_TEXT) return itemListBox = ui.ListBoxExNew(32 + 5, self.MAX_ITEM_COUNT) itemListBox.SetSize(self.GetWidth() - 15 * 2 - ui.ScrollBar.SCROLLBAR_WIDTH, (32 + 5) * self.MAX_ITEM_COUNT) height = 0 for curItem in constInfo.MONSTER_INFO_DATA[race]["items"]: if curItem.has_key("vnum_list"): height += self.AppendItem(itemListBox, curItem["vnum_list"], curItem["count"]) else: height += self.AppendItem(itemListBox, curItem["vnum"], curItem["count"]) if height < itemListBox.GetHeight(): itemListBox.SetSize(itemListBox.GetWidth(), height) self.AppendWindow(itemListBox, 15) itemListBox.SetBasePos(0) if len(constInfo.MONSTER_INFO_DATA[race]["items"]) > itemListBox.GetViewItemCount(): itemScrollBar = ui.ScrollBar() itemScrollBar.SetParent(self) itemScrollBar.SetPosition(itemListBox.GetRight(), itemListBox.GetTop()) itemScrollBar.SetScrollBarSize(32 * self.MAX_ITEM_COUNT + 5 * (self.MAX_ITEM_COUNT - 1)) itemScrollBar.SetMiddleBarSize(float(self.MAX_ITEM_COUNT) / float(height / (32 + 5))) itemScrollBar.Show() itemListBox.SetScrollBar(itemScrollBar)
  11. Wait, so there's no syserr showing from game.py/BINARY_AddTargetMonsterDropInfo when you click to see the drop of a mob? It seems pretty impossible, could you try that again, please?
  12. Not in binary, in root. If you look inside game.py, you'll see this if app.ENABLE_SEND_TARGET_INFO: def BINARY_AddTargetMonsterDropInfo(self, raceNum, itemVnum, itemCount): This function is called with those arguments from your source through PyCallClassMemberFunc. To see the items you receive from the source, you can just add a trace: if app.ENABLE_SEND_TARGET_INFO: def BINARY_AddTargetMonsterDropInfo(self, raceNum, itemVnum, itemCount): import dbg dbg.TraceError("race num %d, itemVnum %d, itemCount %d" % (raceNum, itemVnum, itemCount)) if not raceNum in constInfo.MONSTER_INFO_DATA: However, I don't see why that would be the problem. Also, from what I see, that function is actually building and updating the MONSTER_INFO_DATA dict, so the problem is probably from __LoadInformation_Drops. Try adding this in uiTarge to see if the dict is still empty when the function is called: def __LoadInformation_Drops(self, race): # this import dbg dbg.TraceError("ConstInfo data: %s" % str(constInfo.MONSTER_INFO_DATA)) self.AppendSeperator()
  13. Good, now that we know that you actually receive the items, you can remove that TraceError. Go to root/uiTarget.py and find def __LoadInformation_Drops(self, race) Then, after if race in constInfo.MONSTER_INFO_DATA in the loop add a couple of traces to find out if it's actually loading and reading the items to and from constInfo. Like this: def __LoadInformation_Drops(self, race): self.AppendSeperator() if race in constInfo.MONSTER_INFO_DATA: if len(constInfo.MONSTER_INFO_DATA[race]["items"]) == 0: self.AppendTextLine(localeInfo.TARGET_INFO_NO_ITEM_TEXT) else: itemListBox = ui.ListBoxExNew(32 + 5, self.MAX_ITEM_COUNT) itemListBox.SetSize(self.GetWidth() - 15 * 2 - ui.ScrollBar.SCROLLBAR_WIDTH, (32 + 5) * self.MAX_ITEM_COUNT) height = 0 #here import dbg for curItem in constInfo.MONSTER_INFO_DATA[race]["items"]: if curItem.has_key("vnum_list"): # here dbg.TraceError("race %d, vnum_list: %d" % (race, curItem["vnum_list"])) height += self.AppendItem(itemListBox, curItem["vnum_list"], curItem["count"]) else: #here dbg.TraceError("race %d, vnum: %d" % (race, curItem["vnum"])) height += self.AppendItem(itemListBox, curItem["vnum"], curItem["count"]) if height < itemListBox.GetHeight(): If it shows the items in syserr, then the problem is from Append, if it doesn't show the items, then the problem is from def BINARY_AddTargetMonsterDropInfo. You could also add some traces before that, just to know where it breaks.
  14. Because line[0] isn't 491. Line[0] is 4(actualy, it is either "4", a string, or '4', a char, I didn't look it up), because 4 is the first character on that line. If you'd want it to work that way, you'd actually have to use it like this: if(GetRace() == atoi(line)) { do something } You have to convert the string(because that's what line is) to a number. Line is ALWAYS a string, no matter what the content of that line is.
  15. Is your map allowed in config? This usually happens when the map doesn't exist in MAP_ALLOW.
  16. Right, skipping the part where it bloody loads the items whenever you click that button, let's find out if you actually get the items in binary. If you do, then the problem is from python/root. In UserInterface/PythonNetworkStreamPhaseGame.cpp Look for: bool CPythonNetworkStream::RecvTargetInfoPacket() In that function find if (pInstTarget->IsEnemy() || pInstTarget->IsStone()) { PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_AddTargetMonsterDropInfo", Py_BuildValue("(iii)", pInfoTargetPacket.race, pInfoTargetPacket.dwVnum, pInfoTargetPacket.count)); PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_RefreshTargetMonsterDropInfo", Py_BuildValue("(i)", pInfoTargetPacket.race)); } And add a TraceError, like this: if (pInstTarget->IsEnemy() || pInstTarget->IsStone()) { TraceError("DROP INFO: item: %d, count: %d", pInfoTargetPacket.dwVnum, pInfoTargetPacket.count); PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_AddTargetMonsterDropInfo", Py_BuildValue("(iii)", pInfoTargetPacket.race, pInfoTargetPacket.dwVnum, pInfoTargetPacket.count)); PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "BINARY_RefreshTargetMonsterDropInfo", Py_BuildValue("(i)", pInfoTargetPacket.race)); } Recompile the binary, click to see the drop of a mob, and then check your syserr to see if it tells you the items.
  17. Why not just add specular to your client's and dump_proto's TMobTable and then just set it while building mob_proto? The client's going to load all of it anyway, so I guess that's the most sensical thing to do. Something like this Add the same thing to your dump_proto's TMobTable, and then, in bool Set_Proto_Mob_Table Add in the beginning char line[256]; FILE* fp; fopen_s(&fp, "myMobsWithSpecularFile.txt", "r"); if (!fp) return false; // using a map just so we don't have to loop over all mobs to see if we have one std::unordered_map<uint8_t, uint8_t> vMobWithSpecular; while (fgets(line, 256, fp)) { if(line[0] == '\n' || line[0] == '#')//skip empty lines and the ones starting with # continue; vMobWithSpecular.emplace(std::make_pair(atoi(line), 1)); } fclose(fp); And at the end, before return just add: if (vMobWithSpecular.find(mobTable->dwVnum) != vMobWithSpecular.end()) mobTable->fSpecular = 1.0f; else mobTable->fSpecular = 0.0f; Now your locale mob_proto has specular and your client will load all of it automatically when building m_NonPlayerDataMap. You'll just have to make a function to get that specular when you want to use it. Something like this: float CPythonNonPlayer::GetMonsterSpecular(DWORD dwVnum) { const TMobTable* c_pTable = GetTable(dwVnum); if (!c_pTable) return 0; return c_pTable->fSpecular; }
  18. What about mob_drop_item? You could've left a link to the system so we can see what's reading and what doesn't. Regards, Amun
  19. Please don't take this the wrong way, I'm just asking because you had a server for a fairly long time, so you have some insight into what's needed to maintain it properly and, most likely, stumbled upon problems(/situations?) that most developers/owners may not take into consideration(or even think about). Going back to our storage discussion, for me it doesn't really make sense to pay for any of them if you're not in the top 1% of the servers(the ones that actually need it). If you have some servers lying around(which most people don't), then yeah, whatever, you do you. IMO, allowing people to download the full client from the main server is a mistake, considering that Google drive and Mega have amazing download speeds and pretty big quotas. Using it for your patcher, yeah, that's fine, most files in one's client will never change, so patching the scripts/locals/exe isn't going to be that big of a deal when you barely make an update a week. TLDR: Don't spend money on unnecessary infrastructure, use GDrive/Mega, and don't offer direct download links from your main server, save the bandwidth for patches and serving the actual website(which is why you got the server in the first place). Yeah, so.. my rant is done, hopefully someone will find it useful. Have a great day, - Amun
  20. Pretty cool stuff! However, I would've liked to see some reasons as to why I would want to set up "a bunch of servers" to serve the data to my players when I could just use a bucket on google cloud or something like Amazon's object storage? I mean, they only cost around 2$ 1$/100GB(0.01$/GB) and they're pretty easy to set up. Any thoughts/feedback on this?
  21. Pretty cool idea. By using what Marty posted here The core reduced memory usage from 471 MB to 221, with a peak of 243 MB when booting(loading).
  22. Do you absolutely have to change the map/relog? Do they not appear if you close and open the inventory/change pages?
  23. CRITICAL: where you see // simplified it means I deleted code that wasn't related to critical calc What you need to know, without reading the code(same for penetration): if your critical chance is equal or over 10, then criticalChance = 5 + (iCriticalPct - 10) / 4 if the chance is less than 10, then cut it in half criticalChance = criticalPct/2 REGEN: The english parts are just translated from korean with google translate, so you can ignore them The idea is: HP Regen is disabled while poisoned. If you're not poisoned, you'll regen every 3 seconds. The important parts: const int aiRecoveryPercents[10] = { 1, 5, 5, 5, 5, 5, 5, 5, 5, 5 }; int iSec = (get_dword_time() - ch->GetLastMoveTime()) / 3000; { iPercent = aiRecoveryPercents[MIN(9, iSec)]; iAmount = 15 + (ch->GetMaxHP() * iPercent) / 100; } iAmount += (iAmount * ch->GetPoint(POINT_HP_REGEN)) / 100; Assuming your iPercent returns 5, with a max hp of 30k and 60% regen(from helmet and necklace) we'll get this: 15 + (30.000 * 5) / 100 = 1515 The amount of hp recovered will be of (1515 * 60) / 100 = 909 every 3 seconds Hope it helps
  24. [Hidden Content] # your method def AddItemData(self, itemVnum, metinSlot, attrSlot = 0, flags = 0, transmutation = -1, window_type = player.INVENTORY, slotIndex = -1, refineElement = 0, isShopItem = 0, window_open = 0): # and your function call is this # arg 1 arg2 arg3 , # then the dev wants to skip these keywords and use the default args for:[flags =0, transm = 0, wnd_t = p.Inv], then assign slotIndex, refineElement and the last argument, which is 1. # 1 is not a keyword argument, so the correct call is with either iShopItem = 1, or window_open=1 to match the keyword asked by the method. self.AddItemData(itemVnum, metinSlot, attrSlot, slotIndex = slotIndex, refineElement = refineElement, 1) #So, one of these are valid calls: self.AddItemData(itemVnum, metinSlot, attrSlot, slotIndex = slotIndex, refineElement = refineElement, isShopItem = 1) #or self.AddItemData(itemVnum, metinSlot, attrSlot, slotIndex = slotIndex, refineElement = refineElement, window_open = 1) # I didn't look at the system, so I don't know which one it is. Figure it out from here. If you didn't understand what I said there, the idea is that you can't use "non-keyword" arguments after "keyword" arguments in a function call. These are your function's params(the keywords): itemVnum, metinSlot, attrSlot, flags, transmutation, window_type, slotIndex, refineElement, isShopItem, window_open '1' is not a keyword. Hope it helps
  25. Let me know if I understood this correctly, please. So, you put the pass in trade, accept, open the quest(teleport), the other person accepts the trade(hence, taking the pass), then click on "accept" in the quest and be teleported without losing the pass, right? Is that what you're trying to fix? Second question: By chat message you mean the PM chat(between 2 players) or the map/global chat?
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.