[7428] Add new .map file format use more compact data store and use

Rewrite .map extractor
 + extract more useful data
 + add "-f 0" option for disable size/accuracy optimisation
 + Compatability vs 2.4.3 client data
More fast get .map data
Implement fatigue timer
Rewrite breath timer
Allow absorb/resist for lava/slime environmental damage

Need re-extract map for work.

Signed-off-by: DiSlord <dislord@nomail.com>
This commit is contained in:
DiSlord 2009-03-09 19:37:12 +03:00
parent 95379309e5
commit 6a90d60327
22 changed files with 2280 additions and 877 deletions

View file

@ -351,8 +351,11 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
m_regenTimer = 0;
m_weaponChangeTimer = 0;
m_breathTimer = 0;
m_isunderwater = UNDERWATER_NONE;
for (int i=0; i<MAX_TIMERS; i++)
m_MirrorTimer[i] = DISABLED_MIRROR_TIMER;
m_MirrorTimerFlags = UNDERWATER_NONE;
m_MirrorTimerFlagsLast = UNDERWATER_NONE;
m_isInWater = false;
m_drunkTimer = 0;
m_drunk = 0;
@ -797,25 +800,14 @@ bool Player::StoreNewItemInBestSlots(uint32 titem_id, uint32 titem_amount)
return false;
}
void Player::StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue)
void Player::SendMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, int32 Regen)
{
uint32 BreathRegen = (uint32)-1;
WorldPacket data(SMSG_START_MIRROR_TIMER, (21));
data << (uint32)Type;
data << MaxValue;
data << MaxValue;
data << BreathRegen;
data << (uint8)0;
data << (uint32)0; // spell id
GetSession()->SendPacket(&data);
}
void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen)
{
if(Type==BREATH_TIMER)
m_breathTimer = ((MaxValue + 1*IN_MILISECONDS) - CurrentValue) / Regen;
if (MaxValue == DISABLED_MIRROR_TIMER)
{
if (CurrentValue!=DISABLED_MIRROR_TIMER)
StopMirrorTimer(Type);
return;
}
WorldPacket data(SMSG_START_MIRROR_TIMER, (21));
data << (uint32)Type;
data << CurrentValue;
@ -828,9 +820,7 @@ void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 Cur
void Player::StopMirrorTimer(MirrorTimerType Type)
{
if(Type==BREATH_TIMER)
m_breathTimer = 0;
m_MirrorTimer[Type] = DISABLED_MIRROR_TIMER;
WorldPacket data(SMSG_STOP_MIRROR_TIMER, 4);
data << (uint32)Type;
GetSession()->SendPacket( &data );
@ -841,12 +831,22 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da
if(!isAlive() || isGameMaster())
return;
// Absorb, resist some environmental damage type
uint32 absorb = 0;
uint32 resist = 0;
if (type == DAMAGE_LAVA)
CalcAbsorbResist(this, SPELL_SCHOOL_MASK_FIRE, DIRECT_DAMAGE, damage, &absorb, &resist);
else if (type == DAMAGE_SLIME)
CalcAbsorbResist(this, SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, damage, &absorb, &resist);
damage-=absorb+resist;
WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21));
data << (uint64)guid;
data << (uint8)(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL);
data << (uint32)damage;
data << (uint32)0;
data << (uint32)0;
data << (uint32)absorb; // absorb
data << (uint32)resist; // resist
SendMessageToSet(&data, true);
DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
@ -866,96 +866,153 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da
}
}
void Player::HandleDrowning()
int32 Player::getMaxTimer(MirrorTimerType timer)
{
if(!(m_isunderwater&~UNDERWATER_INLAVA))
return;
//if player is GM, have waterbreath, is dead or if breathing is disabled then return
if(isGameMaster() || !isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING))
switch (timer)
{
StopMirrorTimer(BREATH_TIMER);
// drop every flag _except_ LAVA - otherwise waterbreathing will prevent lava damage
m_isunderwater &= UNDERWATER_INLAVA;
return;
}
uint32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; // default duration
AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING);
for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i)
UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f);
if ((m_isunderwater & UNDERWATER_INWATER) && !(m_isunderwater & UNDERWATER_INLAVA) && isAlive())
{
//single trigger timer
if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER))
case FATIGUE_TIMER:
return MINUTE*IN_MILISECONDS;
case BREATH_TIMER:
{
m_isunderwater|= UNDERWATER_WATER_TRIGGER;
m_breathTimer = UnderWaterTime + 1*IN_MILISECONDS;
if (!isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING))
return DISABLED_MIRROR_TIMER;
int32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS;
AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING);
for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i)
UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f);
return UnderWaterTime;
}
//single trigger "show Breathbar"
if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB))
case FIRE_TIMER:
{
m_isunderwater|= UNDERWATER_WATER_BREATHB;
StartMirrorTimer(BREATH_TIMER, UnderWaterTime);
}
//continuous trigger drowning "Damage"
if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER))
{
//TODO: Check this formula
uint64 guid = GetGUID();
uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1);
EnvironmentalDamage(guid, DAMAGE_DROWNING,damage);
m_breathTimer = 2000;
if (!isAlive())
return DISABLED_MIRROR_TIMER;
return 1*IN_MILISECONDS;
}
default:
return 0;
}
//single trigger retract bar
else if (!(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater & UNDERWATER_WATER_TRIGGER) && (m_breathTimer > 0) && isAlive())
{
uint32 BreathRegen = 10;
// m_breathTimer will be reduced in ModifyMirrorTimer
ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen);
m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING;
}
//remove bar
else if ((m_breathTimer < 50) && !(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater == UNDERWATER_WATER_BREATHB_RETRACTING))
{
StopMirrorTimer(BREATH_TIMER);
m_isunderwater = UNDERWATER_NONE;
}
return 0;
}
void Player::HandleLava()
void Player::UpdateMirrorTimers()
{
if ((m_isunderwater & UNDERWATER_INLAVA) && isAlive())
// Desync flags for update on next HandleDrowning
if (m_MirrorTimerFlags)
m_MirrorTimerFlagsLast = ~m_MirrorTimerFlags;
}
void Player::HandleDrowning(uint32 time_diff)
{
if (!m_MirrorTimerFlags)
return;
// In water
if (m_MirrorTimerFlags & UNDERWATER_INWATER)
{
/*
* arrai: how is this supposed to work? UNDERWATER_INLAVA is always set in this scope!
// Single trigger Set BreathTimer
if (!(m_isunderwater & UNDERWATER_INLAVA))
// Breath timer not activated - activate it
if (m_MirrorTimer[BREATH_TIMER] == DISABLED_MIRROR_TIMER)
{
m_isunderwater|= UNDERWATER_WATER_BREATHB;
m_breathTimer = 1*IN_MILISECONDS;
m_MirrorTimer[BREATH_TIMER] = getMaxTimer(BREATH_TIMER);
SendMirrorTimer(BREATH_TIMER, m_MirrorTimer[BREATH_TIMER], m_MirrorTimer[BREATH_TIMER], -1);
}
*/
// Reset BreathTimer and still in the lava
if (!m_breathTimer)
else // If activated - do tick
{
uint64 guid = GetGUID();
uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage
EnvironmentalDamage(guid, DAMAGE_LAVA, damage);
m_breathTimer = 1*IN_MILISECONDS;
m_MirrorTimer[BREATH_TIMER]-=time_diff;
// Timer limit - need deal damage
if (m_MirrorTimer[BREATH_TIMER] < 0)
{
m_MirrorTimer[BREATH_TIMER]+= 1*IN_MILISECONDS;
// Calculate and deal damage
// TODO: Check this formula
uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1);
EnvironmentalDamage(GetGUID(), DAMAGE_DROWNING, damage);
}
else if (!(m_MirrorTimerFlagsLast & UNDERWATER_INWATER)) // Update time in client if need
SendMirrorTimer(BREATH_TIMER, getMaxTimer(BREATH_TIMER), m_MirrorTimer[BREATH_TIMER], -1);
}
}
else if (!isAlive()) // Disable breath timer and reset underwater flags
else if (m_MirrorTimer[BREATH_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer
{
m_breathTimer = 0;
m_isunderwater = UNDERWATER_NONE;
int32 UnderWaterTime = getMaxTimer(BREATH_TIMER);
// Need breath regen
m_MirrorTimer[BREATH_TIMER]+=10*time_diff;
if (m_MirrorTimer[BREATH_TIMER] >= UnderWaterTime || !isAlive())
StopMirrorTimer(BREATH_TIMER);
else if (m_MirrorTimerFlagsLast & UNDERWATER_INWATER)
SendMirrorTimer(BREATH_TIMER, UnderWaterTime, m_MirrorTimer[BREATH_TIMER], 10);
}
// In dark water
if (m_MirrorTimerFlags & UNDERWARER_INDARKWATER)
{
// Fatigue timer not activated - activate it
if (m_MirrorTimer[FATIGUE_TIMER] == DISABLED_MIRROR_TIMER)
{
m_MirrorTimer[FATIGUE_TIMER] = getMaxTimer(FATIGUE_TIMER);
SendMirrorTimer(FATIGUE_TIMER, m_MirrorTimer[FATIGUE_TIMER], m_MirrorTimer[FATIGUE_TIMER], -1);
}
else
{
m_MirrorTimer[FATIGUE_TIMER]-=time_diff;
// Timer limit - need deal damage or teleport ghost to graveyard
if (m_MirrorTimer[FATIGUE_TIMER] < 0)
{
m_MirrorTimer[FATIGUE_TIMER]+= 1*IN_MILISECONDS;
if (isAlive()) // Calculate and deal damage
{
uint32 damage = GetMaxHealth() / 5 + urand(0, getLevel()-1);
EnvironmentalDamage(GetGUID(), DAMAGE_EXHAUSTED, damage);
}
else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) // Teleport ghost to graveyard
RepopAtGraveyard();
}
else if (!(m_MirrorTimerFlagsLast & UNDERWARER_INDARKWATER))
SendMirrorTimer(FATIGUE_TIMER, getMaxTimer(FATIGUE_TIMER), m_MirrorTimer[FATIGUE_TIMER], -1);
}
}
else if (m_MirrorTimer[FATIGUE_TIMER] != DISABLED_MIRROR_TIMER) // Regen timer
{
int32 DarkWaterTime = getMaxTimer(FATIGUE_TIMER);
m_MirrorTimer[FATIGUE_TIMER]+=10*time_diff;
if (m_MirrorTimer[FATIGUE_TIMER] >= DarkWaterTime || !isAlive())
StopMirrorTimer(FATIGUE_TIMER);
else if (m_MirrorTimerFlagsLast & UNDERWARER_INDARKWATER)
SendMirrorTimer(FATIGUE_TIMER, DarkWaterTime, m_MirrorTimer[FATIGUE_TIMER], 10);
}
if (m_MirrorTimerFlags & (UNDERWATER_INLAVA|UNDERWATER_INSLIME))
{
// Breath timer not activated - activate it
if (m_MirrorTimer[FIRE_TIMER] == DISABLED_MIRROR_TIMER)
m_MirrorTimer[FIRE_TIMER] = getMaxTimer(FIRE_TIMER);
else
{
m_MirrorTimer[FIRE_TIMER]-=time_diff;
if (m_MirrorTimer[FIRE_TIMER] < 0)
{
m_MirrorTimer[FIRE_TIMER]+= 1*IN_MILISECONDS;
// Calculate and deal damage
// TODO: Check this formula
uint32 damage = urand(600, 700);
if (m_MirrorTimerFlags&UNDERWATER_INLAVA)
EnvironmentalDamage(GetGUID(), DAMAGE_LAVA, damage);
else
EnvironmentalDamage(GetGUID(), DAMAGE_SLIME, damage);
}
}
}
else
m_MirrorTimer[FIRE_TIMER] = DISABLED_MIRROR_TIMER;
// Recheck timers flag
m_MirrorTimerFlags&=~UNDERWATER_EXIST_TIMERS;
for (int i = 0; i< MAX_TIMERS; ++i)
if (m_MirrorTimer[i]!=DISABLED_MIRROR_TIMER)
{
m_MirrorTimerFlags|=UNDERWATER_EXIST_TIMERS;
break;
}
m_MirrorTimerFlagsLast = m_MirrorTimerFlags;
}
///The player sobers by 256 every 10 seconds
@ -1227,21 +1284,8 @@ void Player::Update( uint32 p_time )
}
}
//Breathtimer
if(m_breathTimer > 0)
{
if(p_time >= m_breathTimer)
m_breathTimer = 0;
else
m_breathTimer -= p_time;
}
//Handle Water/drowning
HandleDrowning();
//Handle lava
HandleLava();
HandleDrowning(p_time);
//Handle detect stealth players
if (m_DetectInvTimer > 0)
@ -19352,21 +19396,48 @@ PartyResult Player::CanUninviteFromGroup() const
void Player::UpdateUnderwaterState( Map* m, float x, float y, float z )
{
float water_z = m->GetWaterLevel(x,y);
float terrain_z = m->GetHeight(x,y,z, false); // use .map base surface height
uint8 flag1 = m->GetTerrainType(x,y);
LiquidData liquid_status;
ZLiquidStatus res = m->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquid_status);
if (!res)
{
m_MirrorTimerFlags &= ~(UNDERWATER_INWATER|UNDERWATER_INLAVA|UNDERWATER_INSLIME|UNDERWARER_INDARKWATER);
// Small hack for enable breath in WMO
if (IsInWater())
m_MirrorTimerFlags|=UNDERWATER_INWATER;
return;
}
//!Underwater check, not in water if underground or above water level - take UC royal quater for example
if (terrain_z <= INVALID_HEIGHT || z < (terrain_z-2) || z > (water_z - 2) )
m_isunderwater &= ~UNDERWATER_INWATER;
else if ((z < (water_z - 2)) && (flag1 & 0x01))
m_isunderwater |= UNDERWATER_INWATER;
// All liquids type - check under water position
if (liquid_status.type&(MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN|MAP_LIQUID_TYPE_MAGMA|MAP_LIQUID_TYPE_SLIME))
{
if ( res & LIQUID_MAP_UNDER_WATER)
m_MirrorTimerFlags |= UNDERWATER_INWATER;
else
m_MirrorTimerFlags &= ~UNDERWATER_INWATER;
}
//!in lava check, anywhere under lava level
if ((terrain_z <= INVALID_HEIGHT || z < (terrain_z - 0)) && (flag1 == 0x00) && IsInWater())
m_isunderwater |= UNDERWATER_INLAVA;
// Allow travel in dark water on taxi or transport
if (liquid_status.type & MAP_LIQUID_TYPE_DARK_WATER && !isInFlight() && !(GetUnitMovementFlags()&MOVEMENTFLAG_ONTRANSPORT))
m_MirrorTimerFlags |= UNDERWARER_INDARKWATER;
else
m_isunderwater &= ~UNDERWATER_INLAVA;
m_MirrorTimerFlags &= ~UNDERWARER_INDARKWATER;
// in lava check, anywhere in lava level
if (liquid_status.type&MAP_LIQUID_TYPE_MAGMA)
{
if (res & (LIQUID_MAP_UNDER_WATER|LIQUID_MAP_IN_WATER|LIQUID_MAP_WATER_WALK))
m_MirrorTimerFlags |= UNDERWATER_INLAVA;
else
m_MirrorTimerFlags &= ~UNDERWATER_INLAVA;
}
// in slime check, anywhere in slime level
if (liquid_status.type&MAP_LIQUID_TYPE_SLIME)
{
if (res & (LIQUID_MAP_UNDER_WATER|LIQUID_MAP_IN_WATER|LIQUID_MAP_WATER_WALK))
m_MirrorTimerFlags |= UNDERWATER_INSLIME;
else
m_MirrorTimerFlags &= ~UNDERWATER_INSLIME;
}
}
void Player::SetCanParry( bool value )