EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Server Code Submissions (https://www.eqemulator.org/forums/forumdisplay.php?f=669)
-   -   Disable levitate effects in certain zones? (https://www.eqemulator.org/forums/showthread.php?t=23717)

gernblan 10-02-2007 08:34 AM

Disable levitate effects in certain zones?
 
Zones like the hole (where on live levitation effects are disabled), or other zones where players can currently levitate their way to success by climbing some wall then floating over to the top floor of some building or whatnot is a pain... I am wondering if anyone knows of a way or can think of a doable way to force levitate effects off in a zone?

We have some zones that are pretty much an open book if players can levitate to laces they shouldn't be able to get to. I'd love to be able to turn levitation off in those zones.

Just wondering if anyone can offer some guidance on how this may be accomplished.

Thank you.

gernblan 10-06-2007 01:27 PM

What about if someone smarter than I can modify the #nukebuffs command so that it can also nuke single spells? Maybe a #nukebuff command can be added that works like:

#nukebuff <spellid> and it nukes that buff from the player
whereas #nukebuffs will still nuke them all?

Can make it a quest object too and in scripts we can put an invisible mob in the game with a proximity check that will $client->nukebuff(spellnum) the spells we want nuked.

A fancy way to do it might be to give it an array as input, so we can list the spells to nuke... like:

$client->nukebuff(spell1,spell2,spell3,spell4,spell5)

And

#nukebuff spell1 spell2 spell3 spell4

Like that.

This alone would give us the ability to emulate zones like Siren's grotto properly (nuking the speed/lev buffs at the zone in) OR even set an npc in the middle of the zone with a zone-wide proximity trigger and a timer that keeps them nuked in a zone.

I'm sure there's a cleaner way to approach this... such as setting zone flags in the database to allow or disallow and having something global simply turning those spells off in those zones or whatnot.... but heck, I dunno.

I just think this is badly needed, especially since it IS available on live and should be emulated if at all possible, you know?

Oh, also, it will definitely help against certain exploits where people can levitate, climb stuff then float to parts of the zone they should be so easily able to reach without fighting their way to them.

KLS 10-06-2007 01:34 PM

I think we should really just make certain zones lev restricted, I noticed it a while back too but haven't gotten around to implementing it yet.

gernblan 10-06-2007 02:14 PM

Yes that WOULD be the best solution for certain.

Would there be any way to choose which zones are level restricted too (I mean, they wouldn't be hardcoded would they?)

I ask because for example, we're working on a custom zone (an OZ zone that we made) and it has lots of towers in it and multi level stuff. We'd definitely want lev off in that zone.

gernblan 10-06-2007 02:15 PM

l would be nice to be able to nukebuff just one buff from a player though... so that if a GM only wants to remove one effect from a player, they can, without having to nuke them all just to get rid of the one.

Magoth78 11-01-2007 11:00 AM

As requested, zone can be levitate restricted.
http://eqoffline.free.fr/levitrestricted.jpg

Code changes:

1/ In zone.h,
after
Code:

bool        CanDoCombat() const { return(can_combat); }
add
Code:

bool    CanLevitate() const {return(can_levitate); }
after
Code:

bool        can_combat;
add
Code:

bool    can_levitate;
In the file: zonedb.h,
replace
Code:

bool GetZoneCFG(int32 zoneid, NewZone_Struct *data, bool &can_bind, bool &can_combat);
by
Code:

bool GetZoneCFG(int32 zoneid, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate);
In the file zone.cpp and in the function Zone::LoadZoneCFG,
replace
Code:

if(!database.GetZoneCFG(database.GetZoneID(filename), &newzone_data, can_bind, can_combat)) {
by
Code:

if(!database.GetZoneCFG(database.GetZoneID(filename), &newzone_data, can_bind, can_combat, can_levitate)) {
In the file zonedb.cpp,
replace
Code:

bool ZoneDatabase::GetZoneCFG(int32 zoneid, NewZone_Struct *zone_data, bool &can_bind, bool &can_combat) {
        char errbuf[MYSQL_ERRMSG_SIZE];
        char *query = 0;
        MYSQL_RES *result;
        MYSQL_ROW row;
        int i=0;
        bool good = false;
        if (RunQuery(query, MakeAnyLenString(&query, "SELECT ztype,"
                "fog_red,fog_green,fog_blue,fog_minclip,fog_maxclip,"
                "fog_red2,fog_green2,fog_blue2,fog_minclip2,fog_maxclip2,"
                "fog_red3,fog_green3,fog_blue3,fog_minclip3,fog_maxclip3,"
                "fog_red4,fog_green4,fog_blue4,fog_minclip4,fog_maxclip4,"
                "sky,zone_exp_multiplier,safe_x,safe_y,safe_z,underworld,"
                "minclip,maxclip,time_type,canbind,cancombat"
                " from zone where zoneidnumber=%i",zoneid), errbuf, &result)) {
                safe_delete_array(query);
                while((row = mysql_fetch_row(result))) {
                        int r = 0;
                        memset(zone_data,0,sizeof(NewZone_Struct));
                        zone_data->ztype=atoi(row[r++]);
                       
                        for(i=0;i<4;i++){
                                zone_data->fog_red[i]=atoi(row[r++]);
                                zone_data->fog_green[i]=atoi(row[r++]);
                                zone_data->fog_blue[i]=atoi(row[r++]);
                                zone_data->fog_minclip[i]=atof(row[r++]);
                                zone_data->fog_maxclip[i]=atof(row[r++]);
                        }
                       
                        zone_data->sky=atoi(row[r++]);
                        zone_data->zone_exp_multiplier=atof(row[r++]);
                        zone_data->safe_x=atof(row[r++]);
                        zone_data->safe_y=atof(row[r++]);
                        zone_data->safe_z=atof(row[r++]);
                        zone_data->underworld=atof(row[r++]);
                        zone_data->minclip=atof(row[r++]);
                        zone_data->maxclip=atof(row[r++]);
                       
                        zone_data->time_type=atoi(row[r++]);
//not in the DB yet:
                        zone_data->gravity = 0.4;
                       
                        can_bind = atoi(row[r++])==0?false:true;
                        can_combat = atoi(row[r++])==0?false:true;
                       
                        good = true;
                }
                mysql_free_result(result);
        }
        else
                LogFile->write(EQEMuLog::Error, "Error in GetZoneCFG query %s: %s", query, errbuf);
        safe_delete_array(query);
       
        zone_data->zone_id = zoneid;
       
        return(good);
}

by
Code:

bool ZoneDatabase::GetZoneCFG(int32 zoneid, NewZone_Struct *zone_data, bool &can_bind, bool &can_combat, bool &can_levitate) {
        char errbuf[MYSQL_ERRMSG_SIZE];
        char *query = 0;
        MYSQL_RES *result;
        MYSQL_ROW row;
        int i=0;
        bool good = false;
        if (RunQuery(query, MakeAnyLenString(&query, "SELECT ztype,"
                "fog_red,fog_green,fog_blue,fog_minclip,fog_maxclip,"
                "fog_red2,fog_green2,fog_blue2,fog_minclip2,fog_maxclip2,"
                "fog_red3,fog_green3,fog_blue3,fog_minclip3,fog_maxclip3,"
                "fog_red4,fog_green4,fog_blue4,fog_minclip4,fog_maxclip4,"
                "sky,zone_exp_multiplier,safe_x,safe_y,safe_z,underworld,"
                "minclip,maxclip,time_type,canbind,cancombat,canlevitate"
                " from zone where zoneidnumber=%i",zoneid), errbuf, &result)) {
                safe_delete_array(query);
                while((row = mysql_fetch_row(result))) {
                        int r = 0;
                        memset(zone_data,0,sizeof(NewZone_Struct));
                        zone_data->ztype=atoi(row[r++]);
                       
                        for(i=0;i<4;i++){
                                zone_data->fog_red[i]=atoi(row[r++]);
                                zone_data->fog_green[i]=atoi(row[r++]);
                                zone_data->fog_blue[i]=atoi(row[r++]);
                                zone_data->fog_minclip[i]=atof(row[r++]);
                                zone_data->fog_maxclip[i]=atof(row[r++]);
                        }
                       
                        zone_data->sky=atoi(row[r++]);
                        zone_data->zone_exp_multiplier=atof(row[r++]);
                        zone_data->safe_x=atof(row[r++]);
                        zone_data->safe_y=atof(row[r++]);
                        zone_data->safe_z=atof(row[r++]);
                        zone_data->underworld=atof(row[r++]);
                        zone_data->minclip=atof(row[r++]);
                        zone_data->maxclip=atof(row[r++]);
                       
                        zone_data->time_type=atoi(row[r++]);
//not in the DB yet:
                        zone_data->gravity = 0.4;
                       
                        can_bind = atoi(row[r++])==0?false:true;
                        can_combat = atoi(row[r++])==0?false:true;
            can_levitate = atoi(row[r++])==0?false:true;
                       
                        good = true;
                }
                mysql_free_result(result);
        }
        else
                LogFile->write(EQEMuLog::Error, "Error in GetZoneCFG query %s: %s", query, errbuf);
        safe_delete_array(query);
       
        zone_data->zone_id = zoneid;
       
        return(good);
}

In the file spells.cpp, in the function Mob::SpellFinished(int16 spell_id, Mob *spell_target, int16 slot, int16 mana_used),
find
Code:

if(!IsValidSpell(spell_id))
                return false;

and, add after
Code:

if( IsEffectInSpell(spell_id, SE_Levitate) && !zone->CanLevitate() )
    {
        if( IsClient() )
        {
            if(!CastToClient()->GetGM())
            {
                Message(13, "You can't levitate in this zone.");
                            return false;
            }
        }
    }

In the file client_packet.cpp, function Complete_Connect(),
replace
Code:

case SE_Levitate:
        {
                          SendAppearancePacket(AT_Levitate, 2);
                          break;
        }

by
Code:

case SE_Levitate:
        {
                        if( !zone->CanLevitate() )
                        {
                            if(!GetGM())
                            {
                                SendAppearancePacket(AT_Levitate, 0);
                                BuffFadeByEffect(SE_Levitate);
                                Message(13, "You can't levitate in this zone.");
                            }
                        }else{
                            SendAppearancePacket(AT_Levitate, 2);
                        }
                        break;
        }

SQL changes:
Code:

alter table `zone` add column `canlevitate` tinyint (4) DEFAULT '1' NOT NULL  after `cancombat`
I've tested it with the zone: The Hole.
It seems to work correctly.

Mag.

gernblan 11-02-2007 12:31 AM

Incredible!!! Thank You!

gernblan 11-17-2007 12:56 AM

This IS INDEED great!

KLS or someone, please, this is SO BADLY needed... can it be committed please?

cavedude 11-20-2007 03:17 AM

I have this up on TGC and it indeed is working wonderfully. It even strips lev off the player if they enter a no lev zone already buffed. Very nice.

This thread should be moved to Development submission, but I'll let Wild know about it.

Angelox 11-20-2007 09:39 AM

Thanks Magoth78! I was wondering if you could do the same with SOW? I'm tired of seeing NPC's in dungeons running around on like if they snorted coke - not to mention PC's shouldn't be sowed either.

cavedude 11-20-2007 09:55 AM

That goes for any "indoor" spell. Right now, Druids are really doing pretty well for themselves because they can cast anywhere. A good portion of their spells should be outdoor only. I think there is data in the spell files concerning whether a spell is restricted by indoor/outdoor. Perhaps that can be tapped into and a new column in zone be created?

KLS 11-20-2007 11:49 AM

I was looking for this code a week ago but couldn't find it.. buried in another post apparently.

I'll probably mod it to apply to all indoor type spells.

sfisque 11-21-2007 06:22 AM

Quote:

Originally Posted by Angelox (Post 140484)
Thanks Magoth78! I was wondering if you could do the same with SOW? I'm tired of seeing NPC's in dungeons running around on like if they snorted coke - not to mention PC's shouldn't be sowed either.

IIRC, Live didnt restrict npc's this way. i remember frog shamans sow'ing up in Sebilis as well as other npcs doing the same in other zones. they may have changed this at some point, but it was always a bone in my craw when i played live.

/em remembers /shouting "SNARE!! SNARE!!! FOR THE LOVE OF GOD, SNARE IT!!!!"

== sfisque

gernblan 11-27-2007 07:57 PM

Excellent, thank you!!

Angelox 04-12-2008 04:01 PM

Any chance we can get this code in the source?

Thanks in advance

Angelox 04-14-2008 06:49 PM

I'm praying this one gets into the source, haven't seen anything else on it anymore.

KLS 04-14-2008 10:09 PM

I had lost it for a while but since I see it again it'll get in.

gernblan 04-20-2008 03:16 AM

Yes, that's right.

In indoor zones, if you were already sow'd from outside, you could keep it until it faded indoors. You just could not CAST sow while indoors.

IF this code is combined and stuff, please don't tie it all to one switch... it would be nice to say "no lev but yes to run speed effects" or "yes lev but no run speed effects can be cast" -- not both on or both off only, please.

Angelox 04-29-2008 08:10 PM

KLS;
I tried PM to you on this;
Quote:

KLS: (Magoth78), (Angelox)Added zone checks for levitating and being outdoors.
should read
Quote:

KLS: (Magoth78), (Qadar)Added zone checks for levitating and being outdoors.
Qadar was the one with the fix for the spells that work outdoors; outdoors only and Indoor spells; Indoors only.
I just posted the fix.

Thanks

KingMort 07-06-2008 07:12 PM

Could you also make code for COH type spells not working in zones or designated areas of zones ?

trevius 07-06-2008 08:45 PM

I too think that limiting Call of the Hero on a per zone basis would be nice. I am not a coder, but I can use examples of code and alter them fairly well normally. Using the using examples of the code that Magoth and Qadar used for the canlevitate and cancastoutdoor settings, here is what I think would be needed to setup a similar system for Call of the Hero:

zone.h
Code:

After - bool    CanCastOutdoor() const {return(can_castoutdoor);} //qadar
+bool    CanCotH() const {return(can_coth); } //trevius

After - bool    can_levitate;
+bool    can_coth;

zonedb.h
Code:

-bool        GetZoneCFG(int32 zoneid, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city);
+bool        GetZoneCFG(int32 zoneid, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &can_coth);

zone.cpp
Code:

-        if(!database.GetZoneCFG(database.GetZoneID(filename), &newzone_data, can_bind, can_combat, can_levitate, can_castoutdoor, is_city)) {
+        if(!database.GetZoneCFG(database.GetZoneID(filename), &newzone_data, can_bind, can_combat, can_levitate, can_castoutdoor, is_city, can_coth)) {

In zonedb.cpp Remove:
Code:

bool ZoneDatabase::GetZoneCFG(int32 zoneid, NewZone_Struct *zone_data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city) {
        char errbuf[MYSQL_ERRMSG_SIZE];
        char *query = 0;
        MYSQL_RES *result;
        MYSQL_ROW row;
        int i=0;
        int b=0;
        bool good = false;
        if (RunQuery(query, MakeAnyLenString(&query, "SELECT ztype,"
                "fog_red,fog_green,fog_blue,fog_minclip,fog_maxclip,"
                "fog_red2,fog_green2,fog_blue2,fog_minclip2,fog_maxclip2,"
                "fog_red3,fog_green3,fog_blue3,fog_minclip3,fog_maxclip3,"
                "fog_red4,fog_green4,fog_blue4,fog_minclip4,fog_maxclip4,"
                "sky,zone_exp_multiplier,safe_x,safe_y,safe_z,underworld,"
                "minclip,maxclip,time_type,canbind,cancombat,canlevitate,castoutdoor"
                " from zone where zoneidnumber=%i",zoneid), errbuf, &result)) {
                safe_delete_array(query);
                while((row = mysql_fetch_row(result))) {
                        int r = 0;
                        memset(zone_data,0,sizeof(NewZone_Struct));
                        zone_data->ztype=atoi(row[r++]);
                       
                        for(i=0;i<4;i++){
                                zone_data->fog_red[i]=atoi(row[r++]);
                                zone_data->fog_green[i]=atoi(row[r++]);
                                zone_data->fog_blue[i]=atoi(row[r++]);
                                zone_data->fog_minclip[i]=atof(row[r++]);
                                zone_data->fog_maxclip[i]=atof(row[r++]);
                        }
                       
                        zone_data->sky=atoi(row[r++]);
                        zone_data->zone_exp_multiplier=atof(row[r++]);
                        zone_data->safe_x=atof(row[r++]);
                        zone_data->safe_y=atof(row[r++]);
                        zone_data->safe_z=atof(row[r++]);
                        zone_data->underworld=atof(row[r++]);
                        zone_data->minclip=atof(row[r++]);
                        zone_data->maxclip=atof(row[r++]);
                       
                        zone_data->time_type=atoi(row[r++]);
//not in the DB yet:
                        zone_data->gravity = 0.4;
                       
                        b = atoi(row[r++]);
                        can_bind = b==0?false:true;
                        is_city = b==2?true:false;
                        can_combat = atoi(row[r++])==0?false:true;
                            can_levitate = atoi(row[r++])==0?false:true;
                        can_castoutdoor = atoi(row[r++])==0?false:true;
                       
                        good = true;
                }
                mysql_free_result(result);
        }
        else
                LogFile->write(EQEMuLog::Error, "Error in GetZoneCFG query %s: %s", query, errbuf);
        safe_delete_array(query);
       
        zone_data->zone_id = zoneid;
       
        return(good);
}

And in zonedb.cpp, replace what was just removed with:
Code:

bool ZoneDatabase::GetZoneCFG(int32 zoneid, NewZone_Struct *zone_data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &can_coth) {
        char errbuf[MYSQL_ERRMSG_SIZE];
        char *query = 0;
        MYSQL_RES *result;
        MYSQL_ROW row;
        int i=0;
        int b=0;
        bool good = false;
        if (RunQuery(query, MakeAnyLenString(&query, "SELECT ztype,"
                "fog_red,fog_green,fog_blue,fog_minclip,fog_maxclip,"
                "fog_red2,fog_green2,fog_blue2,fog_minclip2,fog_maxclip2,"
                "fog_red3,fog_green3,fog_blue3,fog_minclip3,fog_maxclip3,"
                "fog_red4,fog_green4,fog_blue4,fog_minclip4,fog_maxclip4,"
                "sky,zone_exp_multiplier,safe_x,safe_y,safe_z,underworld,"
                "minclip,maxclip,time_type,canbind,cancombat,canlevitate,castoutdoor,cancoth"
                " from zone where zoneidnumber=%i",zoneid), errbuf, &result)) {
                safe_delete_array(query);
                while((row = mysql_fetch_row(result))) {
                        int r = 0;
                        memset(zone_data,0,sizeof(NewZone_Struct));
                        zone_data->ztype=atoi(row[r++]);
                       
                        for(i=0;i<4;i++){
                                zone_data->fog_red[i]=atoi(row[r++]);
                                zone_data->fog_green[i]=atoi(row[r++]);
                                zone_data->fog_blue[i]=atoi(row[r++]);
                                zone_data->fog_minclip[i]=atof(row[r++]);
                                zone_data->fog_maxclip[i]=atof(row[r++]);
                        }
                       
                        zone_data->sky=atoi(row[r++]);
                        zone_data->zone_exp_multiplier=atof(row[r++]);
                        zone_data->safe_x=atof(row[r++]);
                        zone_data->safe_y=atof(row[r++]);
                        zone_data->safe_z=atof(row[r++]);
                        zone_data->underworld=atof(row[r++]);
                        zone_data->minclip=atof(row[r++]);
                        zone_data->maxclip=atof(row[r++]);
                       
                        zone_data->time_type=atoi(row[r++]);
//not in the DB yet:
                        zone_data->gravity = 0.4;
                       
                        b = atoi(row[r++]);
                        can_bind = b==0?false:true;
                        is_city = b==2?true:false;
                        can_combat = atoi(row[r++])==0?false:true;
                            can_levitate = atoi(row[r++])==0?false:true;
                        can_castoutdoor = atoi(row[r++])==0?false:true;
                        can_coth = atoi(row[r++])==0?false:true;
                       
                        good = true;
                }
                mysql_free_result(result);
        }
        else
                LogFile->write(EQEMuLog::Error, "Error in GetZoneCFG query %s: %s", query, errbuf);
        safe_delete_array(query);
       
        zone_data->zone_id = zoneid;
       
        return(good);
}

In spells.cpp After:
Code:

spells.cpp - function Mob::SpellFinished(int16 spell_id, Mob *spell_target, int16 slot, int16 mana_used),
After:
        if(IsEffectInSpell(spell_id, SE_Levitate) && !zone->CanLevitate()){
                        if(IsClient()){
                                if(!CastToClient()->GetGM()){
                                        Message(13, "You can't levitate in this zone.");
                                        return false;
                                }
                        }
                }

Add: (Note that this is the only part I am unsure about. I highlighted the questionable part in RED and will check more into it later unless someone else can get that part fixed)
Code:

        if(spells[spell_id].spell_id == 1771 && !zone->CanCotH()){
                if(IsClient()){
                                if(!CastToClient()->GetGM()){
                                        Message(13, "You cannot summon players in this zone.");
                                        return false;
                                }
                        }
                }

Required SQL:
Code:

alter table `zone` add column `cancoth` tinyint (4) DEFAULT '1' NOT NULL  after `canlevitate`
I haven't tested this code yet, but I will try to get it added tonight on my server maybe. I will post back here if it works.


All times are GMT -4. The time now is 05:08 PM.

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