Merge commit 'origin/master' into 320

Conflicts:
	src/game/MovementHandler.cpp
This commit is contained in:
tomrus88 2009-08-20 16:24:37 +04:00
commit fec1a1954c
27 changed files with 439 additions and 253 deletions

View file

@ -576,6 +576,8 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory;
recv_data >> quality >> usable;
recv_data.read_skip(16); // unknown 16 bytes: 00 07 01 00 00 01 05 00 06 00 09 01 08 00 03 00
Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER);
if (!pCreature)
{
@ -618,7 +620,8 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data )
{
sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES");
recv_data.hexlike();
recv_data.read_skip<uint64>(); // auctioner guid
uint32 count = 0;

View file

@ -96,6 +96,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//std::string unk1, unk2;
//recv_data >> (std::string)unk1;
@ -131,6 +132,7 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data >> uint64
//recv_data >> uint64
@ -149,6 +151,7 @@ void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data >> uint64
//recv_data >> uint64
@ -160,6 +163,7 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data >> uint64
//recv_data >> uint64
@ -171,6 +175,7 @@ void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data >> uint64
//recv_data >> uint64
@ -184,6 +189,7 @@ void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data >> uint64
//recv_data >> uint64
@ -195,6 +201,7 @@ void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data.readPackGUID(guid)
//recv_data >> uint64
@ -206,6 +213,7 @@ void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data.readPackGUID(guid)
//recv_data >> uint64
@ -218,6 +226,7 @@ void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data.readPackGUID(guid)
//recv_data >> uint64
@ -230,6 +239,7 @@ void WorldSession::HandleCalendarComplain(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN");
recv_data.hexlike();
recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam
//recv_data >> uint64
//recv_data >> uint64

View file

@ -84,15 +84,15 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data )
uint32 map;
float x, y, z;
std::string ticketText = "";
uint32 unk1, unk2;
recv_data >> map >> x >> y >> z; // last check 2.4.3
recv_data >> ticketText;
recv_data >> unk1 >> unk2;
// note: the packet might contain more data, but the exact structure of that is unknown
recv_data.read_skip<uint32>(); // unk1, 0
recv_data.read_skip<uint32>(); // unk2, 1
recv_data.read_skip<uint32>(); // unk3, 0
sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s, unk1 %u, unk2 %u", map, x, y, z, ticketText.c_str(), unk1, unk2);
sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s", map, x, y, z, ticketText.c_str());
if(ticketmgr.GetGMTicket(GetPlayer()->GetGUIDLow()))
{

View file

@ -614,12 +614,14 @@ void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket)
guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
if(!guild)
{
recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD);
return;
}
else if(GetPlayer()->GetGUID() != guild->GetLeader())
{
recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam
SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS);
return;
}
@ -1026,9 +1028,14 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
uint64 GoGuid;
uint8 BankToBank;
uint8 BankTab, BankTabSlot, AutoStore, AutoStoreCount, PlayerSlot, PlayerBag, SplitedAmount = 0;
uint8 BankTabDst, BankTabSlotDst, unk2, ToChar = 1;
uint8 BankTab, BankTabSlot, AutoStore;
uint8 PlayerSlot = NULL_SLOT;
uint8 PlayerBag = NULL_BAG;
uint8 BankTabDst, BankTabSlotDst, unk2;
uint8 ToChar = 1;
uint32 ItemEntry, unk1;
uint32 AutoStoreCount = 0;
uint32 SplitedAmount = 0;
recv_data >> GoGuid >> BankToBank;
if (BankToBank)
@ -1042,10 +1049,11 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
recv_data >> unk2; // always 0
recv_data >> SplitedAmount;
if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS)
return;
if (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot)
if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS || BankTabDst == BankTab && BankTabSlotDst == BankTabSlot)
{
recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
return;
}
}
else
{
@ -1056,17 +1064,22 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
if (AutoStore)
{
recv_data >> AutoStoreCount;
recv_data.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in guild->ToChar)
recv_data.read_skip<uint32>(); // unknown, always 0
}
recv_data >> PlayerBag;
recv_data >> PlayerSlot;
if (!AutoStore)
else
{
recv_data >> PlayerBag;
recv_data >> PlayerSlot;
recv_data >> ToChar;
recv_data >> SplitedAmount;
}
if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF)
{
recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
return;
}
}
if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
@ -1201,14 +1214,6 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data )
// Player <-> Bank
// char->bank autostore click return BankTabSlot = 255 = NULL_SLOT
// do similar for bank->char
if(AutoStore && ToChar)
{
PlayerBag = NULL_BAG;
PlayerSlot = NULL_SLOT;
}
// allow work with inventory only
if(!Player::IsInventoryPos(PlayerBag,PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT) )
{

View file

@ -30,7 +30,8 @@
void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data )
{
//sLog.outDebug("WORLD: CMSG_SPLIT_ITEM");
uint8 srcbag, srcslot, dstbag, dstslot, count;
uint8 srcbag, srcslot, dstbag, dstslot;
uint32 count;
recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count;
//sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count);
@ -489,12 +490,9 @@ void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data )
{
sLog.outDebug( "WORLD: Received CMSG_SELL_ITEM" );
uint64 vendorguid, itemguid;
uint8 _count;
uint32 count;
recv_data >> vendorguid >> itemguid >> _count;
// prevent possible overflow, as mangos uses uint32 for item count
uint32 count = _count;
recv_data >> vendorguid >> itemguid >> count;
if(!itemguid)
return;
@ -970,6 +968,8 @@ void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data)
{
uint32 itemid;
recv_data >> itemid;
recv_data.read_skip<uint64>(); // guid
sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid);
ItemPrototype const *pProto = objmgr.GetItemPrototype( itemid );
if( pProto )

View file

@ -634,7 +634,7 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data)
if(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP) > time(NULL))
return;
if (!corpse->IsWithinDist(GetPlayer(),CORPSE_RECLAIM_RADIUS,false))
if (!corpse->IsWithinDist(GetPlayer(), CORPSE_RECLAIM_RADIUS, true))
return;
uint64 guid;
@ -721,21 +721,31 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
else
{
// we have only extent
float dx = pl->GetPositionX() - atEntry->x;
float dy = pl->GetPositionY() - atEntry->y;
float dz = pl->GetPositionZ() - atEntry->z;
double es = sin(atEntry->box_orientation);
double ec = cos(atEntry->box_orientation);
// calc rotated vector based on extent axis
double rotateDx = dx*ec - dy*es;
double rotateDy = dx*es + dy*ec;
if( (fabs(rotateDx) > atEntry->box_x/2 + delta) ||
(fabs(rotateDy) > atEntry->box_y/2 + delta) ||
// rotate the players position instead of rotating the whole cube, that way we can make a simplified
// is-in-cube check and we have to calculate only one point instead of 4
// 2PI = 360°, keep in mind that ingame orientation is counter-clockwise
double rotation = 2*M_PI-atEntry->box_orientation;
double sinVal = sin(rotation);
double cosVal = cos(rotation);
float playerBoxDistX = pl->GetPositionX() - atEntry->x;
float playerBoxDistY = pl->GetPositionY() - atEntry->y;
float rotPlayerX = atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal;
float rotPlayerY = atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal;
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
float dz = pl->GetPositionZ() - atEntry->z;
float dx = rotPlayerX - atEntry->x;
float dy = rotPlayerY - atEntry->y;
if( (fabs(dx) > atEntry->box_x/2 + delta) ||
(fabs(dy) > atEntry->box_y/2 + delta) ||
(fabs(dz) > atEntry->box_z/2 + delta) )
{
sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotate dX: %f rotate dY: %f dZ:%f), ignore Area Trigger ID: %u",
pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotateDx, rotateDy, dz, Trigger_ID);
sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u",
pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotPlayerX, rotPlayerY, dz, Trigger_ID);
return;
}
}
@ -868,6 +878,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data)
if(decompressedSize > 0xFFFF)
{
recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case
sLog.outError("UAD: Account data packet too big, size %u", decompressedSize);
return;
}
@ -878,10 +889,13 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data)
uLongf realSize = decompressedSize;
if(uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK)
{
recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case
sLog.outError("UAD: Failed to decompress account data");
return;
}
recv_data.rpos(recv_data.wpos()); // uncompress read (recv_data.size() - recv_data.rpos())
std::string adata;
dest >> adata;
@ -987,7 +1001,8 @@ void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket & recv_data )
/* WorldSession::Update( getMSTime() );*/
DEBUG_LOG( "WORLD: Time Lag/Synchronization Resent/Update" );
recv_data.read_skip2<uint64,uint32>();
recv_data.read_skip<uint64>();
recv_data.read_skip<uint32>();
/*
uint64 guid;
uint32 time_skipped;
@ -1010,76 +1025,50 @@ void WorldSession::HandleFeatherFallAck(WorldPacket &/*recv_data*/)
void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data)
{
// no used
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
/*
uint64 guid;
recv_data >> guid;
// now can skip not our packet
if(_player->GetGUID() != guid)
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK" );
recv_data.read_skip<uint64>(); // guid
recv_data.read_skip<uint64>(); // unknown1
recv_data.read_skip<uint32>(); // unknown2
recv_data.read_skip<float>(); // PositionX
recv_data.read_skip<float>(); // PositionY
recv_data.read_skip<float>(); // PositionZ
recv_data.read_skip<float>(); // Orientation
/*
recv_data.hexlike();
recv_data.read_skip<uint32>(); // unk
recv_data >> guid;
recv_data >> unknown1;
recv_data >> unknown2;
recv_data >> PositionX;
recv_data >> PositionY;
recv_data >> PositionZ;
recv_data >> Orientation;
// TODO for later may be we can use for anticheat
DEBUG_LOG("Guid " UI64FMTD,guid);
DEBUG_LOG("unknown1 " UI64FMTD,unknown1);
DEBUG_LOG("unknown2 %u",unknown2);
DEBUG_LOG("X %f",PositionX);
DEBUG_LOG("Y %f",PositionY);
DEBUG_LOG("Z %f",PositionZ);
DEBUG_LOG("O %f",Orientation);
*/
MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
*/
}
void WorldSession::HandleMoveRootAck(WorldPacket& recv_data)
{
recv_data.read_skip<uint64>(); // guid
recv_data.read_skip<uint64>(); // unknown1
recv_data.read_skip<uint32>(); // unknown2
recv_data.read_skip<float>(); // PositionX
recv_data.read_skip<float>(); // PositionY
recv_data.read_skip<float>(); // PositionZ
recv_data.read_skip<float>(); // Orientation
// no used
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
/*
uint64 guid;
recv_data >> guid;
/*
sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_ROOT_ACK" );
recv_data.hexlike();
uint64 guid;
uint64 unknown1;
uint32 unknown2;
float PositionX;
float PositionY;
float PositionZ;
float Orientation;
// now can skip not our packet
if(_player->GetGUID() != guid)
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
recv_data >> guid;
recv_data >> unknown1;
recv_data >> unknown2;
recv_data >> PositionX;
recv_data >> PositionY;
recv_data >> PositionZ;
recv_data >> Orientation;
sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_ROOT_ACK" );
// for later may be we can use for anticheat
DEBUG_LOG("Guid " UI64FMTD,guid);
DEBUG_LOG("unknown1 " UI64FMTD,unknown1);
DEBUG_LOG("unknown1 %u",unknown2);
DEBUG_LOG("X %f",PositionX);
DEBUG_LOG("Y %f",PositionY);
DEBUG_LOG("Z %f",PositionZ);
DEBUG_LOG("O %f",Orientation);
*/
recv_data.read_skip<uint32>(); // unk
MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
*/
}
void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data)

View file

@ -218,7 +218,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if(plMover && plMover->IsBeingTeleported())
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
/* extract packet */
uint64 guid;
@ -231,6 +234,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
ReadMovementInfo(recv_data, &movementInfo);
/*----------------*/
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
return;
@ -353,7 +357,10 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
// now can skip not our packet
if(_player->GetGUID() != guid)
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
// continue parse packet
recv_data >> unk1; // counter or moveEvent
@ -442,6 +449,7 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
if(_player->m_mover->GetGUID() == old_mover_guid)
{
sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid);
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
@ -460,7 +468,10 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
uint64 vehicleGUID = _player->GetCharmGUID();
if(!vehicleGUID) // something wrong here...
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}
uint64 guid;

View file

@ -491,7 +491,7 @@ void ObjectMgr::LoadCreatureTemplates()
CreatureInfo const* heroicInfo = GetCreatureTemplate(cInfo->HeroicEntry);
if (!heroicInfo)
{
sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u not exist.",cInfo->HeroicEntry,cInfo->HeroicEntry);
sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u not exist.", i, cInfo->HeroicEntry, cInfo->HeroicEntry);
continue;
}

View file

@ -3859,19 +3859,34 @@ SpellCastResult Spell::CheckCast(bool strict)
}
}
}
else if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster
else if (m_caster == target)
{
// Additional check for some spells
// If 0 spell effect empty - client not send target data (need use selection)
// TODO: check it on next client version
if (m_targets.m_targetMask == TARGET_FLAG_SELF &&
m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE)
if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster
{
if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection()))
m_targets.setUnitTarget(target);
else
return SPELL_FAILED_BAD_TARGETS;
// Additional check for some spells
// If 0 spell effect empty - client not send target data (need use selection)
// TODO: check it on next client version
if (m_targets.m_targetMask == TARGET_FLAG_SELF &&
m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE)
{
if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection()))
m_targets.setUnitTarget(target);
else
return SPELL_FAILED_BAD_TARGETS;
}
}
// Some special spells with non-caster only mode
// Fire Shield
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
m_spellInfo->SpellIconID == 16)
return SPELL_FAILED_BAD_TARGETS;
// Focus Magic (main spell)
if (m_spellInfo->Id == 54646)
return SPELL_FAILED_BAD_TARGETS;
}
// check pet presents
@ -4679,7 +4694,12 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
bool need = false;
for(uint32 i = 0; i < 3; ++i)
{
if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES)
if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE ||
m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND ||
m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND_2 ||
m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER ||
m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY ||
m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES)
{
need = true;
if(!target)

View file

@ -5438,7 +5438,7 @@ void Aura::HandleNoReagentUseAura(bool /*Apply*/, bool Real)
void Aura::HandleShapeshiftBoosts(bool apply)
{
uint32 spellId = 0;
uint32 spellId1 = 0;
uint32 spellId2 = 0;
uint32 HotWSpellId = 0;
uint32 MasterShaperSpellId = 0;
@ -5448,87 +5448,92 @@ void Aura::HandleShapeshiftBoosts(bool apply)
switch(form)
{
case FORM_CAT:
spellId = 3025;
spellId1 = 3025;
HotWSpellId = 24900;
MasterShaperSpellId = 48420;
break;
case FORM_TREE:
spellId = 5420;
spellId1 = 5420;
spellId2 = 34123;
MasterShaperSpellId = 48422;
break;
case FORM_TRAVEL:
spellId = 5419;
spellId1 = 5419;
break;
case FORM_AQUA:
spellId = 5421;
spellId1 = 5421;
break;
case FORM_BEAR:
spellId = 1178;
spellId1 = 1178;
spellId2 = 21178;
HotWSpellId = 24899;
MasterShaperSpellId = 48418;
break;
case FORM_DIREBEAR:
spellId = 9635;
spellId1 = 9635;
spellId2 = 21178;
HotWSpellId = 24899;
MasterShaperSpellId = 48418;
break;
case FORM_BATTLESTANCE:
spellId = 21156;
spellId1 = 21156;
break;
case FORM_DEFENSIVESTANCE:
spellId = 7376;
spellId1 = 7376;
break;
case FORM_BERSERKERSTANCE:
spellId = 7381;
spellId1 = 7381;
break;
case FORM_MOONKIN:
spellId = 24905;
spellId1 = 24905;
// aura from effect trigger spell
spellId2 = 24907;
MasterShaperSpellId = 48421;
break;
case FORM_FLIGHT:
spellId = 33948;
spellId1 = 33948;
spellId2 = 34764;
break;
case FORM_FLIGHT_EPIC:
spellId = 40122;
spellId1 = 40122;
spellId2 = 40121;
break;
case FORM_METAMORPHOSIS:
spellId = 54817;
spellId1 = 54817;
spellId2 = 54879;
break;
case FORM_SPIRITOFREDEMPTION:
spellId = 27792;
spellId1 = 27792;
spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
break;
case FORM_SHADOW:
spellId1 = 49868;
if(m_target->GetTypeId() == TYPEID_PLAYER) // Spell 49868 have same category as main form spell and share cooldown
((Player*)m_target)->RemoveSpellCooldown(49868);
break;
case FORM_GHOSTWOLF:
case FORM_AMBIENT:
case FORM_GHOUL:
case FORM_SHADOW:
case FORM_STEALTH:
case FORM_CREATURECAT:
case FORM_CREATUREBEAR:
spellId = 0;
spellId1 = 0;
break;
}
if(apply)
{
if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
if (spellId1) m_target->CastSpell(m_target, spellId1, true, NULL, this );
if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
if(m_target->GetTypeId() == TYPEID_PLAYER)
if (m_target->GetTypeId() == TYPEID_PLAYER)
{
const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if(itr->second->state == PLAYERSPELL_REMOVED) continue;
if(itr->first==spellId || itr->first==spellId2) continue;
if (itr->second->state == PLAYERSPELL_REMOVED) continue;
if (itr->first==spellId1 || itr->first==spellId2) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7))))
continue;
@ -5611,7 +5616,7 @@ void Aura::HandleShapeshiftBoosts(bool apply)
}
else
{
m_target->RemoveAurasDueToSpell(spellId);
m_target->RemoveAurasDueToSpell(spellId1);
m_target->RemoveAurasDueToSpell(spellId2);
m_target->RemoveAurasDueToSpell(MasterShaperSpellId);

View file

@ -4524,6 +4524,68 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return true;
}
bool Unit::HandleSpellCritChanceAuraProc(Unit *pVictim, uint32 /*damage*/, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown)
{
SpellEntry const *triggeredByAuraSpell = triggeredByAura->GetSpellProto();
Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
uint32 triggered_spell_id = 0;
Unit* target = pVictim;
int32 basepoints0 = 0;
switch(triggeredByAuraSpell->SpellFamilyName)
{
case SPELLFAMILY_MAGE:
{
switch(triggeredByAuraSpell->Id)
{
// Focus Magic
case 54646:
{
Unit* caster = triggeredByAura->GetCaster();
if(!caster)
return false;
triggered_spell_id = 54648;
target = caster;
break;
}
}
}
}
// processed charge only counting case
if(!triggered_spell_id)
return true;
SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
if(!triggerEntry)
{
sLog.outError("Unit::HandleHasteAuraProc: Spell %u have not existed triggered spell %u",triggeredByAuraSpell->Id,triggered_spell_id);
return false;
}
// default case
if(!target || target!=this && !target->isAlive())
return false;
if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
return false;
if(basepoints0)
CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
else
CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura);
if( cooldown && GetTypeId()==TYPEID_PLAYER )
((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown);
return true;
}
bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
SpellEntry const *dummySpell = triggeredByAura->GetSpellProto ();
@ -5223,6 +5285,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
pVictim->CastSpell(pVictim,57669,true,castItem,triggeredByAura);
return true; // no hidden cooldown
}
// Divine Aegis
if (dummySpell->SpellIconID == 2820)
{
@ -5230,6 +5293,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 47753;
break;
}
// Improved Shadowform
else if (dummySpell->SpellIconID == 217)
{
if(!roll_chance_i(triggerAmount))
return false;
RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
break;
}
switch(dummySpell->Id)
{
// Vampiric Embrace
@ -11130,6 +11204,12 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
triggeredByAura->SetInUse(false);
continue;
}
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s spell crit chance aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
if (!HandleSpellCritChanceAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
{
triggeredByAura->SetInUse(false);
continue;
}
break;
default:
// nothing do, just charges counter

View file

@ -1551,6 +1551,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent );
bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleSpellCritChanceAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown);
bool HandleMendingAuraProc(Aura* triggeredByAura);

View file

@ -26,7 +26,8 @@ void WorldSession::HandleVoiceSessionEnableOpcode( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: CMSG_VOICE_SESSION_ENABLE");
// uint8 isVoiceEnabled, uint8 isMicrophoneEnabled
recv_data.read_skip2<uint8,uint8>();
recv_data.read_skip<uint8>();
recv_data.read_skip<uint8>();
recv_data.hexlike();
}

View file

@ -141,7 +141,7 @@ void WorldSession::QueuePacket(WorldPacket* new_packet)
}
/// Logging helper for unexpected opcodes
void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason)
void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char *reason)
{
sLog.outError( "SESSION: received unexpected opcode %s (0x%.4X) %s",
LookupOpcodeName(packet->GetOpcode()),
@ -149,6 +149,15 @@ void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason)
reason);
}
/// Logging helper for unexpected opcodes
void WorldSession::LogUnprocessedTail(WorldPacket *packet)
{
sLog.outError( "SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)",
LookupOpcodeName(packet->GetOpcode()),
packet->GetOpcode(),
packet->rpos(),packet->wpos());
}
/// Update the WorldSession (triggered by World update)
bool WorldSession::Update(uint32 /*diff*/)
{
@ -182,30 +191,40 @@ bool WorldSession::Update(uint32 /*diff*/)
{
// skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
if(!m_playerRecentlyLogout)
logUnexpectedOpcode(packet, "the player has not logged in yet");
LogUnexpectedOpcode(packet, "the player has not logged in yet");
}
else if(_player->IsInWorld())
{
(this->*opHandle.handler)(*packet);
if (sLog.IsOutDebug() && packet->rpos() < packet->wpos())
LogUnprocessedTail(packet);
}
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
break;
case STATUS_TRANSFER:
if(!_player)
logUnexpectedOpcode(packet, "the player has not logged in yet");
LogUnexpectedOpcode(packet, "the player has not logged in yet");
else if(_player->IsInWorld())
logUnexpectedOpcode(packet, "the player is still in world");
LogUnexpectedOpcode(packet, "the player is still in world");
else
{
(this->*opHandle.handler)(*packet);
if (sLog.IsOutDebug() && packet->rpos() < packet->wpos())
LogUnprocessedTail(packet);
}
break;
case STATUS_AUTHED:
// prevent cheating with skip queue wait
if(m_inQueue)
{
logUnexpectedOpcode(packet, "the player not pass queue yet");
LogUnexpectedOpcode(packet, "the player not pass queue yet");
break;
}
m_playerRecentlyLogout = false;
(this->*opHandle.handler)(*packet);
if (sLog.IsOutDebug() && packet->rpos() < packet->wpos())
LogUnprocessedTail(packet);
break;
case STATUS_NEVER:
sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)",
@ -214,7 +233,7 @@ bool WorldSession::Update(uint32 /*diff*/)
break;
}
}
catch(ByteBufferException &exception)
catch(ByteBufferException &)
{
sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());

View file

@ -733,7 +733,8 @@ class MANGOS_DLL_SPEC WorldSession
void moveItems(Item* myItems[], Item* hisItems[]);
// logging helper
void logUnexpectedOpcode(WorldPacket *packet, const char * reason);
void LogUnexpectedOpcode(WorldPacket *packet, const char * reason);
void LogUnprocessedTail(WorldPacket *packet);
Player *_player;
WorldSocket *m_Socket;

View file

@ -737,7 +737,7 @@ int WorldSocket::ProcessIncoming (WorldPacket* new_pct)
}
}
}
catch(ByteBufferException &exception)
catch(ByteBufferException &)
{
sLog.outError("WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.",
opcode, GetRemoteAddress().c_str(), m_Session?m_Session->GetAccountId():-1);

View file

@ -27,15 +27,16 @@
class ByteBufferException
{
public:
ByteBufferException(bool add, size_t pos, size_t esize, size_t size):add(add), pos(pos), esize(esize), size(size)
ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size)
: add(_add), pos(_pos), esize(_esize), size(_size)
{
PrintPosError();
}
void PrintPosError() const
{
sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: %lu size: %lu) value with size: %lu",(add ? "put" : "get"),(unsigned long)pos, (unsigned long)size, (unsigned long)esize);
sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD,
(add ? "put" : "get"), pos, size, esize);
}
private:
bool add;
@ -262,22 +263,6 @@ class ByteBuffer
template<typename T>
void read_skip() { read_skip(sizeof(T)); }
template<typename T1, typename T2>
void read_skip2() { read_skip(sizeof(T1)+sizeof(T2)); }
template<>
void read_skip<char*>()
{
uint8 size = read<uint8>();
read_skip(size);
}
template<>
void read_skip<char const*>() { read_skip<char*>(); }
template<>
void read_skip<std::string>() { read_skip<char*>(); }
void read_skip(size_t skip)
{
if(_rpos + skip > size())
@ -512,7 +497,8 @@ class ByteBuffer
std::vector<uint8> _storage;
};
template <typename T> ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
template <typename T>
inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
{
b << (uint32)v.size();
for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i)
@ -522,7 +508,8 @@ template <typename T> ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
return b;
}
template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
template <typename T>
inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
{
uint32 vsize;
b >> vsize;
@ -536,7 +523,8 @@ template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
return b;
}
template <typename T> ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
template <typename T>
inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
{
b << (uint32)v.size();
for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i)
@ -546,7 +534,8 @@ template <typename T> ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
return b;
}
template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
template <typename T>
inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
{
uint32 vsize;
b >> vsize;
@ -560,7 +549,8 @@ template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
return b;
}
template <typename K, typename V> ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
template <typename K, typename V>
inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
{
b << (uint32)m.size();
for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i)
@ -570,7 +560,8 @@ template <typename K, typename V> ByteBuffer &operator<<(ByteBuffer &b, std::map
return b;
}
template <typename K, typename V> ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m)
template <typename K, typename V>
inline ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m)
{
uint32 msize;
b >> msize;
@ -584,4 +575,23 @@ template <typename K, typename V> ByteBuffer &operator>>(ByteBuffer &b, std::map
}
return b;
}
template<>
inline void ByteBuffer::read_skip<char*>()
{
std::string temp;
*this >> temp;
}
template<>
inline void ByteBuffer::read_skip<char const*>()
{
read_skip<char*>();
}
template<>
inline void ByteBuffer::read_skip<std::string>()
{
read_skip<char*>();
}
#endif

View file

@ -369,7 +369,11 @@ void Log::outString( const char * str, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stdout,str,);
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
if(m_colored)
ResetColor(true);
@ -379,7 +383,6 @@ void Log::outString( const char * str, ... )
{
outTimestamp(logfile);
va_list ap;
va_start(ap, str);
vfprintf(logfile, str, ap);
fprintf(logfile, "\n" );
@ -401,7 +404,11 @@ void Log::outError( const char * err, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stderr,err,);
va_list ap;
va_start(ap, err);
vutf8printf(stderr, err, &ap);
va_end(ap);
if(m_colored)
ResetColor(false);
@ -412,7 +419,6 @@ void Log::outError( const char * err, ... )
outTimestamp(logfile);
fprintf(logfile, "ERROR:" );
va_list ap;
va_start(ap, err);
vfprintf(logfile, err, ap);
va_end(ap);
@ -434,7 +440,11 @@ void Log::outErrorDb( const char * err, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stderr,err,);
va_list ap;
va_start(ap, err);
vutf8printf(stderr, err, &ap);
va_end(ap);
if(m_colored)
ResetColor(false);
@ -446,7 +456,6 @@ void Log::outErrorDb( const char * err, ... )
outTimestamp(logfile);
fprintf(logfile, "ERROR:" );
va_list ap;
va_start(ap, err);
vfprintf(logfile, err, ap);
va_end(ap);
@ -483,7 +492,10 @@ void Log::outBasic( const char * str, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stdout,str,);
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
if(m_colored)
ResetColor(true);
@ -518,7 +530,10 @@ void Log::outDetail( const char * str, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stdout,str,);
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
if(m_colored)
ResetColor(true);
@ -527,12 +542,14 @@ void Log::outDetail( const char * str, ... )
}
if(logfile && m_logFileLevel > 1)
{
va_list ap;
outTimestamp(logfile);
va_list ap;
va_start(ap, str);
vfprintf(logfile, str, ap);
fprintf(logfile, "\n" );
va_end(ap);
fprintf(logfile, "\n" );
fflush(logfile);
}
@ -548,7 +565,10 @@ void Log::outDebugInLine( const char * str, ... )
if(m_colored)
SetColor(true,m_colors[LogDebug]);
UTF8PRINTF(stdout,str,);
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
if(m_colored)
ResetColor(true);
@ -574,7 +594,10 @@ void Log::outDebug( const char * str, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stdout,str,);
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
if(m_colored)
ResetColor(true);
@ -609,7 +632,10 @@ void Log::outCommand( uint32 account, const char * str, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stdout,str,);
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
if(m_colored)
ResetColor(true);
@ -691,7 +717,11 @@ void Log::outMenu( const char * str, ... )
if(m_includeTime)
outTime();
UTF8PRINTF(stdout,str,);
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
ResetColor(true);
@ -699,7 +729,6 @@ void Log::outMenu( const char * str, ... )
{
outTimestamp(logfile);
va_list ap;
va_start(ap, str);
vfprintf(logfile, str, ap);
va_end(ap);

View file

@ -135,12 +135,8 @@ uint32 TimeStringToSecs(const std::string& timestring)
{
if(isdigit(*itr))
{
std::string str; //very complicated typecast char->const char*; is there no better way?
str += *itr;
const char* tmp = str.c_str();
buffer*=10;
buffer+=atoi(tmp);
buffer+= (*itr)-'0';
}
else
{
@ -419,3 +415,29 @@ bool Utf8FitTo(const std::string& str, std::wstring search)
return true;
}
void utf8printf(FILE *out, const char *str, ...)
{
va_list ap;
va_start(ap, str);
vutf8printf(stdout, str, &ap);
va_end(ap);
}
void vutf8printf(FILE *out, const char *str, va_list* ap)
{
#if PLATFORM == PLATFORM_WINDOWS
char temp_buf[32*1024];
wchar_t wtemp_buf[32*1024];
size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap);
size_t wtemp_len = 32*1024-1;
Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1);
fprintf(out, temp_buf);
#else
vfprintf(out, str, *ap);
#endif
}

View file

@ -283,32 +283,8 @@ std::wstring GetMainPartOfName(std::wstring wname, uint32 declension);
bool utf8ToConsole(const std::string& utf8str, std::string& conStr);
bool consoleToUtf8(const std::string& conStr,std::string& utf8str);
bool Utf8FitTo(const std::string& str, std::wstring search);
#if PLATFORM == PLATFORM_WINDOWS
#define UTF8PRINTF(OUT,FRM,RESERR) \
{ \
char temp_buf[32*1024]; \
va_list ap; \
va_start(ap, FRM); \
size_t temp_len = vsnprintf(temp_buf,32*1024,FRM,ap); \
va_end(ap); \
\
wchar_t wtemp_buf[32*1024]; \
size_t wtemp_len = 32*1024-1; \
if(!Utf8toWStr(temp_buf,temp_len,wtemp_buf,wtemp_len)) \
return RESERR; \
CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1);\
fprintf(OUT,temp_buf); \
}
#else
#define UTF8PRINTF(OUT,FRM,RESERR) \
{ \
va_list ap; \
va_start(ap, FRM); \
vfprintf(OUT, FRM, ap ); \
va_end(ap); \
}
#endif
void utf8printf(FILE *out, const char *str, ...);
void vutf8printf(FILE *out, const char *str, va_list* ap);
bool IsIPAddress(char const* ipaddress);
uint32 CreatePIDFile(const std::string& filename);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8383"
#define REVISION_NR "8396"
#endif // __REVISION_NR_H__