Skip to content

c++ SCript for the Quest Zero Tolerance and spellfix spell_zuldrak_gymers_grab #31196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: 3.3.5
Choose a base branch
from

Conversation

Thor1423
Copy link

@Thor1423 Thor1423 commented Aug 5, 2025

based on this Commit #30286 (comment)

I personally think that the whole thing can be designed better with c++, so here is my c++ idea

Here's my link with the C++ code and two videos
#30286 (comment)

UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_servant_of_drakuru' WHERE `entry` = 28802;

 -- Servant of Drakuru smart ai
SET @ENTRY := 28802;
DELETE FROM `smart_scripts` WHERE `source_type` = 0 AND `entryOrGuid` = @ENTRY;

-- Servant of Drakuru Text
DELETE FROM `creature_text` WHERE `CreatureID`=@ENTRY;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(@ENTRY, 0, 0, "Darmuk must die, mon!", 12, 0, 100, 0, 0, 0, 28884, 0, 'Servant of Drakuru - Say on Charm');

This is my first PR so please forgive me if I forgot something

based on this Commit TrinityCore#30286 (comment) 

I personally think that the whole thing can be designed better with c++, so here is my c++ idea

Here's my link with the C++ code and two videos
TrinityCore#30286 (comment)
@Thor1423 Thor1423 changed the title Update zone_zuldrak.cpp c++ SCript for the Quest Zero Tolerance Aug 5, 2025
Fix Register AI Class
}

enum Events
{
Copy link
Contributor

Choose a reason for hiding this comment

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

this must be outside of class

npc_servant_of_drakuruAI(Creature* creature)
: ScriptedAI(creature), _controller(nullptr), _checkTimer(1000), _controlled(false)
{
_events.Reset();
Copy link
Contributor

Choose a reason for hiding this comment

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

we don't manipulate EventMap in ctor


void SpellHit(WorldObject* caster, SpellInfo const* spell) override
{
if (!spell)
Copy link
Contributor

Choose a reason for hiding this comment

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

SpellInfo cannot ever be null here

{
if (caster && caster->GetTypeId() == TYPEID_PLAYER)
{
Player* player = caster->ToPlayer();
Copy link
Contributor

Choose a reason for hiding this comment

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

this is redundant, cast ToPlayer and then check for nullability in that case


void UpdateAI(uint32 diff) override
{
if (_controlled)
Copy link
Contributor

Choose a reason for hiding this comment

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

this checks per ms, use an event to delay the checks by 500ms-1s

Copy link
Author

Choose a reason for hiding this comment

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

Essentially, the script does exactly what it's supposed to, and therefore there were no compilation errors in the logs or in the game.

I assumed it was solid code that I had created with the help of a friend from back then. You can see in the video that it does what it's supposed to.

But okay, I'm not a professional programmer and I'm not afraid of corrections during the learning phase. So I'm sorry my first attempt isn't good enough for you.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just because a piece of code doesn't throw errors, exceptions, or cause crashes doesn't mean it's optimized to its best. You don't need to check that particular case every tick of Update, it's okay to delay it by 500-1000ms to optimize resources; it's not a deal of not being good enough for me, it's just a suggestion you can take or leave.

Copy link
Author

Choose a reason for hiding this comment

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

Just because a piece of code doesn't throw errors, exceptions, or cause crashes doesn't mean it's optimized to its best. You don't need to check that particular case every tick of Update, it's okay to delay it by 500-1000ms to optimize resources; it's not a deal of not being good enough for me, it's just a suggestion you can take or leave.

That wasn't what I meant. I'll take it to heart and try to optimize it. As I said, I'm still learning and don't know everything yet, and this is my first attempt at a PR. When I get home, I'll try to implement it, so there's a one-time delay. You're right that once the action is completed, no further updates are necessary.

Copy link
Author

@Thor1423 Thor1423 Aug 6, 2025

Choose a reason for hiding this comment

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

@Nyr97

I have now revised it and would like to submit it as is.

#include "ScriptMgr.h"
#include "Creature.h"
#include "SpellInfo.h"
#include "Unit.h"
#include "Player.h"
#include "ScriptedCreature.h"

enum
{
    SPELL_TRIGGER_ID = 52390,
    NPC_ENTRY_CONTROLLED = 28805,
    QUEST_ID = 12686,
    SPELL_CAST = 50361,

    EVENT_CAST_SPELL = 1,
    EVENT_CONTROL_CHECK = 2,
};

class npc_servant_of_drakuru : public CreatureScript
{
public:
    npc_servant_of_drakuru() : CreatureScript("npc_servant_of_drakuru") {}

    struct npc_servant_of_drakuruAI : public ScriptedAI
    {
        npc_servant_of_drakuruAI(Creature* creature): ScriptedAI(creature), _controller(nullptr), _controlled(false) { }

        void JustEngagedWith(Unit* /*who*/) override
        {
            _events.Reset();
            _events.ScheduleEvent(EVENT_CAST_SPELL, 4s);
            _events.ScheduleEvent(EVENT_CONTROL_CHECK, 1s);
        }

        void SpellHit(WorldObject* caster, SpellInfo const* spell) override
        {
            if (spell->Id == SPELL_TRIGGER_ID)
            {
                if (Player* player = caster->ToPlayer())
                {
                    if (player->GetQuestStatus(QUEST_ID) == QUEST_STATUS_INCOMPLETE)
                    {
                        _controller = player;
                        Talk(0);
                        me->UpdateEntry(NPC_ENTRY_CONTROLLED);
                        me->SetHealth(me->GetMaxHealth());
                        _controlled = true;
                    }
                }
            }
        }

        void UpdateAI(uint32 diff) override
        {
            _events.Update(diff);

            while (uint32 eventId = _events.ExecuteEvent())
            {
                switch (eventId)
                {
                case EVENT_CAST_SPELL:
                    if (!_controlled)
                    {
                        if (Unit* target = me->GetVictim())
                            me->CastSpell(target, SPELL_CAST, true);
                    }
                    _events.ScheduleEvent(EVENT_CAST_SPELL, 12s, 14s);
                    break;

                case EVENT_CONTROL_CHECK:
                    if (_controlled)
                    {
                        if (me->GetCharmerOrOwner() != _controller)
                        {
                            if (_controller && _controller->GetQuestStatus(QUEST_ID) == QUEST_STATUS_INCOMPLETE)
                                me->DespawnOrUnsummon(1s, 3s);

                            _controlled = false;
                            _controller = nullptr;
                            _events.Reset();
                            return;
                        }
                    }
                    _events.ScheduleEvent(EVENT_CONTROL_CHECK, 1s);
                    break;
                }
            }

            if (!_controlled)
                ScriptedAI::UpdateAI(diff);
        }

    private:
        EventMap _events;
        Player* _controller;
        bool _controlled;
    };

    CreatureAI* GetAI(Creature* creature) const override
    {
        return new npc_servant_of_drakuruAI(creature);
    }
};

void AddSC_npc_servant_of_drakuru()
{
    new npc_servant_of_drakuru();
}

Code optimization and I hope it's ok this time ^^
@CraftedRO
Copy link
Contributor

you may want to put sql code in a file inside 3.3.5 update path too.

@Thor1423
Copy link
Author

Thor1423 commented Aug 6, 2025

you may want to put sql code in a file inside 3.3.5 update path too.

Do I have to send it separately as a PR?

@CraftedRO
Copy link
Contributor

separate file, in same PR, you can temporary name it 2025_99_99_99_world.sql

@Thor1423
Copy link
Author

Thor1423 commented Aug 6, 2025

separate file, in same PR, you can temporary name it 2025_99_99_99_world.sql

Okay, I'll give it a try ^^
Have you tested the script?

SQL for the PR Quest Zero Tolerance: TrinityCore#31196
@Thor1423
Copy link
Author

Thor1423 commented Aug 6, 2025

ok i have added the SQL File

Missing Healing Effect after grabbed the Storm Cloud with this fix  now works
Fix Spellscript spell_zuldrak_gymers_grab
@Thor1423 Thor1423 changed the title c++ SCript for the Quest Zero Tolerance c++ SCript for the Quest Zero Tolerance and spellfix spell_zuldrak_gymers_grab Aug 6, 2025
Comment on lines +1167 to +1168
if (GetHitCreature()->GetEntry() == NPC_STORM_CLOUD) // Storm Cloud
GetHitCreature()->CastSpell(GetCaster(), SPELL_HEALING_WINDS, true); // Healing Winds
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (GetHitCreature()->GetEntry() == NPC_STORM_CLOUD) // Storm Cloud
GetHitCreature()->CastSpell(GetCaster(), SPELL_HEALING_WINDS, true); // Healing Winds
if (GetHitCreature()->GetEntry() == NPC_STORM_CLOUD) // Storm Cloud
GetHitCreature()->CastSpell(GetCaster(), SPELL_HEALING_WINDS, true); // Healing Winds

Isnt here missing space ?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah it is

@Thor1423
Copy link
Author

Thor1423 commented Aug 7, 2025

Apparently, reading the comments here, they don't want my fixes.

It was worth a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants