Merge branch 'master' into Playerbot
This commit is contained in:
@@ -988,7 +988,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (!IsSmart())
|
||||
break;
|
||||
|
||||
if (targets.empty())
|
||||
if (e.target.type == SMART_TARGET_NONE || e.target.type == SMART_TARGET_SELF)
|
||||
{
|
||||
CAST_AI(SmartAI, me->AI())->StopFollow(false);
|
||||
break;
|
||||
@@ -1644,6 +1644,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
break;
|
||||
}
|
||||
|
||||
if (e.action.orientation.turnAngle)
|
||||
{
|
||||
float turnOri = me->GetOrientation() + (static_cast<float>(e.action.orientation.turnAngle) * M_PI / 180.0f);
|
||||
me->SetFacingTo(turnOri);
|
||||
if (e.action.orientation.quickChange)
|
||||
me->SetOrientation(turnOri);
|
||||
break;
|
||||
}
|
||||
|
||||
if (e.GetTargetType() == SMART_TARGET_SELF)
|
||||
{
|
||||
me->SetFacingTo((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation());
|
||||
@@ -2824,6 +2833,48 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_SET_SCALE:
|
||||
{
|
||||
float scale = static_cast<float>(e.action.setScale.scale) / 100.0f;
|
||||
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (IsUnit(target))
|
||||
{
|
||||
target->ToUnit()->SetObjectScale(scale);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_SUMMON_RADIAL:
|
||||
{
|
||||
if (!me)
|
||||
break;
|
||||
|
||||
TempSummonType spawnType = (e.action.radialSummon.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN;
|
||||
|
||||
float startAngle = me->GetOrientation() + (static_cast<float>(e.action.radialSummon.startAngle) * M_PI / 180.0f);
|
||||
float stepAngle = static_cast<float>(e.action.radialSummon.stepAngle) * M_PI / 180.0f;
|
||||
|
||||
if (e.action.radialSummon.dist)
|
||||
{
|
||||
for (uint32 itr = 0; itr < e.action.radialSummon.repetitions; itr++)
|
||||
{
|
||||
Position summonPos = me->GetPosition();
|
||||
summonPos.RelocatePolarOffset(itr * stepAngle, static_cast<float>(e.action.radialSummon.dist));
|
||||
me->SummonCreature(e.action.radialSummon.summonEntry, summonPos, spawnType, e.action.radialSummon.summonDuration);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32 itr = 0; itr < e.action.radialSummon.repetitions; itr++)
|
||||
{
|
||||
float currentAngle = startAngle + (itr * stepAngle);
|
||||
me->SummonCreature(e.action.radialSummon.summonEntry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), currentAngle, spawnType, e.action.radialSummon.summonDuration);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
break;
|
||||
@@ -4157,34 +4208,105 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
break;
|
||||
case SMART_EVENT_NEAR_PLAYERS:
|
||||
{
|
||||
ObjectVector units;
|
||||
GetWorldObjectsInDist(units, static_cast<float>(e.event.nearPlayer.radius));
|
||||
uint32 playerCount = 0;
|
||||
ObjectVector targets;
|
||||
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearPlayer.radius));
|
||||
|
||||
if (!units.empty())
|
||||
if (!targets.empty())
|
||||
{
|
||||
if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (IsPlayer(target))
|
||||
playerCount++;
|
||||
|
||||
if (units.size() >= e.event.nearPlayer.minCount)
|
||||
ProcessAction(e, unit);
|
||||
if (playerCount >= e.event.nearPlayer.minCount)
|
||||
ProcessAction(e, target->ToUnit());
|
||||
}
|
||||
}
|
||||
RecalcTimer(e, e.event.nearPlayer.checkTimer, e.event.nearPlayer.checkTimer);
|
||||
RecalcTimer(e, e.event.nearPlayer.repeatMin, e.event.nearPlayer.repeatMax);
|
||||
break;
|
||||
}
|
||||
case SMART_EVENT_NEAR_PLAYERS_NEGATION:
|
||||
{
|
||||
ObjectVector units;
|
||||
GetWorldObjectsInDist(units, static_cast<float>(e.event.nearPlayerNegation.radius));
|
||||
uint32 playerCount = 0;
|
||||
ObjectVector targets;
|
||||
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearPlayerNegation.radius));
|
||||
|
||||
if (!units.empty())
|
||||
if (!targets.empty())
|
||||
{
|
||||
if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (IsPlayer(target))
|
||||
playerCount++;
|
||||
}
|
||||
|
||||
if (units.size() < e.event.nearPlayerNegation.minCount)
|
||||
if (playerCount <= e.event.nearPlayerNegation.maxCount)
|
||||
ProcessAction(e, unit);
|
||||
}
|
||||
RecalcTimer(e, e.event.nearPlayerNegation.checkTimer, e.event.nearPlayerNegation.checkTimer);
|
||||
RecalcTimer(e, e.event.nearPlayerNegation.repeatMin, e.event.nearPlayerNegation.repeatMax);
|
||||
break;
|
||||
}
|
||||
case SMART_EVENT_NEAR_UNIT:
|
||||
{
|
||||
uint32 unitCount = 0;
|
||||
ObjectVector targets;
|
||||
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearUnit.range));
|
||||
|
||||
if (!targets.empty())
|
||||
{
|
||||
if (e.event.nearUnit.type)
|
||||
{
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (IsGameObject(target) && target->GetEntry() == e.event.nearUnit.entry)
|
||||
unitCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
if (IsCreature(target) && target->GetEntry() == e.event.nearUnit.entry)
|
||||
unitCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (unitCount >= e.event.nearUnit.count)
|
||||
ProcessAction(e, unit);
|
||||
}
|
||||
RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer);
|
||||
break;
|
||||
}
|
||||
case SMART_EVENT_AREA_CASTING:
|
||||
{
|
||||
if (!me || !me->IsEngaged())
|
||||
return;
|
||||
|
||||
float range = static_cast<float>(e.event.areaCasting.range);
|
||||
ThreatContainer::StorageType threatList = me->GetThreatMgr().GetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
|
||||
{
|
||||
if (e.event.areaCasting.range && !me->IsWithinDistInMap(target, range))
|
||||
continue;
|
||||
|
||||
if (!target || !target->IsNonMeleeSpellCast(false, false, true))
|
||||
continue;
|
||||
|
||||
if (e.event.areaCasting.spellId > 0)
|
||||
if (Spell* currSpell = target->GetCurrentSpell(CURRENT_GENERIC_SPELL))
|
||||
if (currSpell->m_spellInfo->Id != e.event.areaCasting.spellId)
|
||||
continue;
|
||||
|
||||
ProcessAction(e, target);
|
||||
RecalcTimer(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMin);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If no targets are found and it's off cooldown, check again
|
||||
RecalcTimer(e, e.event.areaCasting.checkTimer, e.event.areaCasting.checkTimer);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -4223,6 +4345,12 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
|
||||
case SMART_EVENT_DISTANCE_GAMEOBJECT:
|
||||
RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat);
|
||||
break;
|
||||
case SMART_EVENT_NEAR_UNIT:
|
||||
RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer);
|
||||
break;
|
||||
case SMART_EVENT_AREA_CASTING:
|
||||
RecalcTimer(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax);
|
||||
break;
|
||||
default:
|
||||
e.active = true;
|
||||
break;
|
||||
@@ -4276,6 +4404,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
{
|
||||
case SMART_EVENT_NEAR_PLAYERS:
|
||||
case SMART_EVENT_NEAR_PLAYERS_NEGATION:
|
||||
case SMART_EVENT_NEAR_UNIT:
|
||||
case SMART_EVENT_UPDATE:
|
||||
case SMART_EVENT_UPDATE_OOC:
|
||||
case SMART_EVENT_UPDATE_IC:
|
||||
@@ -4285,6 +4414,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
|
||||
case SMART_EVENT_TARGET_MANA_PCT:
|
||||
case SMART_EVENT_RANGE:
|
||||
case SMART_EVENT_VICTIM_CASTING:
|
||||
case SMART_EVENT_AREA_CASTING:
|
||||
case SMART_EVENT_FRIENDLY_HEALTH:
|
||||
case SMART_EVENT_FRIENDLY_IS_CC:
|
||||
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
|
||||
|
||||
@@ -280,6 +280,10 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
||||
if (temp.event.minMaxRepeat.min == 0 && temp.event.minMaxRepeat.max == 0)
|
||||
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
|
||||
break;
|
||||
case SMART_EVENT_AREA_CASTING:
|
||||
if (temp.event.areaCasting.repeatMin == 0 && temp.event.areaCasting.repeatMax == 0)
|
||||
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
|
||||
break;
|
||||
case SMART_EVENT_FRIENDLY_IS_CC:
|
||||
if (temp.event.friendlyCC.repeatMin == 0 && temp.event.friendlyCC.repeatMax == 0)
|
||||
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
|
||||
@@ -346,10 +350,12 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
||||
case SMART_EVENT_TARGET_MANA_PCT:
|
||||
case SMART_EVENT_RANGE:
|
||||
case SMART_EVENT_VICTIM_CASTING:
|
||||
case SMART_EVENT_AREA_CASTING:
|
||||
case SMART_EVENT_TARGET_BUFFED:
|
||||
case SMART_EVENT_IS_BEHIND_TARGET:
|
||||
case SMART_EVENT_INSTANCE_PLAYER_ENTER:
|
||||
case SMART_EVENT_TRANSPORT_ADDCREATURE:
|
||||
case SMART_EVENT_NEAR_PLAYERS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -572,6 +578,8 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
|
||||
case SMART_EVENT_SUMMONED_UNIT_DIES: return sizeof(SmartEvent::summoned);
|
||||
case SMART_EVENT_NEAR_PLAYERS: return sizeof(SmartEvent::nearPlayer);
|
||||
case SMART_EVENT_NEAR_PLAYERS_NEGATION: return sizeof(SmartEvent::nearPlayerNegation);
|
||||
case SMART_EVENT_NEAR_UNIT: return sizeof(SmartEvent::nearUnit);
|
||||
case SMART_EVENT_AREA_CASTING: return sizeof(SmartEvent::areaCasting);
|
||||
default:
|
||||
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an event {} with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetEventType());
|
||||
@@ -671,7 +679,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_SET_COUNTER: return sizeof(SmartAction::setCounter);
|
||||
case SMART_ACTION_STORE_TARGET_LIST: return sizeof(SmartAction::storeTargets);
|
||||
case SMART_ACTION_WP_RESUME: return NO_PARAMS;
|
||||
case SMART_ACTION_SET_ORIENTATION: return NO_PARAMS;
|
||||
case SMART_ACTION_SET_ORIENTATION: return sizeof(SmartAction::orientation);
|
||||
case SMART_ACTION_CREATE_TIMED_EVENT: return sizeof(SmartAction::timeEvent);
|
||||
case SMART_ACTION_PLAYMOVIE: return sizeof(SmartAction::movie);
|
||||
case SMART_ACTION_MOVE_TO_POS: return sizeof(SmartAction::moveToPos);
|
||||
@@ -763,6 +771,8 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_MUSIC: return sizeof(SmartAction::music);
|
||||
case SMART_ACTION_SET_GUID: return sizeof(SmartAction::setGuid);
|
||||
case SMART_ACTION_DISABLE: return sizeof(SmartAction::disable);
|
||||
case SMART_ACTION_SET_SCALE: return sizeof(SmartAction::setScale);
|
||||
case SMART_ACTION_SUMMON_RADIAL: return sizeof(SmartAction::radialSummon);
|
||||
default:
|
||||
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
@@ -1041,6 +1051,16 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
if (!IsMinMaxValid(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax))
|
||||
return false;
|
||||
break;
|
||||
case SMART_EVENT_AREA_CASTING:
|
||||
if (e.event.areaCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.areaCasting.spellId))
|
||||
{
|
||||
LOG_ERROR("scripts.ai.sai", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Spell entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsMinMaxValid(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax))
|
||||
return false;
|
||||
break;
|
||||
case SMART_EVENT_PASSENGER_BOARDED:
|
||||
case SMART_EVENT_PASSENGER_REMOVED:
|
||||
if (!IsMinMaxValid(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax))
|
||||
@@ -1270,6 +1290,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_EVENT_GO_EVENT_INFORM:
|
||||
case SMART_EVENT_NEAR_PLAYERS:
|
||||
case SMART_EVENT_NEAR_PLAYERS_NEGATION:
|
||||
if (!IsMinMaxValid(e, e.event.nearPlayer.repeatMin, e.event.nearPlayer.repeatMax))
|
||||
return false;
|
||||
break;
|
||||
case SMART_EVENT_NEAR_UNIT:
|
||||
case SMART_EVENT_TIMED_EVENT_TRIGGERED:
|
||||
case SMART_EVENT_INSTANCE_PLAYER_ENTER:
|
||||
case SMART_EVENT_TRANSPORT_RELOCATE:
|
||||
@@ -1920,6 +1944,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_PLAY_CINEMATIC:
|
||||
case SMART_ACTION_SET_GUID:
|
||||
case SMART_ACTION_DISABLE:
|
||||
case SMART_ACTION_SET_SCALE:
|
||||
case SMART_ACTION_SUMMON_RADIAL:
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
|
||||
|
||||
@@ -206,10 +206,12 @@ enum SMART_EVENT
|
||||
/* AC Custom Events */
|
||||
SMART_EVENT_AC_START = 100,
|
||||
|
||||
SMART_EVENT_NEAR_PLAYERS = 101, // min, radius, first timer, check timer
|
||||
SMART_EVENT_NEAR_PLAYERS_NEGATION = 102, // min, radius, first timer, check timer
|
||||
SMART_EVENT_NEAR_PLAYERS = 101, // min, radius, first timer, repeatMin, repeatMax
|
||||
SMART_EVENT_NEAR_PLAYERS_NEGATION = 102, // max, radius, first timer, repeatMin, repeatMax
|
||||
SMART_EVENT_NEAR_UNIT = 103, // type (0: creature 1: gob), entry, count, range, timer
|
||||
SMART_EVENT_AREA_CASTING = 104, // spellId (0: any), range (0: any), repeatMin, repeatMax, checkTimer
|
||||
|
||||
SMART_EVENT_AC_END = 103
|
||||
SMART_EVENT_AC_END = 105
|
||||
};
|
||||
|
||||
struct SmartEvent
|
||||
@@ -482,17 +484,37 @@ struct SmartEvent
|
||||
uint32 minCount;
|
||||
uint32 radius;
|
||||
uint32 firstTimer;
|
||||
uint32 checkTimer;
|
||||
uint32 repeatMin;
|
||||
uint32 repeatMax;
|
||||
} nearPlayer;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 minCount;
|
||||
uint32 maxCount;
|
||||
uint32 radius;
|
||||
uint32 firstTimer;
|
||||
uint32 checkTimer;
|
||||
uint32 repeatMin;
|
||||
uint32 repeatMax;
|
||||
} nearPlayerNegation;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 type;
|
||||
uint32 entry;
|
||||
uint32 count;
|
||||
uint32 range;
|
||||
uint32 timer;
|
||||
} nearUnit;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 spellId;
|
||||
uint32 range;
|
||||
uint32 repeatMin;
|
||||
uint32 repeatMax;
|
||||
uint32 checkTimer;
|
||||
} areaCasting;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 param1;
|
||||
@@ -588,7 +610,7 @@ enum SMART_ACTION
|
||||
SMART_ACTION_SET_COUNTER = 63, // id, value, reset (0/1)
|
||||
SMART_ACTION_STORE_TARGET_LIST = 64, // varID,
|
||||
SMART_ACTION_WP_RESUME = 65, // none
|
||||
SMART_ACTION_SET_ORIENTATION = 66, // quick change, random orientation? (0/1)
|
||||
SMART_ACTION_SET_ORIENTATION = 66, // quick change, random orientation? (0/1), turnAngle
|
||||
SMART_ACTION_CREATE_TIMED_EVENT = 67, // id, InitialMin, InitialMax, RepeatMin(only if it repeats), RepeatMax(only if it repeats), chance
|
||||
SMART_ACTION_PLAYMOVIE = 68, // entry
|
||||
SMART_ACTION_MOVE_TO_POS = 69, // PointId (optional x,y,z offset), transport, controlled, ContactDistance
|
||||
@@ -693,9 +715,11 @@ enum SMART_ACTION
|
||||
SMART_ACTION_DO_ACTION = 223, // ActionId
|
||||
SMART_ACTION_ATTACK_STOP = 224, //
|
||||
SMART_ACTION_SET_GUID = 225, // Sends the invoker's or the base object's own ObjectGuid to target
|
||||
SMART_ACTION_DISABLE = 226, // Disable the targeted creatures, setting them Invisible and Immune to All
|
||||
SMART_ACTION_DISABLE = 226, // state
|
||||
SMART_ACTION_SET_SCALE = 227, // scale
|
||||
SMART_ACTION_SUMMON_RADIAL = 228, // summonEntry, summonDuration, repetitions, startAngle, stepAngle, dist
|
||||
|
||||
SMART_ACTION_AC_END = 227, // placeholder
|
||||
SMART_ACTION_AC_END = 229, // placeholder
|
||||
};
|
||||
|
||||
enum class SmartActionSummonCreatureFlags
|
||||
@@ -1289,6 +1313,7 @@ struct SmartAction
|
||||
{
|
||||
uint32 quickChange;
|
||||
uint32 random;
|
||||
uint32 turnAngle;
|
||||
} orientation;
|
||||
|
||||
struct
|
||||
@@ -1376,6 +1401,21 @@ struct SmartAction
|
||||
{
|
||||
SAIBool state;
|
||||
} disable;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 scale;
|
||||
} setScale;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 summonEntry;
|
||||
uint32 summonDuration;
|
||||
uint32 repetitions;
|
||||
uint32 startAngle;
|
||||
uint32 stepAngle;
|
||||
uint32 dist;
|
||||
} radialSummon;
|
||||
//! Note for any new future actions
|
||||
//! All parameters must have type uint32
|
||||
|
||||
@@ -1777,8 +1817,10 @@ const uint32 SmartAIEventMask[SMART_EVENT_AC_END][2] =
|
||||
{ 0, 0 }, // 98
|
||||
{ 0, 0 }, // 99
|
||||
{ 0, 0 }, // 100
|
||||
{SMART_EVENT_NEAR_PLAYERS, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||
{SMART_EVENT_NEAR_PLAYERS_NEGATION, SMART_SCRIPT_TYPE_MASK_CREATURE }
|
||||
{SMART_EVENT_NEAR_PLAYERS, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
|
||||
{SMART_EVENT_NEAR_PLAYERS_NEGATION, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
|
||||
{SMART_EVENT_NEAR_UNIT, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
|
||||
{SMART_EVENT_AREA_CASTING, SMART_SCRIPT_TYPE_MASK_CREATURE }
|
||||
};
|
||||
|
||||
enum SmartEventFlags
|
||||
|
||||
@@ -2394,6 +2394,11 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
|
||||
return true;
|
||||
}
|
||||
|
||||
CompletedAchievementMap const& AchievementMgr::GetCompletedAchievements()
|
||||
{
|
||||
return _completedAchievements;
|
||||
}
|
||||
|
||||
AchievementGlobalMgr* AchievementGlobalMgr::instance()
|
||||
{
|
||||
static AchievementGlobalMgr instance;
|
||||
|
||||
@@ -300,6 +300,7 @@ public:
|
||||
|
||||
void RemoveCriteriaProgress(AchievementCriteriaEntry const* entry);
|
||||
CriteriaProgress* GetCriteriaProgress(AchievementCriteriaEntry const* entry);
|
||||
CompletedAchievementMap const& GetCompletedAchievements();
|
||||
|
||||
private:
|
||||
enum ProgressType { PROGRESS_SET, PROGRESS_ACCUMULATE, PROGRESS_HIGHEST, PROGRESS_RESET };
|
||||
|
||||
@@ -727,7 +727,7 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player,
|
||||
bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player,
|
||||
std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
|
||||
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
|
||||
uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder)
|
||||
uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout)
|
||||
{
|
||||
uint32 itrcounter = 0;
|
||||
|
||||
@@ -754,14 +754,11 @@ bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
|
||||
|
||||
for (AuctionEntryMap::const_iterator itr = _auctionsMap.begin(); itr != _auctionsMap.end(); ++itr)
|
||||
{
|
||||
if (!AsyncAuctionListingMgr::IsAuctionListingAllowed()) // pussywizard: World::Update is waiting for us...
|
||||
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
|
||||
{
|
||||
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
|
||||
if (GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= searchTimeout) // pussywizard: stop immediately if diff is high or waiting too long
|
||||
{
|
||||
if (sWorldUpdateTime.GetAverageUpdateTime() >= 30 || GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= 10ms) // pussywizard: stop immediately if diff is high or waiting too long
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
bool BuildListAuctionItems(WorldPacket& data, Player* player,
|
||||
std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
|
||||
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
|
||||
uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder);
|
||||
uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout);
|
||||
|
||||
private:
|
||||
AuctionEntryMap _auctionsMap;
|
||||
@@ -184,7 +184,6 @@ public:
|
||||
|
||||
AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId);
|
||||
AuctionHouseObject* GetAuctionsMapByHouseId(uint8 auctionHouseId);
|
||||
AuctionHouseObject* GetBidsMap(uint32 factionTemplateId);
|
||||
|
||||
Item* GetAItem(ObjectGuid itemGuid)
|
||||
{
|
||||
|
||||
@@ -174,11 +174,11 @@ void KillRewarder::_RewardXP(Player* player, float rate)
|
||||
}
|
||||
}
|
||||
|
||||
void KillRewarder::_RewardReputation(Player* player, float rate)
|
||||
void KillRewarder::_RewardReputation(Player* player)
|
||||
{
|
||||
// 4.3. Give reputation (player must not be on BG).
|
||||
// Even dead players and corpses are rewarded.
|
||||
player->RewardReputation(_victim, rate);
|
||||
player->RewardReputation(_victim);
|
||||
}
|
||||
|
||||
void KillRewarder::_RewardKillCredit(Player* player)
|
||||
@@ -208,7 +208,6 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
|
||||
if (!_isPvP || _isBattleGround)
|
||||
{
|
||||
float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
|
||||
float reputationRate = _group ? _groupRate * float(player->GetLevel()) / _sumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
|
||||
sScriptMgr->OnRewardKillRewarder(player, isDungeon, xpRate); // Personal rate is 100%.
|
||||
|
||||
if (_xp)
|
||||
@@ -219,7 +218,7 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
|
||||
if (!_isBattleGround)
|
||||
{
|
||||
// If killer is in dungeon then all members receive full reputation at kill.
|
||||
_RewardReputation(player, isDungeon ? 1.0f : reputationRate);
|
||||
_RewardReputation(player);
|
||||
_RewardKillCredit(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ private:
|
||||
|
||||
void _RewardHonor(Player* player);
|
||||
void _RewardXP(Player* player, float rate);
|
||||
void _RewardReputation(Player* player, float rate);
|
||||
void _RewardReputation(Player* player);
|
||||
void _RewardKillCredit(Player* player);
|
||||
void _RewardPlayer(Player* player, bool isDungeon);
|
||||
void _RewardGroup();
|
||||
|
||||
@@ -5858,7 +5858,7 @@ float Player::CalculateReputationGain(ReputationSource source, uint32 creatureOr
|
||||
}
|
||||
|
||||
// Calculates how many reputation points player gains in victim's enemy factions
|
||||
void Player::RewardReputation(Unit* victim, float rate)
|
||||
void Player::RewardReputation(Unit* victim)
|
||||
{
|
||||
if (!victim || victim->GetTypeId() == TYPEID_PLAYER)
|
||||
return;
|
||||
@@ -5887,7 +5887,6 @@ void Player::RewardReputation(Unit* victim, float rate)
|
||||
if (Rep->RepFaction1 && (!Rep->TeamDependent || teamId == TEAM_ALLIANCE))
|
||||
{
|
||||
float donerep1 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->GetLevel(), static_cast<float>(Rep->RepValue1), ChampioningFaction ? ChampioningFaction : Rep->RepFaction1);
|
||||
donerep1 *= rate;
|
||||
|
||||
FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction1);
|
||||
if (factionEntry1)
|
||||
@@ -5899,7 +5898,6 @@ void Player::RewardReputation(Unit* victim, float rate)
|
||||
if (Rep->RepFaction2 && (!Rep->TeamDependent || teamId == TEAM_HORDE))
|
||||
{
|
||||
float donerep2 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->GetLevel(), static_cast<float>(Rep->RepValue2), ChampioningFaction ? ChampioningFaction : Rep->RepFaction2);
|
||||
donerep2 *= rate;
|
||||
|
||||
FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction2);
|
||||
if (factionEntry2)
|
||||
@@ -13444,7 +13442,10 @@ LootItem* Player::StoreLootItem(uint8 lootSlot, Loot* loot, InventoryResult& msg
|
||||
LootItem* item = loot->LootItemInSlot(lootSlot, this, &qitem, &ffaitem, &conditem);
|
||||
if (!item || item->is_looted)
|
||||
{
|
||||
SendEquipError(EQUIP_ERR_ALREADY_LOOTED, nullptr, nullptr);
|
||||
if (!sScriptMgr->CanSendErrorAlreadyLooted(this))
|
||||
{
|
||||
SendEquipError(EQUIP_ERR_ALREADY_LOOTED, nullptr, nullptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -2086,7 +2086,7 @@ public:
|
||||
ReputationMgr& GetReputationMgr() { return *m_reputationMgr; }
|
||||
[[nodiscard]] ReputationMgr const& GetReputationMgr() const { return *m_reputationMgr; }
|
||||
[[nodiscard]] ReputationRank GetReputationRank(uint32 faction_id) const;
|
||||
void RewardReputation(Unit* victim, float rate);
|
||||
void RewardReputation(Unit* victim);
|
||||
void RewardReputation(Quest const* quest);
|
||||
|
||||
float CalculateReputationGain(ReputationSource source, uint32 creatureOrQuestLevel, float rep, int32 faction, bool noQuestBonus = false);
|
||||
|
||||
@@ -668,23 +668,24 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket& recvData)
|
||||
recvData >> listfrom; // not used in fact (this list does not have page control in client)
|
||||
|
||||
// pussywizard:
|
||||
const uint32 delay = 4500;
|
||||
const uint32 now = GameTime::GetGameTimeMS().count();
|
||||
const Milliseconds now = GameTime::GetGameTimeMS();
|
||||
if (_lastAuctionListOwnerItemsMSTime > now) // list is pending
|
||||
return;
|
||||
uint32 diff = getMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);
|
||||
|
||||
const Milliseconds delay = Milliseconds(4500);
|
||||
Milliseconds diff = GetMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);
|
||||
if (diff > delay)
|
||||
diff = delay;
|
||||
|
||||
_lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual exectuing will change this to getMSTime of that moment
|
||||
_player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID(), true), _player->m_Events.CalculateTime(delay - diff));
|
||||
_lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual executing will change this to getMSTime of that moment
|
||||
_player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID()), _player->m_Events.CalculateTime(delay.count() - diff.count()));
|
||||
}
|
||||
|
||||
void WorldSession::HandleAuctionListOwnerItemsEvent(ObjectGuid creatureGuid)
|
||||
{
|
||||
LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS");
|
||||
|
||||
_lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS().count(); // pussywizard
|
||||
_lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS(); // pussywizard
|
||||
|
||||
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(creatureGuid, UNIT_NPC_FLAG_AUCTIONEER);
|
||||
if (!creature)
|
||||
@@ -757,17 +758,17 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
|
||||
}
|
||||
|
||||
// pussywizard:
|
||||
const uint32 delay = 2000;
|
||||
const uint32 now = GameTime::GetGameTimeMS().count();
|
||||
uint32 diff = getMSTimeDiff(_lastAuctionListItemsMSTime, now);
|
||||
const Milliseconds delay = 2s;
|
||||
const Milliseconds now = GameTime::GetGameTimeMS();
|
||||
Milliseconds diff = GetMSTimeDiff(_lastAuctionListItemsMSTime, now);
|
||||
if (diff > delay)
|
||||
{
|
||||
diff = delay;
|
||||
}
|
||||
_lastAuctionListItemsMSTime = now + delay - diff;
|
||||
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
|
||||
AsyncAuctionListingMgr::GetTempList().push_back(AuctionListItemsDelayEvent(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
|
||||
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder));
|
||||
AsyncAuctionListingMgr::GetTempList().emplace_back(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
|
||||
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder);
|
||||
}
|
||||
|
||||
void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)
|
||||
|
||||
@@ -93,6 +93,8 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
|
||||
loot = &creature->loot;
|
||||
}
|
||||
|
||||
sScriptMgr->OnAfterCreatureLoot(player);
|
||||
|
||||
InventoryResult msg;
|
||||
LootItem* lootItem = player->StoreLootItem(lootSlot, loot, msg);
|
||||
if (msg != EQUIP_ERR_OK && lguid.IsItem() && loot->loot_type != LOOT_CORPSE)
|
||||
@@ -209,6 +211,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
|
||||
}
|
||||
else
|
||||
{
|
||||
sScriptMgr->OnAfterCreatureLootMoney(player);
|
||||
player->ModifyMoney(loot->gold);
|
||||
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold);
|
||||
|
||||
|
||||
@@ -22,11 +22,9 @@
|
||||
#include "Player.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
uint32 AsyncAuctionListingMgr::auctionListingDiff = 0;
|
||||
bool AsyncAuctionListingMgr::auctionListingAllowed = false;
|
||||
Milliseconds AsyncAuctionListingMgr::auctionListingDiff = Milliseconds::zero();
|
||||
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingList;
|
||||
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingListTemp;
|
||||
std::mutex AsyncAuctionListingMgr::auctionListingLock;
|
||||
std::mutex AsyncAuctionListingMgr::auctionListingTempLock;
|
||||
|
||||
bool AuctionListOwnerItemsDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
@@ -60,18 +58,19 @@ bool AuctionListItemsDelayEvent::Execute()
|
||||
|
||||
wstrToLower(wsearchedname);
|
||||
|
||||
uint32 searchTimeout = sWorld->getIntConfig(CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT);
|
||||
bool result = auctionHouse->BuildListAuctionItems(data, plr,
|
||||
wsearchedname, _listfrom, _levelmin, _levelmax, _usable,
|
||||
_auctionSlotID, _auctionMainCategory, _auctionSubCategory, _quality,
|
||||
count, totalcount, _getAll, _sortOrder);
|
||||
count, totalcount, _getAll, _sortOrder, Milliseconds(searchTimeout));
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
data.put<uint32>(0, count);
|
||||
data << (uint32) totalcount;
|
||||
data << (uint32) 300; // clientside search cooldown [ms] (gray search button)
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
if (result)
|
||||
{
|
||||
data.put<uint32>(0, count);
|
||||
data << (uint32) totalcount;
|
||||
data << (uint32) 300; // clientside search cooldown [ms] (gray search button)
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,30 +25,28 @@
|
||||
class AuctionListOwnerItemsDelayEvent : public BasicEvent
|
||||
{
|
||||
public:
|
||||
AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid, bool o) : creatureGuid(_creatureGuid), playerguid(guid), owner(o) {}
|
||||
AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid) : creatureGuid(_creatureGuid), playerguid(guid) {}
|
||||
~AuctionListOwnerItemsDelayEvent() override {}
|
||||
|
||||
bool Execute(uint64 e_time, uint32 p_time) override;
|
||||
void Abort(uint64 /*e_time*/) override {}
|
||||
bool getOwner() { return owner; }
|
||||
|
||||
private:
|
||||
ObjectGuid creatureGuid;
|
||||
ObjectGuid playerguid;
|
||||
bool owner;
|
||||
};
|
||||
|
||||
class AuctionListItemsDelayEvent
|
||||
{
|
||||
public:
|
||||
AuctionListItemsDelayEvent(uint32 msTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax,
|
||||
AuctionListItemsDelayEvent(Milliseconds pickupTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax,
|
||||
uint8 usable, uint32 auctionSlotID, uint32 auctionMainCategory, uint32 auctionSubCategory, uint32 quality, uint8 getAll, AuctionSortOrderVector sortOrder) :
|
||||
_msTimer(msTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax),_usable(usable),
|
||||
_pickupTimer(pickupTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax),_usable(usable),
|
||||
_auctionSlotID(auctionSlotID), _auctionMainCategory(auctionMainCategory), _auctionSubCategory(auctionSubCategory), _quality(quality), _getAll(getAll), _sortOrder(sortOrder) { }
|
||||
|
||||
bool Execute();
|
||||
|
||||
uint32 _msTimer;
|
||||
Milliseconds _pickupTimer;
|
||||
ObjectGuid _playerguid;
|
||||
ObjectGuid _creatureguid;
|
||||
std::string _searchedname;
|
||||
@@ -67,23 +65,17 @@ public:
|
||||
class AsyncAuctionListingMgr
|
||||
{
|
||||
public:
|
||||
static void Update(uint32 diff) { auctionListingDiff += diff; }
|
||||
static uint32 GetDiff() { return auctionListingDiff; }
|
||||
static void ResetDiff() { auctionListingDiff = 0; }
|
||||
static bool IsAuctionListingAllowed() { return auctionListingAllowed; }
|
||||
static void SetAuctionListingAllowed(bool a) { auctionListingAllowed = a; }
|
||||
|
||||
static void Update(Milliseconds diff) { auctionListingDiff += diff; }
|
||||
static Milliseconds GetDiff() { return auctionListingDiff; }
|
||||
static void ResetDiff() { auctionListingDiff = Milliseconds::zero(); }
|
||||
static std::list<AuctionListItemsDelayEvent>& GetList() { return auctionListingList; }
|
||||
static std::list<AuctionListItemsDelayEvent>& GetTempList() { return auctionListingListTemp; }
|
||||
static std::mutex& GetLock() { return auctionListingLock; }
|
||||
static std::mutex& GetTempLock() { return auctionListingTempLock; }
|
||||
|
||||
private:
|
||||
static uint32 auctionListingDiff;
|
||||
static bool auctionListingAllowed;
|
||||
static Milliseconds auctionListingDiff;
|
||||
static std::list<AuctionListItemsDelayEvent> auctionListingList;
|
||||
static std::list<AuctionListItemsDelayEvent> auctionListingListTemp;
|
||||
static std::mutex auctionListingLock;
|
||||
static std::mutex auctionListingTempLock;
|
||||
};
|
||||
|
||||
|
||||
@@ -913,6 +913,37 @@ bool ScriptMgr::CanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScriptMgr::CanSendErrorAlreadyLooted(Player* player)
|
||||
{
|
||||
auto ret = IsValidBoolScript<PlayerScript>([&](PlayerScript* script)
|
||||
{
|
||||
return !script->CanSendErrorAlreadyLooted(player);
|
||||
});
|
||||
|
||||
if (ret && *ret)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptMgr::OnAfterCreatureLoot(Player* player)
|
||||
{
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
{
|
||||
script->OnAfterCreatureLoot(player);
|
||||
});
|
||||
}
|
||||
|
||||
void ScriptMgr::OnAfterCreatureLootMoney(Player* player)
|
||||
{
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
{
|
||||
script->OnAfterCreatureLootMoney(player);
|
||||
});
|
||||
}
|
||||
|
||||
void ScriptMgr::PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type)
|
||||
{
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
@@ -986,7 +1017,7 @@ void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result,
|
||||
void ScriptMgr::OnUpdateGatheringSkill(Player *player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32 &gain) {
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
{
|
||||
script->OnUpdateGatheringSkill(player, skillId, gray, green, yellow, currentLevel, gain);
|
||||
script->OnUpdateGatheringSkill(player, skillId, currentLevel, gray, green, yellow, gain);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1483,6 +1483,30 @@ public:
|
||||
virtual void AnticheatUpdateMovementInfo(Player* /*player*/, MovementInfo const& /*movementInfo*/) { }
|
||||
[[nodiscard]] virtual bool AnticheatHandleDoubleJump(Player* /*player*/, Unit* /*mover*/) { return true; }
|
||||
[[nodiscard]] virtual bool AnticheatCheckMovementInfo(Player* /*player*/, MovementInfo const& /*movementInfo*/, Unit* /*mover*/, bool /*jump*/) { return true; }
|
||||
|
||||
/**
|
||||
* @brief This hook is called, to avoid displaying the error message that the body has already been stripped
|
||||
*
|
||||
* @param player Contains information about the Player
|
||||
*
|
||||
* @return true Avoiding displaying the error message that the loot has already been taken.
|
||||
*/
|
||||
virtual bool CanSendErrorAlreadyLooted(Player* /*player*/) { return true; }
|
||||
|
||||
/**
|
||||
* @brief It is used when an item is taken from a creature.
|
||||
*
|
||||
* @param player Contains information about the Player
|
||||
*
|
||||
*/
|
||||
virtual void OnAfterCreatureLoot(Player* /*player*/) { }
|
||||
|
||||
/**
|
||||
* @brief After a creature's money is taken
|
||||
*
|
||||
* @param player Contains information about the Player
|
||||
*/
|
||||
virtual void OnAfterCreatureLootMoney(Player* /*player*/) { }
|
||||
};
|
||||
|
||||
class AccountScript : public ScriptObject
|
||||
@@ -2447,6 +2471,9 @@ public: /* PlayerScript */
|
||||
void OnPlayerEnterCombat(Player* player, Unit* enemy);
|
||||
void OnPlayerLeaveCombat(Player* player);
|
||||
void OnQuestAbandon(Player* player, uint32 questId);
|
||||
bool CanSendErrorAlreadyLooted(Player* player);
|
||||
void OnAfterCreatureLoot(Player* player);
|
||||
void OnAfterCreatureLootMoney(Player* player);
|
||||
|
||||
// Anti cheat
|
||||
void AnticheatSetSkipOnePacketForASH(Player* player, bool apply);
|
||||
|
||||
@@ -1079,8 +1079,8 @@ public: // opcodes handlers
|
||||
void HandleEnterPlayerVehicle(WorldPacket& data);
|
||||
void HandleUpdateProjectilePosition(WorldPacket& recvPacket);
|
||||
|
||||
uint32 _lastAuctionListItemsMSTime;
|
||||
uint32 _lastAuctionListOwnerItemsMSTime;
|
||||
Milliseconds _lastAuctionListItemsMSTime;
|
||||
Milliseconds _lastAuctionListOwnerItemsMSTime;
|
||||
|
||||
void HandleTeleportTimeout(bool updateInSessions);
|
||||
bool HandleSocketClosed();
|
||||
|
||||
@@ -1918,6 +1918,16 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 34026: // Kill Command
|
||||
// Dungeon Set 3
|
||||
if (caster->HasAura(37483))
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
caster->CastSpell(caster, 37482, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SPELLFAMILY_PALADIN:
|
||||
|
||||
@@ -3436,6 +3436,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
|
||||
spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
|
||||
spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
|
||||
break;
|
||||
case 42463: // Seals of the Pure for Seal of Vengeance/Corruption
|
||||
case 53739:
|
||||
if (AuraEffect const* sealsOfPure = m_caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PALADIN, 25, 0))
|
||||
AddPct(totalDamagePercentMod, sealsOfPure->GetAmount());
|
||||
break;
|
||||
case 53385: // Divine Storm deals normalized damage
|
||||
normalized = true;
|
||||
break;
|
||||
|
||||
@@ -413,6 +413,7 @@ enum WorldIntConfigs
|
||||
CONFIG_LFG_KICK_PREVENTION_TIMER,
|
||||
CONFIG_CHANGE_FACTION_MAX_MONEY,
|
||||
CONFIG_WATER_BREATH_TIMER,
|
||||
CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT,
|
||||
INT_CONFIG_VALUE_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -1286,6 +1286,8 @@ void World::LoadConfigSettings(bool reload)
|
||||
|
||||
_bool_configs[CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH] = sConfigMgr->GetOption<bool>("Pet.RankMod.Health", true);
|
||||
|
||||
_int_configs[CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT] = sConfigMgr->GetOption<uint32>("AuctionHouse.SearchTimeout", 1000);
|
||||
|
||||
///- Read the "Data" directory from the config file
|
||||
std::string dataPath = sConfigMgr->GetOption<std::string>("DataDir", "./");
|
||||
if (dataPath.empty() || (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\'))
|
||||
@@ -2352,41 +2354,27 @@ void World::Update(uint32 diff)
|
||||
|
||||
sScriptMgr->OnPlayerbotUpdate(diff);
|
||||
|
||||
// pussywizard:
|
||||
// acquire mutex now, this is kind of waiting for listing thread to finish it's work (since it can't process next packet)
|
||||
// so we don't have to do it in every packet that modifies auctions
|
||||
AsyncAuctionListingMgr::SetAuctionListingAllowed(false);
|
||||
// pussywizard: handle auctions when the timer has passed
|
||||
if (_timers[WUPDATE_AUCTIONS].Passed())
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetLock());
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update expired auctions"));
|
||||
|
||||
// pussywizard: handle auctions when the timer has passed
|
||||
if (_timers[WUPDATE_AUCTIONS].Passed())
|
||||
{
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update expired auctions"));
|
||||
_timers[WUPDATE_AUCTIONS].Reset();
|
||||
|
||||
_timers[WUPDATE_AUCTIONS].Reset();
|
||||
|
||||
// pussywizard: handle expired auctions, auctions expired when realm was offline are also handled here (not during loading when many required things aren't loaded yet)
|
||||
sAuctionMgr->Update();
|
||||
}
|
||||
|
||||
AsyncAuctionListingMgr::Update(diff);
|
||||
|
||||
if (currentGameTime > _mail_expire_check_timer)
|
||||
{
|
||||
sObjectMgr->ReturnOrDeleteOldMails(true);
|
||||
_mail_expire_check_timer = currentGameTime + 6h;
|
||||
}
|
||||
|
||||
{
|
||||
/// <li> Handle session updates when the timer has passed
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions"));
|
||||
UpdateSessions(diff);
|
||||
}
|
||||
// pussywizard: handle expired auctions, auctions expired when realm was offline are also handled here (not during loading when many required things aren't loaded yet)
|
||||
sAuctionMgr->Update();
|
||||
}
|
||||
|
||||
// end of section with mutex
|
||||
AsyncAuctionListingMgr::SetAuctionListingAllowed(true);
|
||||
AsyncAuctionListingMgr::Update(Milliseconds(diff));
|
||||
|
||||
if (currentGameTime > _mail_expire_check_timer)
|
||||
{
|
||||
sObjectMgr->ReturnOrDeleteOldMails(true);
|
||||
_mail_expire_check_timer = currentGameTime + 6h;
|
||||
}
|
||||
|
||||
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions"));
|
||||
UpdateSessions(diff);
|
||||
|
||||
/// <li> Handle weather updates when the timer has passed
|
||||
if (_timers[WUPDATE_WEATHERS].Passed())
|
||||
|
||||
Reference in New Issue
Block a user