Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-04-22 21:50:43 +08:00
21 changed files with 1499 additions and 40 deletions

View File

@@ -115,7 +115,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// End LoginQueryHolder content
PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, item_guid, itemEntry, ii.owner_guid, m.id FROM mail_items mi INNER JOIN mail m ON mi.mail_id = m.id LEFT JOIN item_instance ii ON mi.item_guid = ii.guid WHERE m.receiver = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, item_guid, itemEntry, ii.owner_guid, m.id FROM mail_items mi INNER JOIN mail m ON mi.mail_id = m.id LEFT JOIN item_instance ii ON mi.item_guid = ii.guid WHERE m.receiver = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_AUCTION_ITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, itemguid, itemEntry FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_AUCTIONS, "SELECT id, houseid, itemguid, itemEntry, count, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid", CONNECTION_SYNCH);
PrepareStatement(CHAR_INS_AUCTION, "INSERT INTO auctionhouse (id, houseid, itemguid, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);

View File

@@ -634,6 +634,9 @@ void SmartAI::MovementInform(uint32 MovementType, uint32 Data)
if (MovementType == POINT_MOTION_TYPE && Data == SMART_ESCORT_LAST_OOC_POINT)
me->ClearUnitState(UNIT_STATE_EVADE);
if (MovementType == WAYPOINT_MOTION_TYPE)
GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_DATA_REACHED, nullptr, Data + 1); // Data + 1 to align smart_scripts and waypoint_data Id rows
GetScript()->ProcessEventsFor(SMART_EVENT_MOVEMENTINFORM, nullptr, MovementType, Data);
if (!HasEscortState(SMART_ESCORT_ESCORTING))
return;
@@ -1150,6 +1153,11 @@ void SmartAI::OnSpellClick(Unit* clicker, bool& /*result*/)
GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELLCLICK, clicker);
}
void SmartAI::PathEndReached(uint32 pathId)
{
GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_DATA_ENDED, nullptr, 0, me->GetWaypointPath());
}
void SmartGameObjectAI::SummonedCreatureDies(Creature* summon, Unit* /*killer*/)
{
GetScript()->ProcessEventsFor(SMART_EVENT_SUMMONED_UNIT_DIES, summon);

View File

@@ -204,6 +204,8 @@ public:
void OnSpellClick(Unit* clicker, bool& result) override;
void PathEndReached(uint32 pathId) override;
// Xinef
void SetWPPauseTimer(uint32 time) { mWPPauseTimer = time; }

View File

@@ -3057,6 +3057,63 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
break;
}
case SMART_ACTION_WAYPOINT_DATA_START:
{
if (e.action.wpData.pathId)
{
for (WorldObject* target : targets)
{
if (IsCreature(target))
{
target->ToCreature()->LoadPath(e.action.wpData.pathId);
target->ToCreature()->GetMotionMaster()->MovePath(e.action.wpData.pathId, e.action.wpData.repeat);
}
}
}
break;
}
case SMART_ACTION_WAYPOINT_DATA_RANDOM:
{
if (e.action.wpDataRandom.pathId1 && e.action.wpDataRandom.pathId2)
{
for (WorldObject* target : targets)
{
if (IsCreature(target))
{
uint32 path = urand(e.action.wpDataRandom.pathId1, e.action.wpDataRandom.pathId2);
target->ToCreature()->LoadPath(path);
target->ToCreature()->GetMotionMaster()->MovePath(path, e.action.wpDataRandom.repeat);
}
}
}
break;
}
case SMART_ACTION_MOVEMENT_STOP:
{
for (WorldObject* target : targets)
if (IsUnit(target))
target->ToUnit()->StopMoving();
break;
}
case SMART_ACTION_MOVEMENT_PAUSE:
{
for (WorldObject* target : targets)
if (IsUnit(target))
target->ToUnit()->PauseMovement(e.action.move.timer);
break;
}
case SMART_ACTION_MOVEMENT_RESUME:
{
for (WorldObject* target : targets)
if (IsUnit(target))
target->ToUnit()->ResumeMovement(e.action.move.timer);
break;
}
default:
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break;
@@ -4538,6 +4595,14 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
RecalcTimer(e, 1200, 1200);
break;
}
case SMART_EVENT_WAYPOINT_DATA_REACHED:
case SMART_EVENT_WAYPOINT_DATA_ENDED:
{
if (!me || (e.event.wpData.pointId && var0 != e.event.wpData.pointId) || (e.event.wpData.pathId && me->GetWaypointPath() != e.event.wpData.pathId))
return;
ProcessAction(e, unit);
break;
}
default:
LOG_ERROR("sql.sql", "SmartScript::ProcessEvent: Unhandled Event type {}", e.GetEventType());
break;

View File

@@ -574,6 +574,8 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_AREA_CASTING: return sizeof(SmartEvent::minMaxRepeat);
case SMART_EVENT_AREA_RANGE: return sizeof(SmartEvent::minMaxRepeat);
case SMART_EVENT_SUMMONED_UNIT_EVADE: return sizeof(SmartEvent::summoned);
case SMART_EVENT_WAYPOINT_DATA_REACHED: return sizeof(SmartEvent::wpData);
case SMART_EVENT_WAYPOINT_DATA_ENDED: return sizeof(SmartEvent::wpData);
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());
@@ -769,6 +771,11 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
case SMART_ACTION_PLAY_SPELL_VISUAL: return sizeof(SmartAction::spellVisual);
case SMART_ACTION_FOLLOW_GROUP: return sizeof(SmartAction::followGroup);
case SMART_ACTION_SET_ORIENTATION_TARGET: return sizeof(SmartAction::orientationTarget);
case SMART_ACTION_WAYPOINT_DATA_START: return sizeof(SmartAction::wpData);
case SMART_ACTION_WAYPOINT_DATA_RANDOM: return sizeof(SmartAction::wpDataRandom);
case SMART_ACTION_MOVEMENT_STOP: return NO_PARAMS;
case SMART_ACTION_MOVEMENT_PAUSE: return sizeof(SmartAction::move);
case SMART_ACTION_MOVEMENT_RESUME: return sizeof(SmartAction::move);
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());
@@ -1321,6 +1328,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_JUST_CREATED:
case SMART_EVENT_FOLLOW_COMPLETED:
case SMART_EVENT_ON_SPELLCLICK:
case SMART_EVENT_WAYPOINT_DATA_REACHED:
case SMART_EVENT_WAYPOINT_DATA_ENDED:
break;
default:
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled event_type({}), Entry {} SourceType {} Event {} Action {}, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
@@ -1945,6 +1954,11 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_PLAY_SPELL_VISUAL:
case SMART_ACTION_FOLLOW_GROUP:
case SMART_ACTION_SET_ORIENTATION_TARGET:
case SMART_ACTION_WAYPOINT_DATA_START:
case SMART_ACTION_WAYPOINT_DATA_RANDOM:
case SMART_ACTION_MOVEMENT_STOP:
case SMART_ACTION_MOVEMENT_PAUSE:
case SMART_ACTION_MOVEMENT_RESUME:
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);

View File

@@ -214,8 +214,10 @@ enum SMART_EVENT
SMART_EVENT_AREA_CASTING = 105, // min, max, repeatMin, repeatMax, rangeMin, rangeMax
SMART_EVENT_AREA_RANGE = 106, // min, max, repeatMin, repeatMax, rangeMin, rangeMax
SMART_EVENT_SUMMONED_UNIT_EVADE = 107, // CreatureId(0 all), CooldownMin, CooldownMax
SMART_EVENT_WAYPOINT_DATA_REACHED = 108, // PointId (0: any), pathId (0: any)
SMART_EVENT_WAYPOINT_DATA_ENDED = 109, // PointId (0: any), pathId (0: any)
SMART_EVENT_AC_END = 108
SMART_EVENT_AC_END = 110
};
struct SmartEvent
@@ -507,6 +509,12 @@ struct SmartEvent
uint32 timer;
} nearUnitNegation;
struct
{
uint32 pointId;
uint32 pathId;
} wpData;
struct
{
uint32 param1;
@@ -714,8 +722,13 @@ enum SMART_ACTION
SMART_ACTION_PLAY_SPELL_VISUAL = 229, // visualId, visualIdImpact
SMART_ACTION_FOLLOW_GROUP = 230, // followState, followType, dist
SMART_ACTION_SET_ORIENTATION_TARGET = 231, // type, target_type, target_param1, target_param2, target_param3, target_param4
SMART_ACTION_WAYPOINT_DATA_START = 232, // pathId, repeat
SMART_ACTION_WAYPOINT_DATA_RANDOM = 233, // pathId1, pathId2, repeat
SMART_ACTION_MOVEMENT_STOP = 234, //
SMART_ACTION_MOVEMENT_PAUSE = 235, // timer
SMART_ACTION_MOVEMENT_RESUME = 236, // timerOverride
SMART_ACTION_AC_END = 232, // placeholder
SMART_ACTION_AC_END = 237, // placeholder
};
enum class SmartActionSummonCreatureFlags
@@ -1434,6 +1447,24 @@ struct SmartAction
uint32 targetParam3;
uint32 targetParam4;
} orientationTarget;
struct
{
uint32 pathId;
SAIBool repeat;
} wpData;
struct
{
uint32 pathId1;
uint32 pathId2;
SAIBool repeat;
} wpDataRandom;
struct
{
uint32 timer;
} move;
//! Note for any new future actions
//! All parameters must have type uint32
@@ -1844,6 +1875,8 @@ const uint32 SmartAIEventMask[SMART_EVENT_AC_END][2] =
{SMART_EVENT_AREA_CASTING, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_AREA_RANGE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_SUMMONED_UNIT_EVADE, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_WAYPOINT_DATA_REACHED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_WAYPOINT_DATA_ENDED, SMART_SCRIPT_TYPE_MASK_CREATURE },
};
enum SmartEventFlags

View File

@@ -635,13 +635,6 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
accountId = playerData->AccountId;
name = playerData->Name;
level = playerData->Level;
// check mailbox
if (playerData->MailCount)
{
SendCharDelete(CHAR_DELETE_FAILED);
return;
}
}
// prevent deleting other players' characters using cheating tools

View File

@@ -19,6 +19,8 @@
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "hyjal.h"
enum Spells
@@ -327,6 +329,26 @@ public:
};
// 31538 - Cannibalize (Heal)
class spell_cannibalize_heal : public SpellScript
{
PrepareSpellScript(spell_cannibalize_heal);
void HandleHeal(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
{
uint32 heal = caster->CountPctFromMaxHealth(7);
SetHitHeal(heal);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_cannibalize_heal::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL);
}
};
struct npc_hyjal_ground_trash : public ScriptedAI
{
npc_hyjal_ground_trash(Creature* creature) : ScriptedAI(creature)
@@ -704,4 +726,5 @@ void AddSC_hyjal()
RegisterHyjalAI(npc_hyjal_ground_trash);
RegisterHyjalAI(npc_hyjal_gargoyle);
RegisterHyjalAI(npc_hyjal_frost_wyrm);
RegisterSpellScript(spell_cannibalize_heal);
}

View File

@@ -38,6 +38,7 @@ enum Spells
SPELL_PSYCHIC_SCREAM = 34322,
SPELL_VOID_BOLT = 39329,
SPELL_TRUE_BEAM = 33365,
SPELL_TELEPORT_START_POSITION = 33244,
};
enum Misc
@@ -55,6 +56,9 @@ enum Misc
#define CENTER_Z 17.9608f
#define CENTER_O 1.06421f
#define PORTAL_Z 17.005f
#define START_POSITION_X 432.74f
#define START_POSITION_Y -373.645f
#define START_POSITION_Z 18.0138f
struct boss_high_astromancer_solarian : public BossAI
{
@@ -146,11 +150,30 @@ struct boss_high_astromancer_solarian : public BossAI
}).Schedule(52100ms, [this](TaskContext context)
{
me->SetReactState(REACT_PASSIVE);
Talk(SAY_SUMMON);
me->RemoveAllAuras();
me->SetModelVisible(false);
scheduler.DelayAll(21s);
scheduler.Schedule(6s, [this](TaskContext)
scheduler.DelayAll(22s);
// blink to room center in this line using SPELL_TELEPORT_START_POSITION and START_POSITION_X, START_POSITION_Y, START_POSITION_Z
scheduler.Schedule(1s, [this](TaskContext)
{
for (uint8 i = 0; i < 3; ++i)
{
float o = rand_norm() * 2 * M_PI;
if (i == 0)
{
me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, CENTER_X + cos(o)*INNER_PORTAL_RADIUS, CENTER_Y + std::sin(o)*INNER_PORTAL_RADIUS, CENTER_Z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000);
}
else
{
me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, CENTER_X + cos(o)*OUTER_PORTAL_RADIUS, CENTER_Y + std::sin(o)*OUTER_PORTAL_RADIUS, PORTAL_Z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000);
}
}
}).Schedule(2s, [this](TaskContext)
{
Talk(SAY_SUMMON);
}).Schedule(3s, [this](TaskContext)
{
me->RemoveAllAuras();
me->SetModelVisible(false);
}).Schedule(7s, [this](TaskContext)
{
summons.DoForAllSummons([&](WorldObject* summon)
{
@@ -171,7 +194,7 @@ struct boss_high_astromancer_solarian : public BossAI
}
}
});
}).Schedule(20s, [this](TaskContext)
}).Schedule(23s, [this](TaskContext)
{
me->SetReactState(REACT_AGGRESSIVE);
summons.DoForAllSummons([&](WorldObject* summon)
@@ -194,20 +217,7 @@ struct boss_high_astromancer_solarian : public BossAI
}
});
});
for (uint8 i = 0; i < 3; ++i)
{
float o = rand_norm() * 2 * M_PI;
if (i == 0)
{
me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, CENTER_X + cos(o)*INNER_PORTAL_RADIUS, CENTER_Y + std::sin(o)*INNER_PORTAL_RADIUS, CENTER_Z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 26000);
}
else
{
me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, CENTER_X + cos(o)*OUTER_PORTAL_RADIUS, CENTER_Y + std::sin(o)*OUTER_PORTAL_RADIUS, PORTAL_Z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 26000);
}
}
context.Repeat(67500ms, 71200ms);
context.Repeat(87500ms, 91200ms);
});
}
@@ -280,4 +290,3 @@ void AddSC_boss_high_astromancer_solarian()
RegisterSpellScript(spell_astromancer_wrath_of_the_astromancer);
RegisterSpellScript(spell_astromancer_solarian_transform);
}

View File

@@ -472,11 +472,11 @@ struct boss_kaelthas : public BossAI
{
DoCastRandomTarget(SPELL_FLAME_STRIKE, 0, 100.0f);
}, 30250ms, 50650ms);
ScheduleTimedEvent(20000ms, [&]
ScheduleTimedEvent(71000ms, [&]
{
Talk(SAY_SUMMON_PHOENIX);
DoCastSelf(SPELL_PHOENIX);
}, 31450ms, 66550ms);
}, 61450ms, 96550ms);
ScheduleTimedEvent(5s, [&]
{
scheduler.DelayAll(30s);
@@ -735,11 +735,11 @@ struct boss_kaelthas : public BossAI
{
DoCastRandomTarget(SPELL_FLAME_STRIKE, 0, 100.0f);
}, 30250ms, 50650ms);
ScheduleTimedEvent(30000ms, [&]
ScheduleTimedEvent(50000ms, [&]
{
Talk(SAY_SUMMON_PHOENIX);
DoCastSelf(SPELL_PHOENIX);
}, 31450ms, 66550ms);
}, 35450ms, 41550ms);
//sequence
ScheduleTimedEvent(20s, 23s, [&]
{

View File

@@ -40,12 +40,15 @@ struct npc_pet_pri_lightwell : public TotemAI
void InitializeAI() override
{
if (Unit* owner = me->ToTempSummon()->GetSummonerUnit())
if (TempSummon* tempSummon = me->ToTempSummon())
{
uint32 hp = uint32(owner->GetMaxHealth() * 0.3f);
me->SetMaxHealth(hp);
me->SetHealth(hp);
me->SetLevel(owner->GetLevel());
if (Unit* owner = tempSummon->GetSummonerUnit())
{
uint32 hp = uint32(owner->GetMaxHealth() * 0.3f);
me->SetMaxHealth(hp);
me->SetHealth(hp);
me->SetLevel(owner->GetLevel());
}
}
me->CastSpell(me, SPELL_PRIEST_LIGHTWELL_CHARGES, false); // Spell for Lightwell Charges