zelig Posted April 17, 2012 Share Posted April 17, 2012 Okay, I'm not quite sure how to state this, so I'll try my best. Is it possible to setup some kind of "after so long, it changes the state of something from 'fighting' to 'active'" query or function? What is happening is that people are fighting in my game, then choosing to just close their browser rather than quit the fight, to change the monster's state back to 'active', so other people can fight it. Does that make sense? Any thoughts or could someone point me in the right direction? Thanks!! Quote Link to comment Share on other sites More sharing options...
Psycho Posted April 17, 2012 Share Posted April 17, 2012 How are you determining the status now? I assume you have a database, so perhaps you have a column for status. I really can't give you a good solution based upon what you have provided. But, I will provide a possible solution with one potential scenario. You can then modify that as you need it. Ok, so I will assume you have a field in the "monsters" table to indicate the status. For simplicity's sake I will call this field "fighting" and a 1 (true) value indicates that the monster is fighting and a 0 (false) indicates the monster is active. The problem, is that you cannot force users to release a monster to go from fighting back to active. The solution is to assume after x amount of inactivity that the monster is active even if the status is 1. With the potential scenario above you could have a query to get a list of all active monsters such as this: SELECT * FROM monsters WHERE fighting = 0 I would fix this problem by first creating a "last_updated" timestamp field in the table. And set the parameters so that value is automatically updated to the current timestamp whenever the record is changed (i.e. you would not have to set the value manually when creating or editing the records). Now, to get all the records that are set as active AND to get the records that are set as fighting but have been inactive for, say, 20 minutes you simply need to change the query SELECT * FROM monsters WHERE fighting = 0 OR last_updated < DATE_SUB(NOW(), INTERVAL 20 MINUTE) Of course you would need to add some functionality for a user that did not close their page but did leave the window inactive. Instead of assuming they can still fight with that monster it would need to see if that user still had control. If not, you can display a message to the user that they lost control due to inactivity. Quote Link to comment Share on other sites More sharing options...
zelig Posted April 18, 2012 Author Share Posted April 18, 2012 Ah, I get it. Okay, so I have a separate table called "battles" that has a "battle_time" field. I will have that update every action. So, if I add in the 20 minute timeout to it, how would that look? It would delete that battle from the `battles` table... DELETE * FROM `battles` WHERE `mid`= (Monster ID -> unique for every single monster) AND `battle_time` = <Whatever the 20 minute thing is> Quote Link to comment Share on other sites More sharing options...
Psycho Posted April 18, 2012 Share Posted April 18, 2012 You don't need to delete anything. There is no timeout event to know when a user has not performed any action. You would have to create a cron job to run every so often to check for inactive records and delete them. That's not efficient. Instead you would change the logic for determining what records are active. Instead of just looking for the status of active you would use TWO criteria to determine if a record is active or not: 1. If the status value is explicitly set as active 2. Or, the last activity value of the record is > 20 minutes Quote Link to comment Share on other sites More sharing options...
zelig Posted April 18, 2012 Author Share Posted April 18, 2012 I don't have a column for status, that's the issue. Here's how the system works currently: When someone fights a monster, that monster's id, hp and no_exp (it won't let you fight monsters you are too strong for) and the player's id is added to the `battles` table in addition to time(). This makes it so that no other person can fight that monster because it also changes the info in the `monsters` table for that monster to state='fighting'. When either the player or monster wins, the battle is deleted from `battles` and the state goes back to 'active' or 'killed', whichever is appropriate. The issue I am having, however, is if a player "times out" or "leaves" without exiting the battle, thus leaving the monster in the 'fighting' state, nullifying anyone else able to battle it now. It also leaves that info in the `battles` table, and that's why I need it to be deleted out. Another quick question (which I may have to add to a different topic): Is there some way I can change that state to 'active' (if it was the monster that was killed) if that time() >= to what I have is the respawn rate, which is defined for each creature based upon what level it is. I believe a cron would work for this one... Quote Link to comment Share on other sites More sharing options...
Psycho Posted April 18, 2012 Share Posted April 18, 2012 When someone fights a monster, that monster's id, hp and no_exp (it won't let you fight monsters you are too strong for) and the player's id is added to the `battles` table in addition to time(). This makes it so that no other person can fight that monster because it also changes the info in the `monsters` table for that monster to state='fighting'. When either the player or monster wins, the battle is deleted from `battles` and the state goes back to 'active' or 'killed', whichever is appropriate. You state "I don't have a column for status, that's the issue.", but that's not true. You just stated that you have a field called "state" which is basically the status. But, with the additional information you've provided you don't even need that field. You can use the associated records in the battles table to derive the information you need. Here is a general idea of what I would do. When a user starts a battle you would add the associated record to the battles table with a foreign key reference back to the monster. However, I wouldn't copy the hp and no_exp to the battles record - again you can derive that from the monsters table. As actions take place with the battle you would update the battles record with the appropriate data. At a minimum I would expect that you would need to store the damage inflicted and of course there should be a automatically updated timestamp. The table would also need a field to indicate if the battle is complete/exited which you would update if the user explicitly leaves the battle or if the monster was killed. So, you could then get a list of any available monsters by JOINing the two tables and using the right criteria. Example SELECT * FROM monsters LEFT JOIN battles ON monsters.id = battles.monster_id AND battles.complete = 0 WHERE battles.last_updated > DATE_SUB(NOW(), INTERVAL 20 MINUTE) This is just a general approach. I can't really provide all the code and queries needed. Quote Link to comment Share on other sites More sharing options...
zelig Posted April 18, 2012 Author Share Posted April 18, 2012 Okay. I could potentially add this to a cron job I already have running every minute that updates dead monsters and turns them back to active once the time > respawn. What would be the type of query I would use? I think I get the JOIN bit, but the INTERVAL part doesn't seem to make sense to me, and doesn't appear to be PHP markup. Quote Link to comment Share on other sites More sharing options...
Psycho Posted April 18, 2012 Share Posted April 18, 2012 Okay. I could potentially add this to a cron job I already have running every minute that updates dead monsters and turns them back to active once the time > respawn. You aren't understanding what I am saying. You don't need a cron job. You don't need to update the records to explicitly set them as active. IF the battle is exited properly then you would explicitly update them to active. But, for the battles that are not exited properly you can determine that they are active if they have not been updated in 20 minutes (or whatever period you want). That is what the example query I provided would do. Let me explain it in plain English. If you wanted a list of all available monsters you would query for all records where 1) there is no active battle record for the monster (i.e. they were exited properly) OR 2) the last activity value is > 20 minutes (i.e. the battle was not exited properly). What would be the type of query I would use? I think I get the JOIN bit, but the INTERVAL part doesn't seem to make sense to me, and doesn't appear to be PHP markup. I gave you an example query. This isn't my project so I'm not going to invest a lot of time to get your DB structure and build and test the optimal query for you. As for the INTERVAL statement, of course it isn't PHP markup. That is a query which would contain MySQL code. The date_sub() function takes a datetime value and subtracts some amount from it. In the example I provided, it is taking the current timestamp [i.e. now()] and subtracting the interval of 20 minutes from it. So in the query OR last_updated < DATE_SUB(NOW(), INTERVAL 20 MINUTE) I was including records who's last_updated value is less than 20 minutes ago. In other words, records which have been inactive for more than 20 minutes Quote Link to comment Share on other sites More sharing options...
zelig Posted April 18, 2012 Author Share Posted April 18, 2012 Okay. *thickhead* (Nevermind... I have a `state` column that I can use for the 'fighting', 'active', or 'dead' bit) I need to add a new column (battle) to the monsters table, make it be a 0 or 1, and then a column for last_update (which will have time). I have reread all of this and I think I get it now. Thanks! Quote Link to comment Share on other sites More sharing options...
zelig Posted April 18, 2012 Author Share Posted April 18, 2012 Okay, this is what I have now, but it doesn't like the INTERVAL 20 MINUTE bit... Parse error: syntax error, unexpected T_LNUMBER $query = mysql_select("SELECT * FROM `monsters` WHERE `state`='fighting'"); $result = mysql_fetch_array("$query"); if ($single_mob['battle_time'] > DATE_SUB(NOW(), INTERVAL 20 MINUTE)) { $query = mysql_select("UPDATE `monsters` SET`battle_time`=0, `state`='active'"); exit; } Quote Link to comment Share on other sites More sharing options...
Psycho Posted April 18, 2012 Share Posted April 18, 2012 Okay, this is what I have now, but it doesn't like the INTERVAL 20 MINUTE bit... Parse error: syntax error, unexpected T_LNUMBER $query = mysql_select("SELECT * FROM `monsters` WHERE `state`='fighting'"); $result = mysql_fetch_array("$query"); if ($single_mob['battle_time'] > DATE_SUB(NOW(), INTERVAL 20 MINUTE)) { $query = mysql_select("UPDATE `monsters` SET`battle_time`=0, `state`='active'"); exit; } I already told you that date_sub() and the content within it (i.e. the INTERVAL part) was not PHP code. It is a MySQL function. Why would you then take that out of the query and try to use it as PHP code? As for the INTERVAL statement, of course it isn't PHP markup. That is a query which would contain MySQL code. The date_sub() function takes a datetime value and subtracts some amount from it. In the example I provided, it is taking the current timestamp [i.e. now()] and subtracting the interval of 20 minutes from it. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.