PDA

View Full Version : server first announcements thru quest system


nightsta69
09-19-2009, 08:04 PM
i'm trying to set up so that when a player hits max level on your server, and they are the first to do so, it does a server wide announcement of it.

heres what i've got so far. i have it placed in quests/templates/player.pl, but I can't get it to work for some reason. can some one take a look at it, and tell me whats wrong pls?

sub EVENT_LEVEL_UP {
my $maxlvl = 50
if(!defined($qglobals{warmaxlvl}) && $ulevel == $maxlvl && $class eq 'Warrior') {
quest::setglobal("warmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel warrior!");
}

if(!defined($qglobals{clrmaxlvl}) && $ulevel == $maxlvl && $class eq 'Cleric') {
quest::setglobal("clrmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel cleric!");
}

if(!defined($qglobals{palmaxlvl}) && $ulevel == $maxlvl && $class eq 'Paladin') {
quest::setglobal("palmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel paladin!");
}

if(!defined($qglobals{rngmaxlvl}) && $ulevel == $maxlvl && $class eq 'Ranger') {
quest::setglobal("rngmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel ranger!");
}

if(!defined($qglobals{skmaxlvl}) && $ulevel == $maxlvl && $class eq 'ShadowKnight') {
quest::setglobal("skmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel shadow knight!");
}

if(!defined($qglobals{drumaxlvl}) && $ulevel == $maxlvl && $class eq 'Druid') {
quest::setglobal("drumaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel druid!");
}

if(!defined($qglobals{mkmaxlvl}) && $ulevel == $maxlvl && $class eq 'Monk') {
quest::setglobal("mkmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel monk!");
}

if(!defined($qglobals{brdmaxlvl}) && $ulevel == $maxlvl && $class eq 'Bard') {
quest::setglobal("brdmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel bard!");
}

if(!defined($qglobals{rogmaxlvl}) && $ulevel == $maxlvl && $class eq 'Rogue') {
quest::setglobal("rogmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel rogue!");
}

if(!defined($qglobals{shmmaxlvl}) && $ulevel == $maxlvl && $class eq 'Shaman') {
quest::setglobal("shmmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel shaman!");
}

if(!defined($qglobals{necmaxlvl}) && $ulevel == $maxlvl && $class 'Necromancer') {
quest::setglobal("necmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel necromancer!");
}

if(!defined($qglobals{wizmaxlvl}) && $ulevel == $maxlvl && $class eq 'Wizard') {
quest::setglobal("wizmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel wizard!");
}

if(!defined($qglobals{magmaxlvl}) && $ulevel == $maxlvl && $class eq 'Magician') {
quest::setglobal("magmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel magician!");
}

if(!defined($qglobals{encmaxlvl}) && $ulevel == $maxlvl && $class eq 'Enchanter') {
quest::setglobal("encmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel enchanter!");
}

if(!defined($qglobals{bstmaxlvl}) && $ulevel == $maxlvl && $class eq 'Beastlord') {
quest::setglobal("bstmaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel beastlord!");
}

if(!defined($qglobals{bermaxlvl}) && $ulevel == $maxlvl && $class eq 'Berserker') {
quest::setglobal("bermaxlvl",1,2,"F");
quest::shout2("$name has made the server first level $ulevel berserker!");
}

}

ChaosSlayerZ
09-19-2009, 08:32 PM
for starters, you need one more } at the very end

nightsta69
09-19-2009, 10:23 PM
just curious, sorry if this seems ignorant, but why do I need one more }? accordin to notepad++ the sub is closed, and every if statement is closed as well.

Shin Noir
09-19-2009, 10:42 PM
Instead of copy pasting the code 15 times, you could do something like this:

sub EVENT_LEVEL_UP {
my $maxlvl = 50;
my @classlist = ("Warrior", "Cleric", "Paladin", "Ranger", "ShadowKnight", "Druid", "Monk", "Bard", "Rogue", "Shaman", "Necromancer", "Wizard", "Magician", "Enchanter", "Beastlord", "Berserker");
foreach my $curclass (@classlist) {
if(!defined($qglobals{$curclass."maxlvl"}) && $ulevel == $maxlvl && $curclass eq $class) {
quest::setglobal($curclass."maxlvl",$name,2,"F");
quest::shout2("$name has made the server first level $ulevel $class!");
return;
}
}
}

I think that may work. I'm storing the player's name in the variable instead of just a boolean flag in hopes that who knows, one day $pglobal will be loadable on NPC's.

If that ever occurs, I wrote a reporter NPC too, $qglobals are a little weird scope wise, NPC's don't load no NPC ID vars (aka Player vars). I may ask the coders to add a $pglobal that when you talk to a NPC, it loads non-NPC ID globals for the zone are loaded into $pglobal{}. Would be handy for this situation, and I can think of a few others.

This code doesn't work, but I wrote it anyways if the theory of player global vars non-NPC specific ever get written in.
sub EVENT_SAY
{
if ($text=~/Hail/i) { #Initial Hail
my @classlist = ("Warrior", "Cleric", "Paladin", "Ranger", "ShadowKnight", "Druid", "Monk", "Bard", "Rogue", "Shaman", "Necromancer", "Wizard", "Magician", "Enchanter", "Beastlord", "Berserker");;
my $buffer = "";
foreach my $curclass (@classlist) {
$buffer = $buffer . $pglobals{$curclass."maxlvl"} . " [$curclass], " if (defined($qglobals{$curclass."maxlvl"}));
if (defined($qglobals{Bardmaxlvl})) { $buffer = $buffer . $pglobals{Bardmaxlvl} . " [$curclass], "; }
}
if (length($buffer) > 3) {
$buffer = substr $buffer, 0, length($buffer)-3;
quest::say("Server First Classes: " . $buffer);
}
quest::say("end");
}
}

nightsta69
09-19-2009, 10:57 PM
Instead of copy pasting the code 15 times, you could do something like this:

sub EVENT_LEVEL_UP {
my $maxlvl = 50;
my @classlist = ("Warrior", "Cleric", "Paladin", "Ranger", "ShadowKnight", "Druid", "Monk", "Bard", "Rogue", "Shaman", "Necromancer", "Wizard", "Magician", "Enchanter", "Beastlord", "Berserker");
foreach my $curclass (@classlist) {
if(!defined($qglobals{$curclass."maxlvl"}) && $ulevel == $maxlvl && $curclass eq $class) {
quest::setglobal($curclass."maxlvl",$name,2,"F");
quest::shout2("$name has made the server first level $ulevel $class!");
return;
}
}
}

I think that may work. I'm storing the player's name in the variable instead of just a boolean flag in hopes that who knows, one day $pglobal will be loadable on NPC's.

I put this in to quests/template/player.pl. restarted server, and still nothing, makes me feel like i'm not putting this in the correct spot, or that #level 50 isn't triggering the sub EVENT_LEVEL_UP. idk which, any enlightenment would be appreciated.

Shin Noir
09-19-2009, 11:42 PM
It should. There may be an issue with scripts in the zone folder conflicting with the templates folder, just for testing try to put the player.pl inside the zone you're inside, and #reloadpl

Shin Noir
09-19-2009, 11:52 PM
Some quest coder should help me out here.. I'm not very familiar with it. :/ but!
LoadPlayerScript() function in embparser.cpp
it does this whole.. string filename= "quests/";
filename += zone;
filename += "/player.pl";
string packagename = "player";
packagename += "_";
packagename += zone; build of the quests\zone\player.pl directory.. tries to eval it
try {
perl->eval_file(packagename.c_str(), filename.c_str());
}
then if it doesn't load, if(!isloaded(packagename.c_str()))
{
filename = "quests/";
filename += QUEST_TEMPLATES_DIRECTORY;
filename += "/player.pl";
try templates. So if I'm not corrected, if a /<zone>/player.pl exists, it stops the parser from loading /templates/player.pl?

nightsta69
09-19-2009, 11:56 PM
did as suggested, tried it with the guild lobby, cut/paste the player.pl and #reloadpl, and worked. cut/paste back into templates folder, #reloadpl, doesn't work. now what I don't understand is there isn't anything in the guild lobby folder, cept the guildhall instance creation script, so i'm not seeing what would be conflicting with the EVENT_LEVEL_UP. btw is there a way to broadcast, instead of having "$name shouts, blah blah blah". was looking more for a system msg world wide, then having the player shout it world wide.

Shin Noir
09-20-2009, 12:30 AM
Try $client->Message(13, "Message here");

Shin Noir
09-20-2009, 12:37 AM
I really hate that 5 minute edit limit. So new post!

I'm working on a quest cheat sheet wiki. Not newb friendly, but a good quick reference is my objective.
This link (http://www.eqemulator.net/wiki/wikka.php?wakka=QuestCheatSheet#clientfunctions) should go to the $client->function() section, the message one and show the different color types noted in source.

nightsta69
09-20-2009, 12:55 AM
does $client->Message() broadcast worldwide, or just to the client that triggered the event?

trevius
09-20-2009, 01:05 AM
Yes, it will try to load the player.pl from the zone folder and if not there, it will load it from templates if one exists there. It would be nice if both could load and run simultaneously so you could have global stuff for player.pl as well as zone specific stuff.

I believe that for any scripts located in the templates folder, the server has to be restarted for them to take effect. Not 100% sure on that, but I think that was the conclusion I came to last time I tried playing around with it.

Also, some notes on your compilation of quest wiki pages:

EVENT_ENTER and EVENT_EXIT are both related to proximities, so they don't work from the player.pl. They are triggered when the client enters or exists a proximity around an NPC.

EVENT_SCALE_CALC is for item quest files, specifically for items with something set in the charmfile field. This event is for setting how much you want an item's stats to scale based on a percentage. Here is an example of a custom quest I made for a custom charm I have on my server:

/quests/items/CHRMTitanium.pl
sub EVENT_SCALE_CALC
{
if (defined($qglobals{titanium_relic})) {
$questitem->SetScale($qglobals{titanium_relic}/10);
}
else {
$questitem->SetScale(0);
}
}

Note that the quest is stored in a folder name "items" instead of a zone name. Also, note that CHRMTitanium from the file name is what needs to be placed in the charmfile field for the item.

Shin Noir
09-20-2009, 01:07 AM
Thanks trevius. and @ nightsta, hmm, that's a good question. Pretty sure it's possible, but can't think of a script I can pull up to find the function.

nightsta69
09-20-2009, 01:14 AM
Yes, it will try to load the player.pl from the zone folder and if not there, it will load it from templates if one exists there. It would be nice if both could load and run simultaneously so you could have global stuff for player.pl as well as zone specific stuff.

so basically what your saying is, for this to work, I have to go through every zone and place my level up script in each player.pl? that'll completely defeat the purpose of what i'm tryin to do. i'm tryin to make something similar to the achievement styles of wow. including leveling, mob slaying, and several other things, which requires the use of quest globals and things such as this. if I have to put my scripts into each and every zone player.pl, that'll be WAY to much work. is there any way of changing the source to read from both? or what is stopping it from using both scripts?

Shin Noir
09-20-2009, 01:27 AM
To use the scale event you utilize "quests/items/" folder? Interesting. Wonder how I'll categorize that.
Sorry for derailing topic nightsta. I'm unsure at your answer, we'll see!

trevius
09-20-2009, 01:54 AM
so basically what your saying is, for this to work, I have to go through every zone and place my level up script in each player.pl? that'll completely defeat the purpose of what i'm tryin to do. i'm tryin to make something similar to the achievement styles of wow. including leveling, mob slaying, and several other things, which requires the use of quest globals and things such as this. if I have to put my scripts into each and every zone player.pl, that'll be WAY to much work. is there any way of changing the source to read from both? or what is stopping it from using both scripts?

No, as long as there isn't already a file named player.pl in your zone folders, they will use the one put in the templates folder. But, again, I think you may need to restart the server for changes to the quest files in the template folder to take effect. You might want to do a search in your quest folder for any files named player.pl to see if there are any in certain zones you might want to use your system in. If so, you either need to remove them, or add your script pieces to the existing files there.

Shin Noir
09-20-2009, 02:11 AM
Couldn't you also take the templates/player.pl file and add conditions in each event on the player's location, and if their location match up paste in the /zone/player.pl code?

:D

nightsta69
09-20-2009, 07:07 AM
Some quest coder should help me out here.. I'm not very familiar with it. :/ but!
LoadPlayerScript() function in embparser.cpp
it does this whole.. string filename= "quests/";
filename += zone;
filename += "/player.pl";
string packagename = "player";
packagename += "_";
packagename += zone; build of the quests\zone\player.pl directory.. tries to eval it
try {
perl->eval_file(packagename.c_str(), filename.c_str());
}
then if it doesn't load, if(!isloaded(packagename.c_str()))
{
filename = "quests/";
filename += QUEST_TEMPLATES_DIRECTORY;
filename += "/player.pl";
try templates. So if I'm not corrected, if a /<zone>/player.pl exists, it stops the parser from loading /templates/player.pl?

curiousity question, if I were to just take this code, and make it so it loads both player.pl, what would be wrong with that?

nightsta69
09-21-2009, 03:16 AM
anyone have a solution for this that doesn't involve copying and pasting into the 20 somethin odd player.pl's in the quest folder? and i'm still wondering what would happen if the source was changed to allow to load both, the player.pl's that are in the zone folders, as well as the templates one.

Shin Noir
09-21-2009, 07:31 AM
I would think modifying the source to incorporate this is going to be more involved than it'd take for ya to just go into..
acrylia
airplane
akanon
bothunder
cabeast
cabwest
charasis
dreadlands
erudnext
erudnint
felwithea
felwitheb
freporte
freportn
gfaydark
greatdivide
grobb
halas
hatesfury
kaladima
kaladimb
neriakb
neriakc
nexus
northkarana
oggok
paineel
poair
poinnovation
pojustice
potimea
potimeb
powater
qcat
qey2hh1
qeynos
qeynos2
qrg
rathemtn
rivervale
sharvahl
skyfire
solrotower
templates
thurgadinb
tox
tutorialb
unrest
veeshan

and write conditions checking if the player is in the zone for each event, though it's going to take a while.. I dunno. That is a lot of files, heh.

Technically could edit your source to do this non-quest style, but, that's kind of complicated too. As is you're hitting a block with that limitation of player.pl not being ran on templates\ and each zone.. Don't really have an easy solution. It's going to probably be work no matter what.

nightsta69
09-21-2009, 08:30 AM
ok I know that this might seem kinda stupid. but I took this code

if(!isloaded(packagename.c_str()))
{
filename = "quests/";
filename += QUEST_TEMPLATES_DIRECTORY;
filename += "/player.pl";

and just added this one line

if(!isloaded(packagename.c_str()) || isloaded(packagename.c_str()))
{
filename = "quests/";
filename += QUEST_TEMPLATES_DIRECTORY;
filename += "/player.pl";

and compiled and now it reads from both files, and it does what I want it to do now lol. I know thats probably a hack and a half, but it works. i've done some testing with it, and have yet to see anything wrong with it. /shrug. :D

joligario
09-21-2009, 08:54 AM
To test, have both player.pl files have an enter zone event. Have the templates file do some emote "A" and the zone file do some emote "B" and see if both run. That's the only conflict I could think of.. both files having the same event.

nightsta69
09-21-2009, 09:07 AM
k tried using both sub EVENT_LEVEL_UP and it does the level up from the templates, but NOT from the zone file. so i'm assuming you can't have 2 of the same events, or the one from templates will override the other from the zone. but other then that, I didn't find any other issues.

Shin Noir
09-21-2009, 09:24 AM
Also your code above will always return true.
if(!isloaded(packagename.c_str()) || isloaded(packagename.c_str()))

It's like putting if(1), since you're covering the two possible returns of isloaded(), it can either return 1 (which is on the second half) or 0 (which is on the left half).

But yeah. If you do what you just did, you essentially screw all zone-based player.pl files if it's only working off templates.

I may have to peek and see if I can solve the event handling to execute the two different player files. *shrugs*..

nightsta69
09-21-2009, 09:56 AM
Also your code above will always return true.
if(!isloaded(packagename.c_str()) || isloaded(packagename.c_str()))

It's like putting if(1), since you're covering the two possible returns of isloaded(), it can either return 1 (which is on the second half) or 0 (which is on the left half).

But yeah. If you do what you just did, you essentially screw all zone-based player.pl files if it's only working off templates.

I may have to peek and see if I can solve the event handling to execute the two different player files. *shrugs*..

its still using the zone based files, IE for doors, creating instances, etc etc. only problem is if BOTH the zone, AND the template player.pl has the same event.(IE if both had sub EVENT_LEVEL_UP) then the template will override the zone pl. other then that, the zone pl works as intended. and yea I know i'm basically making it a true statement regardless, my C+ isn't all that great, I was just looking for a work around, and to see if it was even possible.

Striat_eq
09-22-2009, 11:32 AM
does $client->Message() broadcast worldwide, or just to the client that triggered the event?

The client that triggered.

quest::we(type, "message"); should work. This is world emote.

nightsta69
09-22-2009, 11:44 AM
ah there we go, thats what i've been lookin for, thanx alot.

nightsta69
09-22-2009, 01:06 PM
sub EVENT_LEVEL_UP {
my $maxlvl = 75;
my @classlist = ("Warrior", "Cleric", "Paladin", "Ranger", "ShadowKnight", "Druid", "Monk", "Bard", "Rogue", "Shaman", "Necromancer", "Wizard", "Magician", "Enchanter", "Beastlord", "Berserker");
foreach my $curclass (@classlist) {
if(!defined($qglobals{$curclass."maxlvl"}) && $ulevel == $maxlvl && $curclass eq $class) {
quest::setglobal($curclass."maxlvl",$name,2,"F");
quest::we(5,"$name has made the server first level $ulevel $class!");
return;
}
}
}
here is the completed code for announcments of server first lvl ups. if anyone wants it, have fun! thanks to shin nor and several others in this thread for helping me weed it out, and learn a thing or two! :D I plan on adding more custom stuff, as I delve deeper into the learning curve of perl, and C++. thanks again everyone.