summaryrefslogtreecommitdiff
path: root/src/map/status.c
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2013-10-11 05:07:45 +0200
committerHaru <haru@dotalux.com>2013-10-26 12:46:46 +0200
commit44c33fda3614d588e6bf6cee1cf884e98f1531f0 (patch)
treeb617c00c97675668f3c3a8a44b4c966e39ed520c /src/map/status.c
parentd39918017d4416add066fb78ab7f23cb4436c614 (diff)
downloadhercules-44c33fda3614d588e6bf6cee1cf884e98f1531f0.tar.gz
hercules-44c33fda3614d588e6bf6cee1cf884e98f1531f0.tar.bz2
hercules-44c33fda3614d588e6bf6cee1cf884e98f1531f0.tar.xz
hercules-44c33fda3614d588e6bf6cee1cf884e98f1531f0.zip
Changed 'tick' variables to 64 bit
- This fixes an issue with timers that stop working after about 24-49 days when the tick overflows (note that this may happen much earlier than that, and at hard to predict times, on some systems) - Updated the RDTSC help message in the configure script to also warn users about issues with SpeedStep enabled systems. - On Windows, tick() still has a resolution of 10~15ms (or even as low as 100ms on some systems). A TODO comment (thanks, Ai4rei) was added for a follow-up patch, as I want this one to be as small as possible) - Note: on Windows versions earlier than 6.x (Vista, Server 2008), the tick overflow issue is NOT fixed, since they don't support the function used to retrieve a 64 bit tick. This isn't a big issue, since those platforms are already - or going soon to be - out of their extended support period, and it's already advisable to upgrade, for other reasons. If you're the unfortunate user of such a system, it is recommended that you reboot your machine at least once every 49 days for Hercules to work reliably. - Note: To clear some doubts, since I've already been asked, this has absolutely NOTHING to do with 32/64 bit CPUs or OSes. It's all about a variable's size, not the size of registers of your CPU, and your 32bit CPU will be able to handle this just fine. Signed-off-by: Haru <haru@dotalux.com>
Diffstat (limited to 'src/map/status.c')
-rw-r--r--src/map/status.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/src/map/status.c b/src/map/status.c
index 5f6444971..fc032686e 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -7806,7 +7806,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = 11-val1; //Chance to consume: 11-skill_lv%
break;
case SC_RUN:
- val4 = timer->gettick(); //Store time at which you started running.
+ {
+ //Store time at which you started running.
+ int64 currenttick = timer->gettick();
+ // Note: this int64 value is stored in two separate int32 variables (FIXME)
+ val3 = (int)(currenttick&0x00000000ffffffff);
+ val4 = (int)((currenttick&0xffffffff00000000)>>32);
+ }
tick = -1;
break;
case SC_KAAHI:
@@ -8189,7 +8195,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_WUGDASH:
- val4 = timer->gettick(); //Store time at which you started running.
+ {
+ //Store time at which you started running.
+ int64 currenttick = timer->gettick();
+ // Note: this int64 value is stored in two separate int32 variables (FIXME)
+ val3 = (int)(currenttick&0x00000000ffffffff);
+ val4 = (int)((currenttick&0xffffffff00000000)>>32);
+ }
tick = -1;
break;
case SC__SHADOWFORM: {
@@ -9315,6 +9327,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
{
struct unit_data *ud = unit->bl2ud(bl);
bool begin_spurt = true;
+ // Note: this int64 value is stored in two separate int32 variables (FIXME)
+ int64 starttick = (int64)sce->val3&0x00000000ffffffff;
+ starttick |= ((int64)sce->val4<<32)&0xffffffff00000000;
+
if (ud) {
if(!ud->state.running)
begin_spurt = false;
@@ -9323,7 +9339,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
unit->stop_walking(bl,1);
}
if (begin_spurt && sce->val1 >= 7
- && DIFF_TICK(timer->gettick(), sce->val4) <= 1000
+ && DIFF_TICK(timer->gettick(), starttick) <= 1000
&& (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0))
)
sc_start(bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1));
@@ -9932,7 +9948,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
return 1;
}
-int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) {
struct block_list *bl;
struct status_change *sc;
struct status_change_entry *sce;
@@ -9970,7 +9986,7 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) {
* For recusive status, like for each 5s we drop sp etc.
* Reseting the end timer.
*------------------------------------------*/
-int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
enum sc_type type = (sc_type)data;
struct block_list *bl;
struct map_session_data *sd;
@@ -10786,7 +10802,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) {
struct block_list* src = va_arg(ap,struct block_list*);
struct status_change_entry* sce = va_arg(ap,struct status_change_entry*);
enum sc_type type = (sc_type)va_arg(ap,int); //gcc: enum args get promoted to int
- unsigned int tick = va_arg(ap,unsigned int);
+ int64 tick = va_arg(ap, int64);
if (status->isdead(bl))
return 0;
@@ -11040,7 +11056,7 @@ int status_change_clear_buffs (struct block_list* bl, int type) {
int status_change_spread( struct block_list *src, struct block_list *bl ) {
int i, flag = 0;
struct status_change *sc = status->get_sc(src);
- unsigned int tick;
+ int64 tick;
struct status_change_data data;
if( !sc || !sc->count )
@@ -11082,7 +11098,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) {
const struct TimerData *td = timer->get(sc->data[i]->timer);
if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0)
continue;
- data.tick = DIFF_TICK(td->tick,tick);
+ data.tick = DIFF_TICK32(td->tick,tick);
} else
data.tick = INVALID_TIMER;
break;
@@ -11310,8 +11326,9 @@ int status_natural_heal(struct block_list* bl, va_list args) {
}
//Natural heal main timer.
-int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr_t data) {
- status->natural_heal_diff_tick = DIFF_TICK(tick,status->natural_heal_prev_tick);
+int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) {
+ // This difference is always positive and lower than UINT_MAX (~24 days)
+ status->natural_heal_diff_tick = (unsigned int)cap_value(DIFF_TICK(tick,status->natural_heal_prev_tick), 0, UINT_MAX);
map->foreachregen(status->natural_heal);
status->natural_heal_prev_tick = tick;
return 0;