PDA

View Full Version : Need new event


sandy
02-17-2004, 05:22 AM
hello =)
a lot of monsters have script based on their amount of hp in percent
we need a Event_HP for example ^^
thx

Monrezz
02-17-2004, 12:09 PM
Wouldn't need to be an event, would just need to add a line or 2 to parser.cpp saying npcmob->GetHP().

Take a took in parser.cpp and embparser.cpp and you'll figure it out pretty easy.

Then just use the variable you set (eg $mobhp) and use it an in if statement.

if(($mobhp >= 2000) && $text=~/Hail/i){quest::say("I have over 2k HP!");}

Monrezz
02-17-2004, 12:29 PM
Done (note this is for Perl):

zone\embparser.cpp ~ Line 165:
ExportVar(packagename.c_str(), "hp", itoa(mob->GetHP()));
ExportVar(packagename.c_str(), "mana", itoa(mob->GetMana()));

and ~ Line 174:
ExportVar(packagename.c_str(), "mclass", GetEQClassName(npcmob->GetClass()));
ExportVar(packagename.c_str(), "mobhp", itoa(npcmob->GetHP()));
ExportVar(packagename.c_str(), "mobmana", itoa(npcmob->GetMana()));

Example uses:

if($text =~ /hp/i)
{
quest::say("You have $hp hitpoints.");
}

if($text =~ /mana/i)
{
quest::say("You have $mana mana.");
}

if($text =~ /mobhp/i)
{
quest::say("I have $mobhp hitpoints.");
}

if($text =~ /mobmana/i)
{
quest::say("I have $mobmana mana.");
}

if($text =~ /mclass/i)
{
quest::say("I am a $mclass.");
}

Hope this helps.

Squiffy
02-17-2004, 01:20 PM
I think he's referring to Hitpoint-driven coding, not text-driven coding that retrieves a mob's hitpoints and outputs it.

IE Terris Thule encounter. Butterflies spawn at 75%, AE 15 buff dispell at 50%, 4 Gargoyles at 25%.

I'm sure there's workarounds to get the same effect done, but a hitpoint-driven event would be useful, as well. Don't know the Perl quest system, so this syntax may be completely wrong. Just giving a rough example.

ie

Event_HP (75) {
quest::emote("Terris Thule calls forth nightmarish wraiths");
for (x = 0, x < 21, x++) {
quest::spawn(a_nightmare_wraith, race, etc, etc);
}
}

Event_HP (50) {
quest:cast(WhateverTheAEDebuffSpellNumberIs);
}

Event_HP (25) {
for (x = 0, x < 4, x++) {
quest::spawn(a_gargoyle_thinger, etc);
}
}

Monrezz
02-17-2004, 01:25 PM
Could be done using what was posted above:

$75 = $mobhp*0.75
$50 = $mobhp*0.5
$25 = $mobhp*0.25

if($mobhp == $75){quest::spawn()}
if($mobhp == $50){quest::spawn()}
if($mobhp == $25){quest::spawn()}

Not perfect, but it could be done with a little effort.

Squiffy
02-17-2004, 01:30 PM
Yes, but what triggers these events to fire? Does the code just continuously loop every millisecond until one of the ifs is met? If so, that's rather inefficient.

Don't know if it makes a huge difference or not, I'm just used to making my code as efficient as possible, and I know if this were a program I was creating, I'd have it as an event that is called once, not an infinitely looping event with if statements.

lol and I just realized I mixed in C and VB in some mutated bastardized version of code there :roll:

Daeath
02-19-2004, 12:45 PM
Yes, but what triggers these events to fire? Does the code just continuously loop every millisecond until one of the ifs is met? If so, that's rather inefficient.

Well, has anyone had success with this script yet? Does it create alot of server lag? What do you suggest Squiffy? I'm curious since I'm doing a major overhaul of the PoNightmare and TT could really use this event...

m0oni9
02-19-2004, 05:24 PM
I have a quick and dirty interim way to implement this.

In Mob::CreateHPPacket(), mob.cpp, about line 688:
else
{
if(IsNPC() && IsEngaged())
parse->Event(EVENT_HP, GetNPCTypeID(), NULL, CastToNPC(), CastToMob());
ds->cur_hp=IsNPC()?(sint32)GetHPRatio():cur_hp;
ds->max_hp=100;
}


In PerlembParser::Event(), embparser.cpp, about line 184:
break;
}
case EVENT_HP: {
SendCommands(packagename.c_str(), "EVENT_HP", npcid,
npcmob, mob);
}
default: {



event_codes.h, add:
#define EVENT_HP 9
(imho would look better with enums in here)

You should now be able to make an EVENT_HP sub in your script. You can use the code Monrezz supplied to get access to mob HP, and possibly create another variable (ie: mobHPpercent). The problem with this implementation is that it is (possibly) invoked every time HP updates happen, which is very frequently -- however, I'll note that it didn't affect my load noticeably. I really can't see this being implemented in a way other than using a timer, and calling EVENT_HP sub on engaged mobs, so hopefully this won't be too far off.

Scorpious2k
02-20-2004, 12:39 AM
The only problem I see with this (not having checked the code) is: how many times per second will the event be triggered? Doesn't this have the potential to bring a server to its knees?

Monrezz
02-20-2004, 06:49 AM
He said it is called for everytime HP updates are called for, so it depends how often they're called for I guess :P

m0oni9
02-20-2004, 08:43 AM
The only problem I see with this (not having checked the code) is: how many times per second will the event be triggered? Doesn't this have the potential to bring a server to its knees?
Yes, it has the potential, as I noted. This isn't the final implementation serverside, but a quick add for anyone that wants to play around with this in their perl scripts. The way to go about using it would remain as creating an EVENT_HP sub, and accessing a, for example, mobhppercent variable.

I imagine it will be written this way: 1) keep a global list of mobs with aggro, 2) start a timer of 20 seconds or so, 3) run EVENT_HP for each mob in list. But that won't change how perl scripts use it, so it won't matter to script writers. Of course there may just be a timer inserted into how it currently functions. That could work too.

smogo
02-21-2004, 08:58 AM
the events described above are Mob AI events. For performance reasons, one could doubt it is safe to put them in perl scripts, especially if it is to be called every X ms.

However, it is insteresting to get triggers that run some script depending on HP. i guess the best would be to trigger a few events, like 'half-life', or 'low-life' at 10 % hp, maybe with some hysterisys or one-shot mechanisms.

The drawback is that we get these events triggered for every Mob ; so far, i don't think the code checks for what event is effectively used by the mob's script. One solution would be to flag this when the script is read from the file and compiled, one other to mark Mobs in the DB if they require additional triggers / variables (ala qglobal).

Lurker_005
02-21-2004, 05:01 PM
In a EVENT_ATTACK start a timer that fires every 5 sec or so. Then in EVENT_TIMER place teh code to check the HP. Perhaps work something out to turn off the timer also. That way if the attack failed the timer will eventually go away.

m0oni9
02-21-2004, 08:20 PM
Every mob does not send an HP update packet every second. It really starts when their HP < 100% (or when first engaged, have to double-check).

Also, a perl script isn't really "run" in the sense that it keeps reading these scripts off of the disk. They are compiled when loaded, and remain in memory for the duration of the package, afaik. This isn't taking into account exported variables, of course.

I hadn't thought of Lurker's idea. If the script timers are working well, that doesn't sound bad at all. We could export a variable that would say whether the mob was engaged or not, and when EVENT_TIMER was triggered, it could disable based on that.

On a side note, one of the things I don't like is the amount of variables exported. I have XS code that will work in terms of creating functions that can be called from perl, and receive a return value. You still would need to have a module.pm file somewhere for it to be able to deal with it, however. But this would eliminate some overhead.

Scorpious2k
02-22-2004, 01:45 AM
I hadn't thought of Lurker's idea. If the script timers are working well, that doesn't sound bad at all. We could export a variable that would say whether the mob was engaged or not, and when EVENT_TIMER was triggered, it could disable based on that.

Or an EVENT_HEALTH (as opposed to EVENT_HP so you could report mana etc too) as you suggested, but incorporate Lurker's idea of a timer. In other words, once the event is triggered, start a timer that won't allow it to be triggered again for a few seconds.

Wouldn't that satisfy both the need for the event and the concern for cpu/bandwidth conservation?

Also, although this has been discussed from a perl quest point of view, I would like to note that both formats are supported and any changes should work in both.

sandy
02-26-2004, 03:41 PM
one thing i found very nice for such type of script events was those used in neverwinter nights

in fact, every monster have some different type of events pre defined ( death, see something, on spawn etc ... ) and there was a default script for each of these events but they were not used except the onspawn one

in the onspawn script if we put this line :
SetSpawnInCondition (NW_FLAG_DEATH_EVENT);
then the ondeath script was fired when the monster died^

i don't know if it can help but it was a smart way to use such specific scripts of monsters