A possible hitch in the 'update as the user is logged in and active' is that some resources might be required even when the user is not logged in. For instance, the obvious use for gold would be to buy things, and if you're not logged in, you're not buying things, so your gold doesn't need to be updated via cron when you can just update it when the player next logs in.
But, if part of your combat system is to allow the winner of a battle to loot some of the gold of the loser, than that gold needs to be updated, even when the defending player isn't logged in.
I ran into this problem in my own game for both gold, and troops. If I set troop creation at like 15 minutes (or whatever), and the person raises up 100 troops, and then logs out before it's complete, if I don't have a script running that says 'check to see if the troops are done', and that guy gets attacked a few hours later but hasn't logged in to update his troops, those troops will not be available, even though they should have been.
So I think if the item is part of an equation that can be influenced by other players (troops, gold, etc), then your only option is to use a cron, right?
Or I suppose you could run an update query on the player being attacked to make sure those items are where they need to be, prior to running your other calculations... perhaps that's the best solution.
well, the approach has some flaws, but you may even set up an endless script.
sortha like..
start of loop
get current time (A),
query the events database and do the things needed,
get time again (B)
calculate execution time (B-A)
if execution time is less than 5 sec, then sleep(5-execution time)
end of loop
supposedly it will not allow the script to double-update.
to make sure the hdd is not whacked by the query/update things, you can simply use a database stored in RAM memory, and every 24, or 12, or 6 hours write the contents of the whole database to the disk (copy it) to make sure things don't get lost if something goes wrong. (so you can roll back..) Also, database in ram will allow swift updates, less likely the script has to run right after its finished running.
If things get ugly even whit this solution, and your processing power is limited, you can do a nice trick.
IF the execution time is longer than 5 seconds, it means the server is not fas enough to serve all needs.
You can make a variable that would add a sleep command to all players when they update the page (or click on something) they will see a server lag of a short time. this lets the server have enough time to finish the events table. Also, after the loop is complete ( everything updated so execution time is less than 5 seconds) you need to reset the variable to zero. (so no sleep, no artificial lag). This helps to handle overload on the server, and will annoy your players. Might as well LOG when something like this happens, so you will know your server has reached its limits.
this should keep everything up to date. don't forget to sort the event table by the timestamp. this will make sure things happen in order.
so in essence, you have a table that holds CURRENT STATUS
sortha like..
player X, building Y, building LVL
(building lvl 0 to whatever is the maximum, and -1 means its allready under construction/upgrade, -2 is not available yet, or whatever)
and you got an events table,
sortha like
type_of_event, variable 1 ,variable 2, variable 3,...., timestamp
where timestamp indicates when should it be done.
course, applying this is not all that easy as it looks.
when you query the database, you should only care for rows, where things are in the past compared to current timestamp. (timestamp A in my example loop)
so when querying you should select WHERE timestamp is less OR equal to timestamp A, and order the result according to timestamp.
then, you need to process every line (for eatch loop),
supposedly you can make a function that can deal with that.
for this event table might be useful to store variables that help you select what to update.
I don't know if its possible to make a mysql query update multiple value whit in 1 single query.
probably it would be more useful than doing a query for every single value that needs to be updated.
but, thats another story.
also, there are things that do not need to be so accurate.
like .. if players earn gold from a mine with a rate of X / hr, you may not want to trash the event table with that. one side is, player may need to wait for 5 valuable seconds for the gold to start building his wall, in order to finish it before the enemy arrives. other side is, gold is not used all the time, for 500 players it would be extra 500 lines to check in the event table.
so you make that "on demand" update. when the player opens up build panel, the amount of resources are calculated, and shown to the player. this reduces the load on the event table.
in order to do that, values that are updated "on demand" has to be stored with a timestamp.
sortha like:
Player X, resource Y, income rate, timestamp
when you display anything, where the resource could be spent, you take the difference of current and stored timestamp, calculate NEW resource available, update the table with new values, and then show it to the player.
and this is the point, where things get rather complicated. If player upgrades his gold mine, you have to make sure to recalculate the resources WHEN the new mine is built, whit the original income rate. Then store that, update the tables with new lvl for the gold mine, and new income rate.
may ask why..
well, if player did not visit any page that would update his resources for a long time, and his mine upgrade also took a long time, his resources would be upgraded for the WHOLE time period with the higher income rate.
it is critical to have a very clean function to handle the events table, in order to get rid of such bugs.
Its late in the night here, sorry if my post was long/disturbed. I was just thinking my input can be useful.