EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Quests::Q&A (https://www.eqemulator.org/forums/forumdisplay.php?f=599)
-   -   Porters (https://www.eqemulator.org/forums/showthread.php?t=39546)

markusdabrave 04-03-2015 03:42 PM

Porters
 
If I wanted to create a NPCs at the various Wizard Spires and Druid Rings that would teleport you to other spires/rings, what's the best way to go about it? I was thinking at first about a buff bot casting the teleport spell on you, but then I realized those are in-group spells so that probably wouldn't work. Plus I don't want the teleporter disappearing (though that would be kind of funny.. .which wizard spire/druid ring is the porter at :)). At any rate, I'm thinking more in terms of a translocator-type scenario. Or maybe something akin to the gnome in the guild hall that sends you off based on an item he gives you. From a design standpoint, what's the simplest way of doing this? Or is it even possible.

dagulus2 04-03-2015 03:53 PM

You might want to take a look at the Wayfairer Magus scripts to see if they could be adapted to what you want.

markusdabrave 04-03-2015 07:23 PM

Will do, thanks

Edit: Ok, I know this has got to be here. I was looking at buffbot spells and got my porters to work. The only problem is everything is instacast. I've done some searching for pause and wait in the scripts but can't seem to find anything of relevance to what I'm doing. Here's what I've got so far:

Code:

sub EVENT_SAY {
    if ($text=~/Hail/i) {
        plugin::Whisper("Hail! Where would you like to go? [Surefall] Glade?");
    }
    if ($text=~/Surefall/i) {
        quest::say("Camo for safety...");
        quest::selfcast(34);
        quest::say("Off to Surefall Glade!");
        quest::selfcast(2021);
    }
}

I tried $npc->CastSpell(2021,$userid); but that only resulted in my NPC teleporting away (which was quite humorous... and may actually be something I implement later.. but I digress). My assumption here is that 2021 (Ring of Surefall) is a self-only spell, and 2020 (Circle of Surefall) is a group spell that the druid has to be a member of, which is why they're not working. Self-cast works but it's a little hoaky seeing a warrior cast a spell to teleport. So I guess there are a couple of questions:

1. Can I suppress the player character from doing the cast animation on a SelfCast?
2. What's the keyword for inserting a pause/wait between spells being cast? I saw pause(timer) but that didn't work so I suspect it only has to do with movement.
3. Is it even possible for an NPC to cast a group spell on a non-group member (similar to target group buff only this would really be target group circle :))

Asylum 04-12-2015 01:32 PM

Avoid using "spells" altogether and simply use the following to move the player that triggers the event:

quest::movepc(zone_id, x, y, z, heading);

If you want a delay, set it to trigger a timer for x seconds, then under EVENT_TIMER paste the above (also may want to stop the timer...).

If you are transporting into an instance:

quest::MovePCInstance(zone_id, instance_id, x, y, z);

If you have a flare for the dramatic, have the npc cast a spell during the delay to make it appear that's the graphic he or she is casting.

See the second post in this thread http://www.eqemulator.org/forums/showthread.php?t=38773 for using proximity say to create and port player(s)/group to an instance. It can be used with quest::movepc(zone_id, x, y, z, heading); as well for static zones or to a different area of the same zone/instance. Be sure you activate the proximitysay command in EVENT_SPAWN or it will not use it.

markusdabrave 04-15-2015 04:54 PM

Thanks for the advice, I'll give the movepc thing a try. You're exactly right on what my goal is. I'd like to make the porter cast 2-3 seconds of spell effects, then the player get teleported out. The problem I've run into is that everything happens sequentially. Timer -> Spell Effect -> Port rather than Timer & Spell Effect -> Port.

Right now this is what my code is. Functionally, it works fine. I'd like like it feel a little less botty and more pc-ish :)

Also, if there's a way to make this script not use so many if statements, I'm all ears. I'm new to perl but not programming so I suspect there has to be a way to combine those if statements into fewer lines of code.

Code:

sub EVENT_SAY {
        if ($text=~/Hail/i) {
        plugin::Whisper("Hail! Where would you like to go? [Butcherblock] Mountains, The [Feerrott], North [Karana], [Lavastorm] Mountains, [Misty] Thicket, [South Ro], [Steamfont] Mountains, West [Commonlands] or [Toxxulia] Forest?");
        }
#        if ($text=~/Surefall/i) {
#        quest::selfcast(34);
#        quest::say("Off to Surefall Glade!");
#        quest::selfcast(2021);
#        }
        if ($text=~/Commonlands/i) {
        quest::say("Off to West Commonlands!");
        quest::selfcast(34);
        quest::selfcast(531);
        }
        if ($text=~/Butcherblock/i) {
        quest::say("Off to Butcherblock Mountains!");
        quest::selfcast(34);
        quest::selfcast(532);
        }
        if ($text=~/Feerrott/i) {
        quest::say("Off to The Feerrott!");
        quest::selfcast(34);
        quest::selfcast(536);
        }
        if ($text=~/Karana/i) {
        quest::say("Off to North Karana!");
        quest::selfcast(34);
        quest::selfcast(530);
        }
        if ($text=~/Lavastorm/i) {
        quest::say("Off to Lavastorm Mountains!");
        quest::selfcast(34);       
        quest::selfcast(534);
        }
        if ($text=~/Misty/i) {
        quest::say("Off to Misty Thicket!");
        quest::selfcast(34);
        quest::selfcast(538);
        }
        if ($text=~/South Ro/i) {
        quest::say("Off to South Ro!");
        quest::selfcast(34);
        quest::selfcast(535);
        }
        if ($text=~/Steamfont/i) {
        quest::say("Off to Steafont Mountains!");       
        quest::selfcast(34);
        quest::selfcast(537);
        }
        if ($text=~/Toxxulia/i) {
        quest::say("Off you Toxxulia Forest!");
        quest::selfcast(34);
        quest::selfcast(533);
        }
}


ghanja 04-15-2015 05:08 PM

There is, but keeping with basics. It's better to use elsif's in place of all the other if's you have after the initial if.

Code:

sub EVENT_SAY {
        if ($text=~/Hail/i) {
                plugin::Whisper("Hail! Where would you like to go? [Butcherblock] Mountains, The [Feerrott], North [Karana], [Lavastorm] Mountains, [Misty] Thicket, [South Ro], [Steamfont] Mountains, West [Commonlands] or [Toxxulia] Forest?");
        }
#        elsif ($text=~/Surefall/i) {
#                quest::selfcast(34);
#                quest::say("Off to Surefall Glade!");
#                quest::selfcast(2021);
#        }
        elsif ($text=~/Commonlands/i) {
                quest::say("Off to West Commonlands!");
                quest::selfcast(34);
                quest::selfcast(531);
        }
        elsif ($text=~/Butcherblock/i) {
                quest::say("Off to Butcherblock Mountains!");
                quest::selfcast(34);
                quest::selfcast(532);
        }
        elsif ($text=~/Feerrott/i) {
                quest::say("Off to The Feerrott!");
                quest::selfcast(34);
                quest::selfcast(536);
        }
        elsif ($text=~/Karana/i) {
                quest::say("Off to North Karana!");
                quest::selfcast(34);
                quest::selfcast(530);
        }
        elsif ($text=~/Lavastorm/i) {
                quest::say("Off to Lavastorm Mountains!");
                quest::selfcast(34);       
                quest::selfcast(534);
        }
        elsif ($text=~/Misty/i) {
                quest::say("Off to Misty Thicket!");
                quest::selfcast(34);
                quest::selfcast(538);
        }
        elsif ($text=~/South Ro/i) {
                quest::say("Off to South Ro!");
                quest::selfcast(34);
                quest::selfcast(535);
        }
        elsif ($text=~/Steamfont/i) {
                quest::say("Off to Steafont Mountains!");       
                quest::selfcast(34);
                quest::selfcast(537);
        }
        elsif ($text=~/Toxxulia/i) {
                quest::say("Off you Toxxulia Forest!");
                quest::selfcast(34);
                quest::selfcast(533);
        }
}

I've never used it on a port spell, but, if you're wanting effects and such, then perhaps:
Code:

$npc->SpellFinished(####, $client)
Or a timer with animation and aura that will do a movepc after a few seconds.

markusdabrave 04-15-2015 06:20 PM

I made the recommended if->elsif changes. As a test, I added the SpellFinished function to the commonlands port. It's still insta-casting when I say Commonlands though. Code I'm using is below. I'm wondering if this is going to work since the NPC isn't casting the port spell, the player is self-casting it.


Code:

elsif ($text=~/Commonlands/i) {
                quest::say("Off to West Commonlands!");
                quest::selfcast(34);
              $npc->SpellFinished(531, $client)
                quest::selfcast(531);
        }


ghanja 04-15-2015 07:09 PM

Code:

$npc->SpellEffect(<effect>, <duration>);
Then a quest::movepc -- I like the control of it, and this assumes you may wish to send them somewhere other than the safe point.

markusdabrave 04-15-2015 11:44 PM

Ok so the spell effect is working and the move command works great. I definitely like this better. However, timers still aren't cooperating. I'm so close I can taste it:

Code:

sub EVENT_SPAWN {
        quest::settimer("portercast",10);
}

sub EVENT_TIMER {
        if($timer eq "portercast") {
        quest::say("Casting...");
        quest::stoptimer("portercast");
        quest::say("Moved");
        }
}

sub EVENT_SAY {
        if ($text=~/Hail/i) {
        plugin::Whisper("Hail! Where would you like to go? [Butcherblock] Mountains, The [Feerrott], North [Karana], [Lavastorm] Mountains, [Misty] Thicket, [South Ro], [Steamfont] Mountains, West [Commonlands] or [Toxxulia] Forest?");
        }
        elsif ($text=~/Commonlands/i) {
        quest::say("Off to West Commonlands!");
        quest::settimer("portercast",10);
        }
#        quest::movepc(21, 1427, 479, -51, 0);
}

I think maybe this is an order thing. What happens is:
1. I /say commonlands
2. NPC says "Off to West Commonlands!"
3. NPC starts spell effect
4. 10 seconds later NPC says "Casting..." immediately followed by "Moved".

Seems like I'm getting hung up in the EVENT_TIMERS sub. The "Casting..." and "Moved" are something I just added in for testing instead of loading constantly. "Moved" is where my move line would be. So if I move it down past where the portercast timer is called in EVENT_SAY, it triggers simultaneously as the timer and I end up with "Moved" before "Casting..."

I could put the move command in the EVENT_TIMERS sub, but then I would have to mess with multiple timers, which seems like it would be defeating the purpose of using the timer. When you call a timer like that, where does the actual timer pause take place? Within EVENT_TIMERS would seem to be the obvious answer. Is there not a way to make the EVENT_SAY steps pause until the timer call is complete?

Edit:
I tried adding the move command to the EVENT_TIMERS sub but it doesn't function at all there.

ghanja 04-16-2015 12:52 PM

Code:

quest::pause(xxx);
Think of timers as being independent/isolated, any code after a quest::settimer continues to run immediately. Timers can give the illusion of pause depending on what they do. When I mentioned timers, that was going a different route, not combining SpellEffect/SpellFinished and timers, sorry, I wasn't clear.

markusdabrave 04-16-2015 05:01 PM

I'll give that a try tonight. If it's that simple, I'm going to feel really dumb :)

markusdabrave 04-16-2015 09:29 PM

Negatory on the wait command. Doing some further research, that appears to be intended for pauses in waypoints. Man I got nothing now. Here's what the current code looks like. I've simplified it to its basics to troubleshoot:

Code:

sub EVENT_SAY {
        if ($text=~/Hail/i) {
        plugin::Whisper("Hail! Where would you like to go? [Butcherblock] Mountains, The [Feerrott], North [Karana], [Lavastorm] Mountains, [Misty] Thicket, [South Ro], [Steamfont] Mountains, West [Commonlands] or [Toxxulia] Forest?");
        }
       
        elsif ($text=~/Commonlands/i) {
        quest::say("Off to West Commonlands!");
        $client->SpellEffect(43,10);
        quest::settimer("castdelay",10);
#      quest::movepc(21, 1427, 479, -51, 0);
        }
}

sub EVENT_TIMER {
        if($timer eq "castdelay") {
        #quest::stoptimer("castdelay");
        quest::say("Off you go!");
        quest::stoptimer("castdelay");
        }
}

I've moved the quest::movepc command into the EVENT_TIMER if statement, but it doesn't seem to function there. If I leave it as seen above, it moves the player at the same time everything else happens. When I tried adding the quest::wait, I tried in both EVENT_TIMER and the EVENT_SAY subs but nothing.

ghanja 04-16-2015 10:17 PM

Yeah pause is for waypoints and yet I still cite them as a pause. Sorry, cannot get that through this thick head for some reason (maybe if I used scripted travel it would stick).

Instead, I should have said:

Code:

sleep(x);
And I believe I'll step away until all the commotion has ceased so I can stop talking out of my arse.

ghanja 04-16-2015 10:40 PM

Scratch that too. This is the NPC's script. Hmm.

markusdabrave 04-16-2015 10:50 PM

LOL I know, I ran into that as well. However - success at last!! Apparently, there's not a built in delay so you have to write your own. I stumbled across this thread and it's working like a champ.

Code:

sub EVENT_SAY{
        if ($text=~/Hail/i) {
                plugin::Whisper("Hail! Where would you like to go? [Butcherblock] Mountains, The [Feerrott], North [Karana], [Lavastorm] Mountains, [Misty] Thicket, [South Ro], [Steamfont] Mountains, West [Commonlands] or [Toxxulia] Forest?");
        }
       
        elsif ($text=~/Commonlands/i) {
        quest::say("Off to West Commonlands!");
        $client->SpellEffect(43,10);
        castdelay(5);
        quest::selfcast(34);
        quest::movepc(21, 1427, 479, -51, 0);
        }
}
sub castdelay{
        $delayOver = (time + @_[0]);
        while (time < $delayOver){}
        1;
}

Order of events is now:
1. /say commonlands to NPC
2. Spell Effect appears on player
3. Player self-invises
4. 5 seconds later player is moved to WC druid ring

Whew. Thanks for the help. I at least learned a lot :)


All times are GMT -4. The time now is 06:51 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.