![]() |
Chest Editor and Tiles - Printable Version +- Mirage Engine (https://mirage-engine.uk/forums) +-- Forum: Mirage Source (Nostalgia) (https://mirage-engine.uk/forums/forumdisplay.php?fid=61) +--- Forum: Archive (2006-2011) (https://mirage-engine.uk/forums/forumdisplay.php?fid=18) +---- Forum: Resources (https://mirage-engine.uk/forums/forumdisplay.php?fid=49) +---- Thread: Chest Editor and Tiles (/showthread.php?tid=36) |
Chest Editor and Tiles - funkynut - 01-06-2006 ----===== Chest Tile tutorial =====---- Difficulty: 3/5 All this tutorial will do is allow chests to be placed on tiles, display them being opened and closed, allow you to block players from opening them a second time and update the chests. This isn’t exactly based on anything else, though I did advise someone to try copying what’s already in the code I’m doing it this way because I can implement features better like this =) Overview (Written after finishing this) When this is finished you should be able to create a chest with the help of a chest editor that will display 3 item lists that will also give the name, type of item and the picture once you’ve clicked on an item. You can also set if a player is able to open the chest more then once and if the chest is edited then a player is automatically able to reopen the new chest. Only problem with this is that if you use two or more of the same chests anywhere and one is opened, they are all set as opened until the time set to close after has elapsed, same for if the player is only allowed to open the chest once, even if they open the same map in a different location it will count as the same map. ![]() ^^^ ChestEditor ![]() ^^^ Chest Tile Ok, Lets start by adding a Chest type that will basically describe a new data type and what it will store (Like chest items etc) Add the following code to the bottom of modTypes in both server and client Code: Type ChestRec Now we need to add a constant that dictates how many different chests can be made add one time, so in both Client and server in modConstants find’MAX_PLAYERS’ and under it, add: Code: Public Const MAX_CHESTS = 100 Now we need to actually make the variable that will store each chests detail so find in both Server and clients Code: Public Spell(1 To MAX_SPELLS) As SpellRec And add under it add Code: Public Chest(1 To MAX_CHESTS) As ChestRec Now, add a new form to the client, and change the following properties Name - frmChestEditor BorderStyle - 1 - Fixed Single Caption - Chest Editor StartUpPosition - 2 - Center Screen Now, add a textbox somewhere (This will be the chest name) Name - txtName Text - (empty) Now add three ListBoxes and for each one change the properties to Name - lstItem Index - Give the 1st listbox 1 2nd listbox 2 3rd listbox 3 Add 3 Labels, each one under the Listboxes above, then Change the properties to Name - lblItemName Alignment - 2 - Center Caption - Item Name Index - 1, 2, 3 (Corresponding to the listboxs above them) Yet again, add another 3 labels under the above labels Name - lblItemType Alignment - 2 - Center Caption - Item Type Index - 1, 2, 3 (Corresponding to the labels above them) Now we need some Picture boxes for the items to blt into, so start this off by adding three picture boxes under the label you’ve just added and change the properties to these: Name - picItem Index - 1, 2, 3 (Same as above, give it the same index as the objects above it) Height - 480 (32 pixels) Width - 480 (32 Pixels) Yay, still more to come, add a checkbox and the change the properties to; Name - chkOpenAgain Caption - Open Once Time for the objects that will help with how the long the chest will be open for =) Add a Horizontal Scrollbar (or vertical which ever you prefer) Name - scrlTime LargeChange - 100 Max - 32767 Value - 10 Min - 1 Now a label Name - lblTime Caption - 10 And a textbox Name - txtTime Text - 10 And finally add two command buttons Name - cmdSave and cmdCancel Cancel - cmdCancel = true Default - cmdSave = true Now all you need to do is add a few labels to show what each thing does. Once you’ve done that, you should have a form that looks something like this… ![]() Now a bit of code for the form, this is all the code that will go into this form, but it’ll do for now Double Click on the cancel button and add Code: Unload me Now we need the scrollbar to change the textbox and the label that display the same value so double click the scrollbar and add Code: ' --- Change the values for the txt and lbls Code: ' --- Check if the time entered is within range and is actually a number Code: ' Map Editor Code: ' Chest Editor Basically, it checks if the first 12 letters = /chesteditor and if it is, it will send a packet to the server requesting chest editor and will then clear the text onscreen. Now we need code for the server to run once it’s received the packet so find in the server: Code: ' ::::::::::::::::::::::::::::: Code: ' ::::::::::::::::::::::::::::::: Now, we need to allow the client to do something when we receive the packet so find in the client: Code: ' :::::::::::::::::::: And under it add: Code: ' ::::::::::::::::::::::::: This pretty much opens up index form and lists all the chest names down in the list and also set a flag (InChestEditor) so we know what were meant to be editing. Now, we need to declare the flag so find: (Still in the client) Code: Public InSpellEditor As Boolean Code: Public InChestEditor As Boolean Now you also need to find Code: InSpellEditor = False Code: InChestEditor = False Code: If InSpellEditor = True Then And under that, add Code: If InChestEditor = True Then Now this is the part where the server actually sends the chest details to the client for editing so find what you added earlier in the server Code: ' ::::::::::::::::::::::::::::::: Now underneath it add: Code: ' ::::::::::::::::::::::: Also find Code: Sub SendPlayerXY(ByVal Index As Long) And add: Code: Sub SendEditChestTo(ByVal Index As Long, ByVal ChestNum As Long) The code above just sends one of the chests details to the client ready to be viewed and edited. The client needs to interpret this, so find what you did earlier: Code: ' ::::::::::::::::::::::::: And add under it: Code: ' ::::::::::::::::::::::: Now, we need to create the sub ‘ChestEditorInit’ that we’ve called in the above piece of code, all the sub does is load the details onto the Chest Editor form then loads the form, so find the sub Code: Public Sub ItemEditorBltItem() Code: Public Sub ChestEditorInit() Ok, now we need to add some more code to the chest editor, this new bit of code will add the ability to view item picture, name and type when we click on it. First let’s deal with getting the item name. Double click on one of the listbox on the chest editor window and add this piece of code: Code: If frmChestEditor.lstItem(Index).ListIndex > 0 Then This just checks if an item is selected, if it is, it will retrieve the item name, if not it will just replace it with N/A Now we need to change the item type label, so under Code: lblItemName(Index).Caption = Trim(Item(lstItem(Index).ListIndex).Name) Code: Select Case Item(lstItem(Index).ListIndex).Type This may look like quite a bit but its nothing really, all it is checking what type it is, and depending on the type of item, will change the label to different text Also, under the other bit you just added Code: lblItemName(Index).Caption = "N/A" Code: lblItemType(Index).Caption = "N/A" TADA Now the form displays the item details, but now we can go one step better and display a picture. I’m not going to do this the normal way where another copy of the items.bmp is loaded into a picture box since that wastes so much memory considering its already loaded into a direct draw surface, so I’m going to do some blting!! YAY! *cough* Anyway, since a lot of you don’t understand how to blt, I’m going to try explain this as easy as I can (But don’t expect miracles, since I suck at explaining things) First, we’ll start by adding a timer, that every time is set off, will draw the item back into the picture boxes, so create a timer called ‘tmrBlt’ with an interval of 50. Then add this code Code: Dim n As Integer DC = DD_ItemSurf.GetDC This is like an address to the surface which we need to be able to blt something directly from the direct draw surface, only problem is that by doing this, we lock up the surface (I’ll tell you how to unlock it later) For n = 1 To 3 If lstItem(n).ListIndex > 0 Then Call BitBlt(picItem(n).hdc, 0, 0, PIC_X, PIC_Y, DC, 0, Item(lstItem(n).ListIndex).Pic * PIC_Y, SRCCOPY) Else picItem(n).Refresh End If Next n That is the main section, all it does it runs through each picture box, checks if there’s an item selected in the list box, if there isn’t, it clears the picture box to make it blank by using the refresh function. If there is an item to be bltted then it will call bitblt. The first argument, picitem(n).hdc is basically the address for the picture box that were drawing to The next two arguments are the x,y coordinates and since we want to blt it at the very top corner of the picture box, we have it as 0,0 The next two following them are the width, and height, and for both I have used a constant which at default are both 32 (Same size as the picture box) Onto the next argument, this is where we supply the address to the source, which in this case is the direct draw surface, which if you remember, we saved to the variable DC Next two arguments are the source x,y. Since we start on the very left of the item sheet, x = 0, but since y changes depending on the item, we find out what picture number the item is assigned, then we multiply by 32(pic_y) pixels to get the actual location on the items sheet The final Argument tells it what type of blt to perform, there are many different types, depending on what effects you want but this one (SRCCOPY) just copies the image directly over as it is The final piece of text (Call DD_ItemSurf.ReleaseDC(DC)) is the part that unlocks the surface we used as a source Ok so we’ve done the bltting part, but we just need to quickly edit the cancel button before we go onto Double click cancel button and add this under unload me Code: InChestEditor = False Ok, now we need to make another addition to the chest editor. The ability to select what the chest looks like while open or closed, so open up frmChestEditor and add two more picture boxes and a command button and change properties to these: First Picture Box;- Name - picOpen Borderstyle - 0 –None Width -480 (32 pixels, or equal to pic_x) Height - 480 (32 Pixels, or equal to pic_y) Second Picture Box;- Name - picClose Borderstyle - 0 –None Width -480 (32 pixels, or equal to pic_x) Height - 480 (32 Pixels, or equal to pic_y) Command Button;- Name -cmdTile Caption - View Tiles Now double click cmdTile and add this code Code: frmTiles.Show Now we need to add a new form that will display all the tiles, don’t ask why I decided to put it in a new form, just felt like it =D Anyway, you need to add the following controls Timer = Name – tmrBlt interval – 50 Picture Box = Name – picTiles Height – 5760 Width – 3360 ScrollBar(Best horizontal) = Name – scrlTiles Now, I’m not going to tell you what the code does that I’m about to give you since its pretty explanatory so replace all the code in frmTiles with the following Code: Option Explicit Code: ChestEditorInit Code: ChestClosedX = Chest(EditorIndex).ClosedTileX Now’s the part where we start doing something, we now have to send the update to the server, and be able to save and load the chests from file. First lets send the update to the server, double click cmdSave and input this code Code: With Chest(EditorIndex) Now for the Sub that organises the info that’s to be send, find Code: Public Sub SendSaveItem(ByVal ItemNum As Long) Code: Public Sub SendSaveChest(ByVal chestnum As Long) Code: ' ::::::::::::::::::::::: Code: ' ::::::::::::::::::::::: Yay, done the majority of the work, now all we got to do is check if a player can open it and gain a prize and then close it after. First, we need to add two temp variables to the chest type server side, so find type ChestRec in the server and in the bottom add Code: ' --- Some temp stuff Also, in both the client and server, find Code: Public Const TILE_TYPE_KEYOPEN = 6 Code: Public Const TILE_TYPE_CHEST = 7 We now need to add the chest tile to map editor with a new form to allow a chest to be placed on the map, so first add an option button onto the attributes frame called optChest and double click it and add the code Code: frmMapchest.show vbmodal For the people who don’t know what vbmodal does, it just pretty much loads the form on top of the owner (if not specified, like here, it’s just the form it was called from) and doesn’t allow control to the form owner until the window is closed. Ok, so make a new form and change the following properties Name - frmMapChest BorderStyle - Fixed Style ShowInTask - False Now add the following controls and edited properties ListBox Name - lstChest 3 Labels Name - lblItem Index - 1,2, 3 Two command buttons Name -cmdOK and cmdCancel Cancel -cmdCancel = true Default -cmdOk = true Ok, in this form, will be a list with chest names and every time we click on a chest name, the 3 labels will update with what the chests contain so when we load the form, we need to make a request to the server for the chest names and items so add the following to the bottom of modClientTcp Code: Public Sub SendChestInfoRequest() Then in the server at the bottom of modHandleData within the main sub add the following Code: ' ::::::::::::::::::::::: This doesn’t do much, if the chest packet arrives, it will create a packet consisting of chest names and the items to be sent back to the client. Now we need to do something similar to the client, so at the bottom of modHandleData in the client (Again in the main sub) add the following Code: ' ::::::::::::::::::::::: Ok, find in the client Code: ' Used for map key opene ditor And under it add the following variable Code: ' Used for Chest ditor Now open up the frmMapChest form again and copy and paste the following code into it Code: Option Explicit Again, not much interesting there so I don’t think it warrants an explanation Ok, find Code: If frmMirage.optKeyOpen.Value = True Then And under it add Code: If frmMirage.optChest.Value = True And ChestListNum > 0 Then Find: Code: If .Type = TILE_TYPE_KEYOPEN Then Call DrawText(TexthDC, x * PIC_X + 8, y * PIC_Y + 8, "O", QBColor(White)) And under it add Code: If .Type = TILE_TYPE_CHEST Then Call DrawText(TexthDC, x * PIC_X + 8, y * PIC_Y + 8, "C", QBColor(Yellow)) Not much here but this is still quite important, after all what are the mappers going to do if they cant see where they’ve placed the chest tiles. I’ll go into a bit of an explanation of what this does, the first argument, TexthDC is just the ‘address’ to the surface we are going to blt the text on. The next two arguments are the x,y arguments (no need to explain them I think) The following argument is the text that were going to blt, hence were bltting the letter c onto the tile The final argument is the colour, you can either use rgb() to get a colour, or use the visual basic built in ones that you can call using qbcolor() Yay, not much to go now, all we need to do is edit a bit of code to stop players walking over chests, code to blt the chests on map and a bit more to allow players to open the chests. Let’s start with blocking players if they try to walk over the chests Starting Client side, find in sub CanMove Code: If Map.Tile(GetPlayerX(MyIndex), GetPlayerY(MyIndex) - 1).Type = TILE_TYPE_BLOCKED Then Swap that with Code: If Map.Tile(GetPlayerX(MyIndex), GetPlayerY(MyIndex) - 1).Type = TILE_TYPE_BLOCKED Or Map.Tile(GetPlayerX(MyIndex), GetPlayerY(MyIndex) - 1).Type = TILE_TYPE_CHEST Then Find Code: If Map.Tile(GetPlayerX(MyIndex), GetPlayerY(MyIndex) + 1).Type = TILE_TYPE_BLOCKED Then Swap that with Code: If Map.Tile(GetPlayerX(MyIndex), GetPlayerY(MyIndex) + 1).Type = TILE_TYPE_BLOCKED Or Map.Tile(GetPlayerX(MyIndex), GetPlayerY(MyIndex) + 1).Type = TILE_TYPE_CHEST Then Again, find Code: If Map.Tile(GetPlayerX(MyIndex) - 1, GetPlayerY(MyIndex)).Type = TILE_TYPE_BLOCKED Then And change that with Code: If Map.Tile(GetPlayerX(MyIndex) - 1, GetPlayerY(MyIndex)).Type = TILE_TYPE_BLOCKED Or Map.Tile(GetPlayerX(MyIndex) - 1, GetPlayerY(MyIndex)).Type = TILE_TYPE_CHEST Then And find Code: If Map.Tile(GetPlayerX(MyIndex) + 1, GetPlayerY(MyIndex)).Type = TILE_TYPE_BLOCKED Then And change that with Code: If Map.Tile(GetPlayerX(MyIndex) + 1, GetPlayerY(MyIndex)).Type = TILE_TYPE_BLOCKED Or Map.Tile(GetPlayerX(MyIndex) + 1, GetPlayerY(MyIndex)).Type = TILE_TYPE_CHEST Then That change alone is enough to stop most players, but if there’s someone with a hacked, or old client, they wont be stopped so we need to change server side aswell, so find in sub PlayerMove Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index), GetPlayerY(Index) - 1).Type TILE_TYPE_BLOCKED Then And change that with Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index), GetPlayerY(Index) - 1).Type TILE_TYPE_BLOCKED And Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index), GetPlayerY(Index) - 1).Type TILE_TYPE_CHEST Then Same with Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index), GetPlayerY(Index) + 1).Type TILE_TYPE_BLOCKED Then And change that with Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index), GetPlayerY(Index) + 1).Type TILE_TYPE_BLOCKED And Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index), GetPlayerY(Index) + 1).Type TILE_TYPE_CHEST Then Yet again, find Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index) - 1, GetPlayerY(Index)).Type TILE_TYPE_BLOCKED Then swap with Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index) - 1, GetPlayerY(Index)).Type TILE_TYPE_BLOCKED And Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index) - 1, GetPlayerY(Index)).Type TILE_TYPE_CHEST Then Yet again, find Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index) + 1, GetPlayerY(Index)).Type TILE_TYPE_BLOCKED Then swap with Code: If Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index) + 1, GetPlayerY(Index)).Type TILE_TYPE_BLOCKED And Map(GetPlayerMap(Index)).Tile(GetPlayerX(Index) + 1, GetPlayerY(Index)).Type TILE_TYPE_CHEST Then Ok, time for the OPENING CHEST part, woooo000ooo Server side in modHandleData locate Code: If LCase(Parse(0)) = "attack" Then Code: ' Check for chests infront of the player All this does is looks for a chest in front of the player and calls the sub that will soon do all the item giving Now we need to create the routine that will do all the opening chest business so open up modGameLogic server side and at the bottom at Code: Public Sub OpenChest(ByVal Index As Long, ByVal ChestNum As Long) Pretty basic, checks if it’s a valid chest then checks if the chest is still open from someone else. It will then follow that by checking if a user has opened it before by checking what version the chest was when they last opened it (If they have) and if it’s the same as current version, then shouldn’t allow them (that is if the chest disallows it) Now then, we now know the user can open the chest so lets do it, first we give the user the 3 items (If one of the items is blank, I wont do anything) and following that it will try construct a message depending on how many items were collected Need to add a quick edit to the client, find the ChestRec type and add to the bottom Code: AlreadyOpen As Boolean Now add the following to the bottom of the main sub in modHandleData Code: ' ::::::::::::::::::::::: These two packets handle the open and closed chest packets from the server which are used for deciding if a chest is to be blted with an open or closed tile. Now for some actual bltting, add the following sub to the bottom of modGameLogic Code: Public Sub BltChest(ByVal ChestNum As Long, ByVal X As Long, ByVal Y As Long) And then find Code: Call BltTile(X, Y) Code: If Map.Tile(X, Y).Type = TILE_TYPE_CHEST Then Now for the final bit, getting the server to close the chests so find Code: ' Check for disconnections And add under it Code: ' --- Check to Close Chests Also declare TotalTime at the top of the sub That’s the tut finished, horay, not much else to say, I started rushing this towards the end since this amazingly took me 3 nights =/ (mainly because I kept watching tv, doing coursework or playing games every 10 mins) Ok, forgot one small part that updates the chests for players, find in the server Code: Sub SendItems(ByVal Index As Long) And under that sub add the following sub Code: Sub SendChests(ByVal Index As Long) Also find in modHandleData in the server Code: ' Save it Code: Call SendDataToAll("CHESTUPDATE" & n & SEP_CHAR & Chest(n).ClosedTileX & SEP_CHAR & Chest(n).ClosedTileY & SEP_CHAR & Chest(n).OpenTileX & SEP_CHAR & Chest(n).OpenTileY & SEP_CHAR & END_CHAR) Now add to the bottom of modHandleData in the client (Within the main sub) Code: ' ::::::::::::::::::::::::: - Gilgamesch - 04-08-2006 yay, new tuts^^ - funkynut - 05-08-2006 This tuts atleast two months old gil... Anyway, You sure you placed the code in the correct area, and as far as errors go, what errors did you get because everyone I know thats tryed this found it error free... - Coke - 20-08-2006 hmm, so this means you can have a cheast in a cave and each player can only open it once? Or can only one player open it once... If every player can open it once thats brilliant - real quests ;O - funkynut - 20-08-2006 I think the way I set it up (did this a while ago) was that each player can only open the same chest once (unless you set it so they can open it multiple times) and if you update a chest then the players are automaticly able to reopen the chest to gain the new items |