Skip to content

Commit

Permalink
[10677] Send to creature/etc Update call real diff from last update a…
Browse files Browse the repository at this point in the history
…nd use it.

Now in case when creature/etc some tices not updates in result stay
in not active (no near players or active objects) cell some important
timers (corpse decay, summon timers, group loot expire, aura durations, etc) will
updates at real diff time from last prev. update call.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>

For some systems added exclude use real diff time because current limitations
like move generators. So its stay use last tick diff and considered freeze and
skip all time while creature in not active map part.
  • Loading branch information
cipherCOM authored and VladimirMangos committed Nov 3, 2010
1 parent 6c2611e commit 10784a8
Show file tree
Hide file tree
Showing 35 changed files with 162 additions and 149 deletions.
22 changes: 11 additions & 11 deletions src/game/Creature.cpp
Expand Up @@ -406,7 +406,7 @@ uint32 Creature::ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData *
return display_id;
}

void Creature::Update(uint32 diff)
void Creature::Update(uint32 update_diff, uint32 tick_diff)
{
if (m_needNotify)
{
Expand Down Expand Up @@ -467,7 +467,7 @@ void Creature::Update(uint32 diff)
if (m_isDeadByDefault)
break;

if (m_corpseDecayTimer <= diff)
if (m_corpseDecayTimer <= update_diff)
{
// since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless
uint16 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<Creature>(GetDBTableGUIDLow()) : 0;
Expand All @@ -482,11 +482,11 @@ void Creature::Update(uint32 diff)
}
else
{
m_corpseDecayTimer -= diff;
m_corpseDecayTimer -= update_diff;
if (m_groupLootId)
{
if(diff < m_groupLootTimer)
m_groupLootTimer -= diff;
if(update_diff < m_groupLootTimer)
m_groupLootTimer -= update_diff;
else
StopGroupLoot();
}
Expand All @@ -498,7 +498,7 @@ void Creature::Update(uint32 diff)
{
if (m_isDeadByDefault)
{
if (m_corpseDecayTimer <= diff)
if (m_corpseDecayTimer <= update_diff)
{
// since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless
uint16 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<Creature>(GetDBTableGUIDLow()) : 0;
Expand All @@ -516,11 +516,11 @@ void Creature::Update(uint32 diff)
}
else
{
m_corpseDecayTimer -= diff;
m_corpseDecayTimer -= update_diff;
}
}

Unit::Update( diff );
Unit::Update(update_diff, tick_diff);

// creature can be dead after Unit::Update call
// CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
Expand All @@ -531,7 +531,7 @@ void Creature::Update(uint32 diff)
{
// do not allow the AI to be changed during update
m_AI_locked = true;
i_AI->UpdateAI(diff);
i_AI->UpdateAI(tick_diff); // AI not react good at real update delays (while freeze in non-active part of map)
m_AI_locked = false;
}

Expand All @@ -541,10 +541,10 @@ void Creature::Update(uint32 diff)
break;
if(m_regenTimer > 0)
{
if(diff >= m_regenTimer)
if(update_diff >= m_regenTimer)
m_regenTimer = 0;
else
m_regenTimer -= diff;
m_regenTimer -= update_diff;
}
if (m_regenTimer != 0)
break;
Expand Down
2 changes: 1 addition & 1 deletion src/game/Creature.h
Expand Up @@ -401,7 +401,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; }
char const* GetSubName() const { return GetCreatureInfo()->SubName; }

void Update(uint32 time); // overwrite Unit::Update
void GetRespawnCoord(float &x, float &y, float &z, float* ori = NULL, float* dist =NULL) const;
uint32 GetEquipmentId() const { return m_equipmentId; }

Expand Down Expand Up @@ -637,6 +636,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
void SendAreaSpiritHealerQueryOpcode(Player *pl);

protected:
void Update(uint32 update_diff, uint32 tick_diff); // overwrite Unit::Update
bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
void RelocationNotify();
Expand Down
6 changes: 3 additions & 3 deletions src/game/DynamicObject.cpp
Expand Up @@ -106,7 +106,7 @@ Unit* DynamicObject::GetCaster() const
return ObjectAccessor::GetUnit(*this, GetCasterGUID());
}

void DynamicObject::Update(uint32 p_time)
void DynamicObject::Update(uint32 update_diff, uint32 /*tick_diff*/)
{
// caster can be not in world at time dynamic object update, but dynamic object not yet deleted in Unit destructor
Unit* caster = GetCaster();
Expand All @@ -118,8 +118,8 @@ void DynamicObject::Update(uint32 p_time)

bool deleteThis = false;

if(m_aliveDuration > int32(p_time))
m_aliveDuration -= p_time;
if(m_aliveDuration > int32(update_diff))
m_aliveDuration -= update_diff;
else
deleteThis = true;

Expand Down
3 changes: 2 additions & 1 deletion src/game/DynamicObject.h
Expand Up @@ -35,7 +35,6 @@ class DynamicObject : public WorldObject
void RemoveFromWorld();

bool Create(uint32 guidlow, Unit *caster, uint32 spellId, SpellEffectIndex effIndex, float x, float y, float z, int32 duration, float radius);
void Update(uint32 p_time);
void Delete();
uint32 GetSpellId() const { return m_spellId; }
SpellEffectIndex GetEffIndex() const { return m_effIndex; }
Expand Down Expand Up @@ -67,6 +66,8 @@ class DynamicObject : public WorldObject
GridReference<DynamicObject> &GetGridRef() { return m_gridRef; }

protected:
void Update(uint32 update_diff, uint32 tick_diff); // overwrite WorldObject::Update

uint32 m_spellId;
SpellEffectIndex m_effIndex;
int32 m_aliveDuration;
Expand Down
2 changes: 1 addition & 1 deletion src/game/GameObject.cpp
Expand Up @@ -159,7 +159,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
return true;
}

void GameObject::Update(uint32 /*p_time*/)
void GameObject::Update(uint32 /*update_diff*/, uint32 /*tick_diff*/)
{
if (GetObjectGuid().IsMOTransport())
{
Expand Down
3 changes: 2 additions & 1 deletion src/game/GameObject.h
Expand Up @@ -588,7 +588,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
void RemoveFromWorld();

bool Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint8 animprogress, GOState go_state);
void Update(uint32 p_time);
GameObjectInfo const* GetGOInfo() const;

bool IsTransport() const;
Expand Down Expand Up @@ -711,6 +710,8 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject

uint64 GetRotation() const { return m_rotation; }
protected:
void Update(uint32 update_diff, uint32 tick_diff); // overwrite WorldObject::Update

uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
Expand Down
4 changes: 1 addition & 3 deletions src/game/GridNotifiers.cpp
Expand Up @@ -187,9 +187,7 @@ template<class T> void
ObjectUpdater::Visit(GridRefManager<T> &m)
{
for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{
iter->getSource()->Update(i_timeDiff);
}
iter->getSource()->UpdateCall(i_time, i_diff);
}

bool CannibalizeObjectCheck::operator()(Corpse* u)
Expand Down
10 changes: 6 additions & 4 deletions src/game/GridNotifiers.h
Expand Up @@ -61,13 +61,14 @@ namespace MaNGOS
struct MANGOS_DLL_DECL GridUpdater
{
GridType &i_grid;
uint32 i_time;
uint32 i_timeDiff;
GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {}
GridUpdater(GridType &grid, uint32 time_, uint32 diff) : i_grid(grid), i_time(time_), i_timeDiff(diff) {}

template<class T> void updateObjects(GridRefManager<T> &m)
{
for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
iter->getSource()->Update(i_timeDiff);
iter->getSource()->UpdateCall(i_time, i_timeDiff);
}

void Visit(PlayerMapType &m) { updateObjects<Player>(m); }
Expand Down Expand Up @@ -136,8 +137,9 @@ namespace MaNGOS

struct MANGOS_DLL_DECL ObjectUpdater
{
uint32 i_timeDiff;
explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {}
uint32 i_time; // current tick time in msecs
uint32 i_diff; // current tick time diff in msecs
explicit ObjectUpdater(uint32 time_, uint32 diff) : i_time(time_), i_diff(diff) {}
template<class T> void Visit(GridRefManager<T> &m);
void Visit(PlayerMapType &) {}
void Visit(CorpseMapType &) {}
Expand Down
2 changes: 1 addition & 1 deletion src/game/GridNotifiersImpl.h
Expand Up @@ -41,7 +41,7 @@ inline void MaNGOS::VisibleNotifier::Visit(GridRefManager<T> &m)
inline void MaNGOS::ObjectUpdater::Visit(CreatureMapType &m)
{
for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
iter->getSource()->Update(i_timeDiff);
iter->getSource()->UpdateCall(i_time, i_diff);
}

inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPoint, Creature* c)
Expand Down
24 changes: 11 additions & 13 deletions src/game/Map.cpp
Expand Up @@ -514,20 +514,18 @@ bool Map::loaded(const GridPair &p) const
return ( getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord) );
}

void Map::Update(const uint32 &t_diff)
void Map::Update(uint32 time_, uint32 diff)
{
/// update players at tick
for(m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter)
{
Player* plr = m_mapRefIter->getSource();
if(plr && plr->IsInWorld())
plr->Update(t_diff);
}
if (Player* plr = m_mapRefIter->getSource())
if (plr->IsInWorld())
plr->UpdateCall(time_, diff);

/// update active cells around players and active objects
resetMarkedCells();

MaNGOS::ObjectUpdater updater(t_diff);
MaNGOS::ObjectUpdater updater(time_, diff);
// for creature
TypeContainerVisitor<MaNGOS::ObjectUpdater, GridTypeMapContainer > grid_object_update(updater);
// for pets
Expand Down Expand Up @@ -638,7 +636,7 @@ void Map::Update(const uint32 &t_diff)
GridInfo *info = i->getSource()->getGridInfoRef();
++i; // The update might delete the map and we need the next map before the iterator gets invalid
MANGOS_ASSERT(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
sMapMgr.UpdateGridState(grid->GetGridState(), *this, *grid, *info, grid->getX(), grid->getY(), t_diff);
sMapMgr.UpdateGridState(grid->GetGridState(), *this, *grid, *info, grid->getX(), grid->getY(), diff);
}
}

Expand Down Expand Up @@ -1849,17 +1847,17 @@ bool InstanceMap::Add(Player *player)
return true;
}

void InstanceMap::Update(const uint32& t_diff)
void InstanceMap::Update(uint32 time_, uint32 diff)
{
Map::Update(t_diff);
Map::Update(time_, diff);

if(i_data)
i_data->Update(t_diff);
i_data->Update(diff);
}

void BattleGroundMap::Update(const uint32& diff)
void BattleGroundMap::Update(uint32 time_, uint32 diff)
{
Map::Update(diff);
Map::Update(time_, diff);

GetBG()->Update(diff);
}
Expand Down
6 changes: 3 additions & 3 deletions src/game/Map.h
Expand Up @@ -108,7 +108,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
template<class T> void Add(T *);
template<class T> void Remove(T *, bool);

virtual void Update(const uint32&);
virtual void Update(uint32 time_, uint32 diff);

void MessageBroadcast(Player *, WorldPacket *, bool to_self);
void MessageBroadcast(WorldObject *, WorldPacket *);
Expand Down Expand Up @@ -382,7 +382,7 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
~InstanceMap();
bool Add(Player *);
void Remove(Player *, bool);
void Update(const uint32&);
void Update(uint32 time_, uint32 diff);
void CreateInstanceData(bool load);
bool Reset(uint8 method);
uint32 GetScriptId() { return i_script_id; }
Expand All @@ -407,7 +407,7 @@ class MANGOS_DLL_SPEC BattleGroundMap : public Map
BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode);
~BattleGroundMap();

void Update(const uint32&);
void Update(uint32 time_, uint32 diff);
bool Add(Player *);
void Remove(Player *, bool);
bool CanEnter(Player* player);
Expand Down
8 changes: 4 additions & 4 deletions src/game/MapInstanced.cpp
Expand Up @@ -43,24 +43,24 @@ void MapInstanced::InitVisibilityDistance()
}
}

void MapInstanced::Update(const uint32& t)
void MapInstanced::Update(uint32 time_, uint32 diff)
{
// take care of loaded GridMaps (when unused, unload it!)
Map::Update(t);
Map::Update(time_, diff);

// update the instanced maps
InstancedMaps::iterator i = m_InstancedMaps.begin();

while (i != m_InstancedMaps.end())
{
if(i->second->CanUnload(t))
if(i->second->CanUnload(diff))
{
DestroyInstance(i); // iterator incremented
}
else
{
// update only here, because it may schedule some bad things before delete
i->second->Update(t);
i->second->Update(time_, diff);
++i;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/game/MapInstanced.h
Expand Up @@ -34,7 +34,7 @@ class MANGOS_DLL_DECL MapInstanced : public Map
~MapInstanced() {}

// functions overwrite Map versions
void Update(const uint32&);
void Update(uint32 time_, uint32 diff);
void RemoveAllObjectsInRemoveList();
void UnloadAll(bool pForce);

Expand Down
6 changes: 3 additions & 3 deletions src/game/MapManager.cpp
Expand Up @@ -239,17 +239,17 @@ void MapManager::DeleteInstance(uint32 mapid, uint32 instanceId)
}

void
MapManager::Update(uint32 diff)
MapManager::Update(const uint32 time_, const uint32 diff)
{
i_timer.Update(diff);
if( !i_timer.Passed() )
return;

for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter)
iter->second->Update((uint32)i_timer.GetCurrent());
iter->second->Update(time_, (uint32)i_timer.GetCurrent());

for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter)
(*iter)->Update((uint32)i_timer.GetCurrent());
(*iter)->UpdateCall(time_, (uint32)i_timer.GetCurrent());

i_timer.SetCurrent(0);
}
Expand Down
2 changes: 1 addition & 1 deletion src/game/MapManager.h
Expand Up @@ -67,7 +67,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
}

void Initialize(void);
void Update(uint32);
void Update(const uint32 time, const uint32 diff);

void SetGridCleanUpDelay(uint32 t)
{
Expand Down
14 changes: 12 additions & 2 deletions src/game/Object.cpp
Expand Up @@ -103,6 +103,16 @@ void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
m_PackGUID.Set(guid);
}

void WorldObject::UpdateCall(uint32 newtime, uint32 diff)
{
// use real time diff from last object update call
// this can have big diff from tick diff time for object returning to active zone)
uint32 realDiff = getMSTimeDiff(m_lastUpdateTime, newtime);
m_lastUpdateTime = newtime;

Update(realDiff, diff);
}

void Object::SetObjectScale(float newScale)
{
SetFloatValue(OBJECT_FIELD_SCALE_X, newScale);
Expand Down Expand Up @@ -1121,7 +1131,7 @@ void Object::BuildUpdateData( UpdateDataMapType& /*update_players */)

WorldObject::WorldObject()
: m_isActiveObject(false), m_currMap(NULL), m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f)
m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_lastUpdateTime(getMSTime())
{
}

Expand Down Expand Up @@ -2084,4 +2094,4 @@ bool WorldObject::IsControlledByPlayer() const
default:
return false;
}
}
}

5 comments on commit 10784a8

@rsa
Copy link
Contributor

@rsa rsa commented on 10784a8 Nov 4, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in instances/BG first tick value sended to creature in Update() may be very high (converted negative?). example - shaman totems.

@Marik23
Copy link
Contributor

@Marik23 Marik23 commented on 10784a8 Nov 4, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's interesting, that you mention it RSA.

On my debian dedicated server, I cannot summon totems anymore.
On Windows everything is alright.

@SeTM
Copy link

@SeTM SeTM commented on 10784a8 Nov 5, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, in instances and bg totems not work

@rsa
Copy link
Contributor

@rsa rsa commented on 10784a8 Nov 5, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

problem in real multithreading (not available in Wintendo)
solve -
https://github.com/rsa/mangos/commit/e8b1a653d07801fdfea81de2e0352594fefea5fd

@Marik23
Copy link
Contributor

@Marik23 Marik23 commented on 10784a8 Nov 5, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seams to work at the first sight.
I will do further tests, but it is an improvement of this patch.
All non-Win'er will thank you ;)

Please sign in to comment.