Jump to content
metin2dev

Leaderboard


Popular Content

Showing content with the highest reputation since 09/18/2017 in all areas

  1. 28 points
    v17.5 Beta new packs are here! New dungeon w/ weapons, armors, mobs, sashes. New Halloween minigame gui files, costumes, pet and mount with 2 textures. And so on.. https://mega.nz/#!OUIyVZDD!ype03n5EIuKbBkz0JzSGHCMHPBtjhZbbwUSYxYgt2ew I wasn't update my proto packer yet. I cannot decrypt the mob_proto because of the changed structure. And the item_proto is containing a lot of new informations, new types, subtypes, applytypes and so on. item_proto: https://mega.nz/#!qBwCmKBC!wYp28d456Npdza9xOHZ5_zjFTQRRhNCtj9rxUtSHurE
  2. 24 points
    Hi here are some new Metin2 Wallpaper Source: Turkmmo
  3. 22 points
    Frankie/M2BobFixed/warxwar/RaFFa is stealing your players' passwords! What does it mean? Everyone who is using his last "ultimate protection" is indirectly sending all his players' users&passwords to his webserver. How? https://imgur.com/a/TqYYC As you can see, he's sending the player's user&pass at login to his remote webserver faking it as "m2bob login". Haha To understand better what's going on, we need to "decrypt" the text. https://i.imgur.com/iq9DuFj.png Why would he do such a thing? Well, it's nothing new that he does retarded things like this. Mostly for his own profit. And also to harm/destroy other servers, since he opened one from stolen server-files. How many servers are now fucked up? There are quite some so far. Is he really skilled? Haha, no. He's a retard. 99.8% of his code comes from stackoverflow.com, and he also was trying to rip-off Koray's protection. He also needs to update the hashes in his protection each time there's a new m2bob version. So, who is Frankie? He's an Italian bipolar guy, and professional liar (he would NEVER NEVER NEVER confess, but he would make some excuses). I taught him python in 2010, but he understood nothing, and I gave up on him. Between 2010-2013 he was just begging for money by doing some quick dirty job in python for random servers. In 2014-2015, he created his m2bobfixed service, and there's quite some people who cried blood because of that. In 2017, he faked that his skype was hacked by romanians to start reselling other people's files. In 2018, he opened a(n infamous) pserver from stolen files, and he's currently stealing users&passwords and private files from all of his "clients". If he joined your PC via teamviewer, or if he sent you some .exe/.dll, it's quite sure he stole something from you. Additional things: 1) He placed the protection inside a folder called "AccountProtect", but in reality it's a password stealer. Can you understand the irony? https://i.imgur.com/PuupV8U.png 2) You can try and decrypt the strings by yourself. Download https://pastebin.com/H9v0heBh then compile n run it: # c++ main.cpp # ./a.out
  4. 21 points
    Hello, This little thing is marks your pet seal into your inventory like the autopotion. This arrives with the v17.5 patch. Open PetSystem.cpp and replace or make it fit for you: void CPetActor::SetSummonItem(LPITEM pItem) { if (NULL == pItem) { LPITEM pSummonItem = ITEM_MANAGER::instance().FindByVID(m_dwSummonItemVID); if (NULL != pSummonItem) pSummonItem->SetSocket(1, FALSE); m_dwSummonItemVID = 0; m_dwSummonItemVnum = 0; return; } pItem->SetSocket(1, TRUE); m_dwSummonItemVID = pItem->GetVID(); m_dwSummonItemVnum = pItem->GetVnum(); } After that open the uiInventory.py and paste this code below the autopotion if-statement in the RefreshBagSlotWindow function. elif itemVnum >= 53001 and itemVnum <= 53256: metinSocket = [player.GetItemMetinSocket(globalSlotNumber, j) for j in xrange(player.METIN_SOCKET_MAX_NUM)]# <!> globalSlotNumber may be different <!> isActivated = 0 != metinSocket[1] if isActivated: self.wndItem.ActivateSlot(i) else: self.wndItem.DeactivateSlot(i)
  5. 20 points
    Hello. I saw this stuff on this and on another board also with bugs or it was incomplete, and I made it to myself. Feel free to use it with your brain. Good to know about this: The name of those items which have attributes will be golden. The skillbook and skillforget items will show the name of skill also. If the item isn't yours than the ownership color will be red instead of yellow. * Készségkönyv = Skillbook(id:50300) * Feledés könyve = Skillforget book(id:70037) PS.: If you have problems with the implementation: start to upgrade your programming knowledges and don't disturb me in private message, I won't answer. Thank you for understanding. https://mega.nz/#!KAh3DQqL!yQQX9o4N8sTsS7Woa4W07C8t5jwp0TV5xg7MHLSFz5Y
  6. 19 points
    I think they forgot to cythonize =)) I don't recommend to use that code, is ugly ... https://mega.nz/#!Ixl0nLZa!61VOx87EA9zBUiNAHD-poUZnaIx3VZr6RVgqUT3LZu4
  7. 18 points
  8. 18 points
    The textures of this water are ideally joined by no visible textures (seams). Colors are well matched to the climate of the metin. Download: You can find the link in the video description! If you want to see more of my work, look here: https://metin2dev.org/board/index.php?/topic/16751-3d-art-tatsumaru/
  9. 16 points
    Hello. I was looking inside the official python files and I found a little fix for this: Let me explain a bit the problem. If you leave open the inventory/dragon soul inventory/expanded taskbar or the affected objects and then you are using quest for teleportation, the windows what you left open will be closed because of the quest and when the quest executed those windows what you left open before would be opened again, but the warp is killing this procedure and that happens what you can see in the video, the windows are there but you cannot see them. Btw you can close them with escape key. The fix is coming from webzen: Simple, just execute a .Hide() function before the Destroy function has been called on that object what is stuck on the main window after teleport and that's it. For example: interfaceModule.py -> Interface class -> Close function: if self.wndInventory: self.wndInventory.Hide()#fix self.wndInventory.Destroy() if self.wndDragonSoul: self.wndDragonSoul.Hide()#fix self.wndDragonSoul.Destroy()
  10. 15 points
    Hello, pretty sure anyone of you knows about the Dispel and Heal Lag problem that has been around since always. This little modification will fix both these problems completely. (Thanks @Horinna for helping with the in-game tests) Problem: The RemoveAffect function calls ComputePoints() (Complete rearrange of all the player stats and equip parts, one of the heaviest checks). The correct function to use is RefreshAffect() which does its job pretty fine! But that's not the only problem: Based on the current code, that function would get called every single time an affect gets removed or added, while it should only get called once, at the end of the process. Solution: We could make new functions for those 2 special flags (REMOVE_BAD_AFFECT and REMOVE_GOOD_AFFECT), but in order to keep things simple for you guys, i'll simply "dynamicize" the RemoveAffect function. 1. go to char_affect.cpp: 2: go to char.h: This way, we applied a simple boolean value arg to the RemoveAffect function, which will get set to true by default. By setting it to false like this RemoveAffect(affectLUL, false); we are basically saying the game to not Rearrange the points when affectLUL gets removed. now we will use a cycle to do that for every affect like usual, and we will rearrange of the points just once, at the end of the process, like it should be. 3. In char_affect.cpp: Done! Comparison:
  11. 14 points
    Hey there, I have an Halloween gift for you all. i have been working for a few hours on official like element image on target window(See screenshots below). When you click on a mob if it is defined as elemental, it will open an element image in addition to the target window. Don't forget to hit the like button! (C) Metin2 guild wars - coded by [GA]Ruin - 27/10/2017 (I create custom metin2 systems in c++/python. if you want a custom system send me a pm and we can talk over skype). Client files: element_image_client_files.rar Let's begin! Server Side: Open service.h, add in the end: #define ELEMENT_TARGET Open char.cpp, search for else { p.dwVID = 0; p.bHPPercent = 0; } add below: #ifdef ELEMENT_TARGET const int ELEMENT_BASE = 11; DWORD curElementBase = ELEMENT_BASE; DWORD raceFlag; if (m_pkChrTarget && m_pkChrTarget->IsMonster() && (raceFlag = m_pkChrTarget->GetMobTable().dwRaceFlag) >= RACE_FLAG_ATT_ELEC) { for (int i = RACE_FLAG_ATT_ELEC; i <= RACE_FLAG_ATT_DARK; i *= 2) { curElementBase++; int diff = raceFlag - i; if (abs(diff) <= 1024) break; } p.bElement = curElementBase - ELEMENT_BASE; } else { p.bElement = 0; } #endif open packet.h, search for: } TPacketGCTarget; add above: #ifdef ELEMENT_TARGET BYTE bElement; #endif Client side: open locale_inc.h, add in the end: #define ELEMENT_TARGET open packet.h, search for } TPacketGCTarget; add above: #ifdef ELEMENT_TARGET BYTE bElement; #endif open PythonNetworkPhaseGame.cpp, look for: else if (pInstPlayer->CanViewTargetHP(*pInstTarget)) replace below with the following: #ifdef ELEMENT_TARGET PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(iii)", TargetPacket.dwVID, TargetPacket.bHPPercent, TargetPacket.bElement)); #else PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(ii)", TargetPacket.dwVID, TargetPacket.bHPPercent)); #endif open PythonApplicationModule.cpp, look for #ifdef ENABLE_ENERGY_SYSTEM add above: #ifdef ELEMENT_TARGET PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 0); #endif open game.py, look for def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show() replace with: if app.ENABLE_VIEW_ELEMENT: def SetHPTargetBoard(self, vid, hpPercentage,bElement): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.SetElementImage(bElement) self.targetBoard.Show() else: def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show() open uitarget.py, look for import background add below: if app.ENABLE_VIEW_ELEMENT: ELEMENT_IMAGE_DIC = {1: "elect", 2: "fire", 3: "ice", 4: "wind", 5: "earth", 6 : "dark"} look for: self.isShowButton = False add below: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None inside Destroy method, look for: self.__Initialize() add below: if app.ENABLE_VIEW_ELEMENT: self.elementImage = None inside ResetTargetBoard method, look for: self.hpGauge.Hide() add below: if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None look for : def SetElementImage(self,elementId): add above: if app.ENABLE_VIEW_ELEMENT: def SetElementImage(self,elementId): try: if elementId > 0 and elementId in ELEMENT_IMAGE_DIC.keys(): self.elementImage = ui.ImageBox() self.elementImage.SetParent(self.name) self.elementImage.SetPosition(-60,-12) self.elementImage.LoadImage("d:/ymir work/ui/game/12zi/element/%s.sub" % (ELEMENT_IMAGE_DIC[elementId])) self.elementImage.Show() except: pass Compile server, client source and root pack and that's it! Enjoy! Happy halloween! element_image_client_files.rar
  12. 14 points
    I made a sequence generator script. You can find it in here: https://github.com/martysama0134/how-to-mt2-general/tree/master/sequence-generator This python script automatically generates the sequence table for `EterLib\NetStream.cpp` (in `s_bSequenceTable`) and `game\src\sequence.cpp` (in `gc_abSequence`). (the keys get changed every time you run the script) A sequence table is just a simple random generated array with 16x2048 bytes between 0x0 and 0xfe. Replacing the sequence table makes older/unwanted launchers unable to access the server.
  13. 14 points
    Version 1.0 Hair pinned with Japanese pins for shaman girl. - a face with artificial shadow on the texture was added to the hair. This solution recompense to some extent the lack of shadows in the game engine - the model is carefully crafted - the model has a hair icon - the texture is in good quality NOTE: Please do not change hair to other characters class. The hair looks just fine only on shaman girl. Do not spoil it. Comment or Like = more good models, remember.
  14. 14 points
    Definitely DevDick. You can find him several times dicking around in this new leaked root: (screenshot by Syreldar)
  15. 13 points
  16. 13 points
    (Video at the end) Lockpicking is the new system which allows you to train special ability. This ability upgrade your skill of opening new boxes which are on maps(like npc). Every level gives higher chance to open box and probability to get more rewards. To train Lockpicking skill players have to read special books. You can set the level from which players can use this system. Maximum level of skill is 40, but it's configurable. Player can check how many boxes found. System support multilang servers. Missions Additionaly you will get special missions for this sytem, you can easily configure them or add new ones(just add new item to the table). After finished mission player receive reward directly in Quest Scroll. Configuration ItemShop Also you can earn some money from itemshop by this system : ) Magical key rises you chance to open box to 100%, but count of items which you can get from box still depends on skill level. The Key can be used only 10 times. Download & Scan http://www19.zippyshare.com/v/ECjEXsuj/file.html https://www.virustotal.com/#/file/d4fb8b52a8ed74f3a2fbf74efdbd2cc2c042ed82b243fea4d7d18561fa206750/detection
  17. 11 points
    https://i.imgur.com/TBOcLui.gifv uiCommon.py class ItemQuestionDialog(ui.ScriptWindow): def __init__(self): ui.ScriptWindow.__init__(self) self.__CreateDialog() self.tooltipItem = uiToolTip.ItemToolTip() self.toolTip = uiToolTip.ToolTip() self.window_type = 0 self.count = 0 self.dropType = 0 self.dropCount = 0 self.dropNumber = 0 def __del__(self): ui.ScriptWindow.__del__(self) def __CreateDialog(self): pyScrLoader = ui.PythonScriptLoader() pyScrLoader.LoadScriptFile(self, "QuestionDialog.py") self.board = self.GetChild("board") self.textLine = self.GetChild("message") self.acceptButton = self.GetChild("accept") self.cancelButton = self.GetChild("cancel") self.titleBar = ui.TitleBar() self.titleBar.SetParent(self.board) self.titleBar.MakeTitleBar(244, "yellow") self.titleBar.SetPosition(8, 7) self.titleBar.Show() self.titleName = ui.TextLine() self.titleName.SetParent(self.titleBar) self.titleName.SetPosition(0, 4) self.titleName.SetWindowHorizontalAlignCenter() self.titleName.SetHorizontalAlignCenter() self.titleName.Show() self.slotList = [] for i in xrange(3): slot = ui.ImageBox() slot.LoadImage("d:/ymir work/ui/public/slot_base.sub") slot.SetParent(self) slot.SetWindowHorizontalAlignCenter() self.slotList.append(slot) def Open(self, vnum, slot = None, price = None): item.SelectItem(vnum) xSlotCount, ySlotCount = item.GetItemSize() try: if self.window_type == "inv": metinSlot = [player.GetItemMetinSocket(player.INVENTORY, slot, i) for i in xrange(player.METIN_SOCKET_MAX_NUM)] elif self.window_type == "shop": metinSlot = [shop.GetItemMetinSocket(slot, i) for i in xrange(player.METIN_SOCKET_MAX_NUM)] except: pass if vnum in (50300, 70037): self.titleName.SetText("%s %s" % (skill.GetSkillName(metinSlot[0]), item.GetItemName())) elif vnum == 70104: self.titleName.SetText("%s %s" % (nonplayer.GetMonsterName(metinSlot[0]), item.GetItemName())) else: self.titleName.SetText(item.GetItemName()) newHeight = 0 if price: newHeight = 20 itemPrice = ui.TextLine() itemPrice.SetPosition(0, 77 + 32*ySlotCount) itemPrice.SetWindowHorizontalAlignCenter() itemPrice.SetHorizontalAlignCenter() itemPrice.SetVerticalAlignCenter() itemPrice.SetParent(self.board) if str(price).isdigit(): itemPrice.SetText(localeInfo.NumberToMoneyString(price)) else: itemPrice.SetText(price) itemPrice.Show() self.itemPrice = itemPrice slotGrid = ui.SlotWindow() slotGrid.SetParent(self) slotGrid.SetPosition(-16, 62) slotGrid.SetWindowHorizontalAlignCenter() slotGrid.AppendSlot(0, 0, 0, 32*xSlotCount, 32*ySlotCount) slotGrid.AddFlag("not_pick") slotGrid.Show() self.slotGrid = slotGrid if self.count > 1 and vnum != 1: self.slotGrid.SetItemSlot(0, vnum, self.count) else: self.slotGrid.SetItemSlot(0, vnum) self.SetSize(260, 110 + 32*ySlotCount + newHeight) self.board.SetSize(260, 110 + 32*ySlotCount + newHeight) self.textLine.SetPosition(0, 44) for i in xrange(min(3, ySlotCount)): self.slotList[i].SetPosition(0, 30 + ySlotCount*32 - i*32) if vnum != 1: self.slotList[i].OnMouseOverIn = lambda arg = slot: self.OverInItem(arg) self.slotList[i].OnMouseOverOut = lambda arg = self.tooltipItem: self.OverOutItem(arg) else: self.slotList[i].OnMouseOverIn = lambda arg = localeInfo.MONETARY_UNIT0: self.OverInToolTip(arg) self.slotList[i].OnMouseOverOut = lambda: self.OverOutToolTip() self.slotList[i].Show() self.GetChild("accept").SetPosition(-40, 74 + 32*ySlotCount + newHeight) self.GetChild("cancel").SetPosition(40, 74 + 32*ySlotCount + newHeight) self.titleBar.SetCloseEvent(ui.__mem_func__(self.Close)) self.SetCenterPosition() self.SetTop() self.Show() def SetCloseEvent(self, event): self.titleBar.SetCloseEvent(event) def SetMessage(self, text): self.textLine.SetText(text) def OverInToolTip(self, arg): self.toolTip.ClearToolTip() self.toolTip.AppendTextLine(arg, 0xffffff00) self.toolTip.Show() def OverOutToolTip(self): self.toolTip.Hide() def OverInItem(self, slot): if self.window_type == "shop": self.tooltipItem.SetShopItem(slot) elif self.window_type == "inv": self.tooltipItem.SetInventoryItem(slot) def OverOutItem(self, tooltipItem): if None != tooltipItem: self.tooltipItem.HideToolTip() self.tooltipItem.ClearToolTip() def Close(self): self.ClearDictionary() self.slotList = [] self.titleBar = None self.titleName = None self.itemPrice = None self.slotGrid = None self.toolTip = None self.tooltipItem = None self.Hide() constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(0) def SetWidth(self, width): height = self.GetHeight() self.SetSize(width, height) self.board.SetSize(width, height) self.SetCenterPosition() self.UpdateRect() def SAFE_SetAcceptEvent(self, event): self.acceptButton.SAFE_SetEvent(event) def SAFE_SetCancelEvent(self, event): self.cancelButton.SAFE_SetEvent(event) def SetAcceptEvent(self, event): self.acceptButton.SetEvent(event) def SetCancelEvent(self, event): self.cancelButton.SetEvent(event) def SetText(self, text): self.textLine.SetText(text) def SetAcceptText(self, text): self.acceptButton.SetText(text) def SetCancelText(self, text): self.cancelButton.SetText(text) def OnPressEscapeKey(self): self.Close() return True add imports import constInfo import skill import nonplayer This is just a class, now you just have to call it itemQuestionDialog = uiCommon.ItemQuestionDialog() itemQuestionDialog.window_type = "inv" #for inventory itemQuestionDialog.window_type = "shop" #for shops itemQuestionDialog.count = ... drop MONEY itemQuestionDialog.Open(1, "", attachedMoney) drop ITEM itemQuestionDialog.Open(itemVNum, slotNumber) buy&sell ITEM itemQuestionDialog.Open(itemVNum, slotNumber, price)
  18. 10 points
    Hello people, i saw that a lot of people want to start developing on Metin2, but there isn't a place where the people can easly see tutorials without surf the whole internet. My idea is to create a reference for anyone who want to start creating his own server, starting from the first steps into the creation of a full Metin2 Server, but also a place where advanced developers could orient into the complicated parts of this world. The special thing about this wiki is that everyone could add or alter pages (that will be approved by moderators), so everyone could contribute to the wiki. The wiki his hosted inside a website that i own (it would be very complicated handle this kind of project inside any forum). At the monent, the wiki is started and it's only in english. (Translation system will be added, contact me if you would like to translate) The wiki will be completly free and without any kind of advertisement. (But altervista's limitated band could make the site unaccessible) Link here: https://rewardmetin2.altervista.org/index.php?title=Main_Page. Greets!
  19. 10 points
    Some years ago I created a (python2) script to generate xtea keys randomly, here it is: xtea-keys-generator.rar You can also find it in here: https://github.com/martysama0134/how-to-mt2-general/tree/master/xtea-keys-generator It generates the code for EterNexus, for EterPack.cpp, and also the hex string you see inside the compiled launcher.
  20. 10 points
    Please stop posting this ...
  21. 10 points
    I want a ferrari, ships and bitches. TY
  22. 9 points
    Hi devs, today I will release the fix I made for the skill cooldown, already fixed on official servers, this is the bug it self: And this is the fix: Regards! Fix skill cooldown ~ Shang.rar ### root/ui.py ### Search: def SetSlotCoolTimeColor(self, slotIndex, r, g, b, a): wndMgr.SetSlotCoolTimeColor(self.hWnd, slotIndex, r, g, b, a) ### Add after: def StoreSlotCoolTime(self, key, slotIndex, coolTime, elapsedTime = 0.0): wndMgr.StoreSlotCoolTime(self.hWnd, key, slotIndex, coolTime, elapsedTime) def RestoreSlotCoolTime(self, key): wndMgr.RestoreSlotCoolTime(self.hWnd, key) Thanks to @Horinna for report that bug. Here's the fix: """ Find this: elif (not self.__CanUseSkillNow()) or (skillGrade != j): skillPage.SetSlotCount(realSlotIndex, 0) skillPage.DisableCoverButton(realSlotIndex) Add this under:""" skillPage.DeactivateSlot(realSlotIndex) # After the else, paste this: if player.IsSkillActive(slotIndex) and (skillGrade == j): # fix001 skillPage.ActivateSlot(realSlotIndex) # The if should look like this: if (skillGrade == skill.SKILL_GRADE_COUNT) and j == (skill.SKILL_GRADE_COUNT-1): skillPage.SetSlotCountNew(realSlotIndex, skillGrade, skillLevel) elif (not self.__CanUseSkillNow()) or (skillGrade != j): skillPage.SetSlotCount(realSlotIndex, 0) skillPage.DisableCoverButton(realSlotIndex) skillPage.DeactivateSlot(realSlotIndex) # fix else: skillPage.SetSlotCountNew(realSlotIndex, skillGrade, skillLevel) if player.IsSkillActive(slotIndex) and (skillGrade == j): # fix skillPage.ActivateSlot(realSlotIndex)
  23. 9 points
  24. 9 points
    Can you code better then them? I'm sure you don't have 0.5% (percent) from them knowledges in programming. You understand how it's work a def function, for, while, if, else, elif statement and know to declare a list etc and you think you are a guru on python? and you can criticize developers who have over 10 years on programming? If you was a man who have some years experience in programming you never criticize guys like them, because know how it's work that domain, you can refactor on every day your code, and all time exist "better then previous version", you think they do all efforts to make the code full organized & clean & pro & perfectly? No employee will do that, after a lot a years on domain, you don't care too much how code looks or how much optimized is it, if is working well. Especially if they are paid with a low sallary, they will not do the best. If i put you to explain some functions of them code you get mind fuck, because you are at a very low level. A lot a people talk about "shit code", and most of them (98%) doesn't know how to use a list/dict comprehension or a map, filter, lambadas, generators on python. Also if you think you are more good then them, then rewrite the game as you like it, or do your own MMORPG. < sarcasm level 999 PS: I just saying my point of view, don't need to approve or disapprove it.\ Sorry for the english level 999. Was a joke.
  25. 9 points
    Hi to everyone! Almost everyday i have messages about new christmas map for this year. Yeah as every year im working on map for christmas. The map will be 7x3, including cave and christmas city! Im working on monsters and other christmas stuff right now Here are first images:
×