Go Back   EQEmulator Home > EQEmulator Forums > Archives > Archive::Development > Archive::Development

Archive::Development Archive area for Development's posts that were moved here after an inactivity period of 90 days.

Reply
 
Thread Tools Display Modes
  #1  
Old 01-20-2004, 04:27 AM
Mongrel
Hill Giant
 
Join Date: Jul 2003
Location: Germany
Posts: 232
Default Fix: Invisibility and IVU (Huge! Requires DB change)

This is a pretty big update, so I probably made a mistake somewhere in this post. I'll update this accordingly.

Note to the devs: I'd love to post this in a better way, but I don't know how to use diffs. It's a large update, sorry if it's confusing at some points.

Another note: Some of the linebreaks might be wrong (they shouldn't though). I had to add them to make this somewhat readable.

@Trump: If this is too large for you to merge (not meant as an insult!), maybe you could send me your cvs version and I'll merge it in myself.

To make invis and IVU work we have to change the DB structure a bit and modify the code for zone.exe.

DB changes:
First we need to change our NPC Types table. We will add three columns: see_invis, see_invis_undead and undead. All three are pretty self-explanatory, however they're not linked with each other in any way shape or form. That way it's easy to make high level undeads that can see through Invis vs. Undead or boss mobs that see through normal Invisibility.

Here are the SQL commands to change the DB (copy&paste the commands below into a text file):

Code:
-- Add a see_invis, see_invis_undead and an undead column
ALTER TABLE npc_types ADD COLUMN 
(
see_invis TINYINT NOT NULL default '0',
see_invis_undead TINYINT NOT NULL default '1'
);
This will make all our mobs "alive" and able to see through IVU, but not through invis.

Here are SQL commands to make a few npcs undead:

Code:
-- Change race 14 (Werewolf) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=14;

-- Change race 27 (Froglok Ghoul) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=27;

-- Change race 32 (Ghost) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=32;

-- Change race 33 (Ghoul) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=33;

-- Change race 45 (Demi Lich) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=45;

-- Change race 60 (Skeleton) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=60;

-- Change race 65 (Vampire) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=65;

-- Change race 70 (Zombie) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=70;

-- Change race 85 (Spectre) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=85;

-- Change race 98 (Elf Vampire) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=98;

-- Change race 117 (Ghost Dwarf) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=117;

-- Change race 118 (Erudite Ghost) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=118;

-- Change race 122 (Dragon Skeleton) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=122;

-- Change race 146 (Spectral Sarnak) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=146;

-- Change race 147 (Spectral Iksar) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=147;

-- Change race 155 (Sarnak Skeleton) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=155;

-- Change race 161 (Iksar Skeleton) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=161;

-- Change race 174 (Cold Spectre) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=174;

-- Change race 196 (Ghost Dragon) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=196;

-- Change race 208 (Vampyre) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=208;

-- Change race 234 (Vah Shir Skeleton) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=234;

-- Change race 282 (Skeletal Horse) to undead
UPDATE npc_types SET see_invis=1, see_invis_undead=0 WHERE race=282;
I'm sure I missed a few PoP undeads, but I never played PoP on live, so I don't really know those races. Feel free to add a few on your own.
That was easy, wasn't it? Gets a lot more difficult now ...

Now to the code changes:
In zone/zonedump.h add the following two lines to the structure NPCType:

Code:
	bool	see_invis;			// Mongrel: See Invis flag added
	bool	see_invis_undead;	// Mongrel: See Invis flag added
At this point you may have to rebuild EQEmuShareMem. While I was debugging this I found that sizeof(NPCType) returned the wrong value. Recompiling fixed this.

In common/database.cpp search for the following line four times. The first appearance is right at the top of the file, we don't want that one. The second and third appearances is about items and doors, we don't need those. The fourth appearance is the one we need (about npc_types).
Code:
#ifdef SHAREMEM
Inside this #ifdef block you will find a function named bool Database:BLoadNPCTypes(). This function is used to load the NPC Types from the DB when you're using EQEmuShareMem. I doubt anyone is using the non-sharemem version, so won't go into that now.

Inside bool Database:BLoadNPCTypes() look for the following lines:
Code:
			NPCType tmpNPCType;
			// support the old database too for a while...
        		// neotokyo: added aggroradius
        		// neotokyo: added bodytype
			MakeAnyLenString(&query, "SELECT id,name,level,race,class,hp,gender,texture,helmtexture,size,loottable_id, merchant_id, banish, mindmg, maxdmg, npcspecialattks, npc_spells_id, d_meele_texture1,d_meele_texture2, walkspeed, runspeed,fixedz,hp_regen_rate,mana_regen_rate,aggroradius,bodytype,npc_faction_id,face FROM npc_types");//WHERE zone='%s'", zone_name
			if (RunQuery(query, strlen(query), errbuf, &result))
			{
Replace it with:
Code:
			NPCType tmpNPCType;
			// support the old database too for a while...
        		// neotokyo: added aggroradius
        		// neotokyo: added bodytype
			MakeAnyLenString(&query, "SELECT id,name,level,race,class,hp,gender,texture,helmtexture,size,loottable_id, merchant_id, banish, mindmg, maxdmg, npcspecialattks, npc_spells_id, d_meele_texture1,d_meele_texture2, walkspeed, runspeed,fixedz,hp_regen_rate,mana_regen_rate,aggroradius,
bodytype,npc_faction_id,face,see_invis,see_invis_undead FROM npc_types");//WHERE zone='%s'", zone_name
			if (RunQuery(query, strlen(query), errbuf, &result))
			{
I have added "see_invis,see_invis_undead" to the end of the query.

Then change this:
Code:
					tmpNPCType.luclinface=atoi(row[27]);
                			// set defaultvalue for aggroradius
					if (tmpNPCType.aggroradius <= 0)
                    			    tmpNPCType.aggroradius = 70;

					//tmpNPCType.ipc = atoi(row[27]);
to this:
Code:
					tmpNPCType.luclinface=atoi(row[27]);
                			// set defaultvalue for aggroradius
					if (tmpNPCType.aggroradius <= 0)
                    			    tmpNPCType.aggroradius = 70;

					tmpNPCType.see_invis = atoi(row[28]);
					tmpNPCType.see_invis_undead = atoi(row[29]);
							//tmpNPCType.ipc = atoi(row[27]);
At this point the NPC Types have been updated, however mobs, when spawned, do not know about this yet. That's what we'll do next.

In zone/mob.h find the constructor of the class "mob"
Code:
	Mob(const char*   in_name,
	    const char*   in_lastname,
	    sint32  in_cur_hp,
	    sint32  in_max_hp,

// Many more lines of code here ... skipping ...

	    int16   in_d_meele_texture1,
	    int16   in_d_meele_texture2
	);
	virtual ~Mob();
add the following two lines to the end of the constructor:
Code:
		int8	in_see_invis,
		int8	in_see_invis_undead
The result should look like this:
Code:
	Mob(const char*   in_name,
	    const char*   in_lastname,
	    sint32  in_cur_hp,
	    sint32  in_max_hp,

// Many more lines of code here ... skipping ...

	    int16   in_d_meele_texture1,
	    int16   in_d_meele_texture2,
		int8	in_see_invis,
		int8	in_see_invis_undead
	);
	virtual ~Mob();
Do not forget to add the comma after "in_d_meele_texture2"

Now search for the following lines in the same file:
Code:
	inline bool SeeInvisible() { return false; }
	inline bool SeeInvisibleUndead() { return true; }
	
	bool IsInvisible(Mob* other = 0) {
	// TC - removing until SeeInvisible is implemented.
	//if (other && other->SeeInvisible() && !sneaking) { return false; }
		if (other && !sneaking) { return false; }
	   if (sneaking && BehindMob(other, GetX(), GetY()) ){ return true; }
       else { return invisible; }
    }
Replace it with:
Code:
	inline bool SeeInvisible() { return see_invis; }				// Mongrel: Now using the flags
	inline bool SeeInvisibleUndead() { return see_invis_undead; }	// Mongrel: Now using the flags
	
	bool IsInvisible(Mob* other = 0) 
	{
	// TC - removing until SeeInvisible is implemented.
	// Mongrel: Reimplementing see invis
		if (other && invisible && !other->SeeInvisible()) 
		{ 
			return true; 
		}
		if (other && invisible_undead && !other->SeeInvisibleUndead()) 
		{ 
			return true; 
		}
		if (other && !sneaking) 
		{ 
			return false; 
		}
		if (sneaking && BehindMob(other, GetX(), GetY()) )
		{ 
			return true; 
		}
		else 
		{ 
			return invisible; 
		}
	}
Now find this (still in zone/mob.h)
Code:
	bool	invulnerable;
	bool	invisible, invisible_undead, sneaking;
	void	Spin();
	void	Kill();
Replace with:
Code:
	bool	invulnerable;
	bool	invisible, invisible_undead, sneaking;
	bool	see_invis, see_invis_undead;	// Mongrel: See Invis and See Invis vs. Undead
	void	Spin();
	void	Kill();
Now open zone/mob.cpp and apply the changes we just made to the constructor:
Change
Code:
		 int8	in_luclinface, // and beard
		 int8	in_aa_title,
		 float	in_fixed_z,
		 int16	in_d_meele_texture1,
		 int16	in_d_meele_texture2
		 )
{
to

Code:
		 int8	in_luclinface, // and beard
		 int8	in_aa_title,
		 float	in_fixed_z,
		 int16	in_d_meele_texture1,
		 int16	in_d_meele_texture2,
		 int8	in_see_invis,
		 int8	in_see_invis_undead
		 )
{
At the end of the constructor change:
Code:
	pStandingPetOrder = SPO_Follow;
	
	// Bind wound
	bindwound_timer = new Timer(10000);
	bindwound_timer->Disable();
	bindwound_target = 0;
to

Code:
	pStandingPetOrder = SPO_Follow;

	see_invis = in_see_invis;
	see_invis_undead = in_see_invis_undead;
	
	// Bind wound
	bindwound_timer = new Timer(10000);
	bindwound_timer->Disable();
	bindwound_target = 0;
Now open zone/npc.cpp and search for the following:
Code:
	  d->fixedZ,
	  d->d_meele_texture1,
	  d->d_meele_texture2)
{
	Mob* mob = entity_list.GetMob(name);
Replace with:
Code:
	  d->fixedZ,
	  d->d_meele_texture1,
	  d->d_meele_texture2,
	  d->see_invis,
	  d->see_invis_undead
	  )
{
	Mob* mob = entity_list.GetMob(name);
Open zone/client.cpp and find:
Code:
	1, // fixedz
	0, // standart text1
	0 // standart text2
	)
{
	for(int cf=0;cf<21;cf++)
Replace with:

Code:
	1, // fixedz
	0, // standart text1
	0, // standart text2
	0, // see_invis
	0 // see_invis_undead
	)
{
	for(int cf=0;cf<21;cf++)
Open zone/PlayerCorpse.cpp and search for:
Code:
// To be used on NPC death and ZoneStateLoad
Corpse::Corpse(NPC* in_npc, ItemList** in_itemlist, int32 in_npctypeid, NPCType** in_npctypedata, int32 in_decaytime)
 : Mob("Unnamed_Corpse","",0,0,in_npc->GetGender(),in_npc->GetRace(),in_npc->GetClass(),0//bodytype added
       ,in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),0,in_npc->GetSize(),0,0,
in_npc->GetHeading(),in_npc->GetX(),in_npc->GetY(),in_npc->GetZ(),0,0,in_npc->GetTexture(),
in_npc->GetHelmTexture(),0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,1,0,0)
{
Replace with:
Code:
// To be used on NPC death and ZoneStateLoad
Corpse::Corpse(NPC* in_npc, ItemList** in_itemlist, int32 in_npctypeid, NPCType** in_npctypedata, int32 in_decaytime)
 : Mob("Unnamed_Corpse","",0,0,in_npc->GetGender(),in_npc->GetRace(),in_npc->GetClass(),0//bodytype added
       ,in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),0,in_npc->GetSize(),0,0,
in_npc->GetHeading(),in_npc->GetX(),in_npc->GetY(),in_npc->GetZ(),0,0,in_npc->GetTexture(),
in_npc->GetHelmTexture(),0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,1,0,0,0,0)
{
This just adds two zeros at the end for the two new flags

Repeat with
Code:
// To be used on PC death
Corpse::Corpse(Client* client, PlayerProfile_Struct* pp, sint32 in_rezexp, int8 iCorpseLevel)
 : Mob("Unnamed_Corpse","",0,0,client->GetGender(),client->GetRace(),client->GetClass(), 0, // bodytype added
        client->GetDeity(),client->GetLevel(),0,0, client->GetSize(), 0, 0,client->GetHeading(),client->GetX(),client->GetY(),client->GetZ(),0,0,client->GetTexture(),
client->GetHelmTexture(),0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,1,0,0)
{
change to:
Code:
// To be used on PC death
Corpse::Corpse(Client* client, PlayerProfile_Struct* pp, sint32 in_rezexp, int8 iCorpseLevel)
 : Mob("Unnamed_Corpse","",0,0,client->GetGender(),client->GetRace(),client->GetClass(), 0, // bodytype added
        client->GetDeity(),client->GetLevel(),0,0, client->GetSize(), 0, 0,client->GetHeading(),client->GetX(),client->GetY(),client->GetZ(),0,0,client->GetTexture(),
client->GetHelmTexture(),0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,1,0,0,0,0)
{
and again ... find:
Code:
// To be called from LoadFromDBData
Corpse::Corpse(int32 in_dbid, int32 in_charid, char* in_charname, ItemList* in_itemlist, int32 in_copper, int32 in_silver, int32 in_gold, int32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, int8 in_gender, int16 in_race, int8 in_class, int8 in_deity, int8 in_level, int8 in_texture, int8 in_helmtexture,int32 in_rezexp)
 : Mob("Unnamed_Corpse","",0,0,in_gender, in_race, in_class, 0, in_deity, in_level,0,0, in_size, 0, 0, in_heading, in_x, in_y, in_z,0,0,in_texture,in_helmtexture,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,1,0,0)
{
change to:
Code:
// To be called from LoadFromDBData
Corpse::Corpse(int32 in_dbid, int32 in_charid, char* in_charname, ItemList* in_itemlist, int32 in_copper, int32 in_silver, int32 in_gold, int32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, int8 in_gender, int16 in_race, int8 in_class, int8 in_deity, int8 in_level, int8 in_texture, int8 in_helmtexture,int32 in_rezexp)
 : Mob("Unnamed_Corpse","",0,0,in_gender, in_race, in_class, 0, in_deity, in_level,0,0, in_size, 0, 0, in_heading, in_x, in_y, in_z,0,0,in_texture,in_helmtexture,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,1,0,0,0,0)
{
Ok, we're almost done now. Open zone/spells.cpp. Function bool Mob::SpellEffect():

Search for "case SE_InvisVsUndead"
Replace
Code:
			case SE_InvisVsUndead: {
#ifdef SPELL_EFFECT_SPAM
				Message(0, "Effect #%i: You cast an Invis Vs Undead spell.", i);
#endif
				Mob *p = this->GetPet();
				if (p)
with
Code:
			case SE_InvisVsUndead: {
#ifdef SPELL_EFFECT_SPAM
				Message(0, "Effect #%i: You cast an Invis Vs Undead spell.", i);
#endif
				invisible_undead = true;
				Mob *p = this->GetPet();
				if (p)
In function void Mob::BuffFadeBySlot() replace
Code:
			case SE_Invisibility: {
				invisible = false;
				break;
			}
with
Code:
			case SE_Invisibility: {
				invisible = false;
				break;
			}
			case SE_InvisVsUndead: {
				invisible_undead = false;
				break;
			}
I've tested this quite a lot and it works. As I already mentioned at the beginning of this post, I might have forgotten something somewhere.

Well, that's it. It could be done in an easier way, but doing it like above makes invis/ivu very flexible.

Edit: Rewrote some lines. They weren't exactly wrong, but sometimes it wasn't clear what I meant.
Reply With Quote
  #2  
Old 01-20-2004, 04:53 AM
Trumpcard
Demi-God
 
Join Date: Jan 2002
Location: Charlotte, NC
Posts: 2,614
Default

Wow... What a change !

I'll look at it tonight, but it shouldnt be too hard to merge in.
__________________
Quitters never win, and winners never quit, but those who never win and never quit are idiots.
Reply With Quote
  #3  
Old 01-20-2004, 08:40 PM
Mongrel
Hill Giant
 
Join Date: Jul 2003
Location: Germany
Posts: 232
Default

I just tested this with Shawn cvs from 01-12-04 and found an error in my post. I forgot to add something, which made the fix not working:

(Note: I've also added this to my initial post.)

-----------------------------------------

Now open zone/mob.cpp and apply the changes we just made to the constructor:
Change
Code:
		 int8	in_luclinface, // and beard
		 int8	in_aa_title,
		 float	in_fixed_z,
		 int16	in_d_meele_texture1,
		 int16	in_d_meele_texture2
		 )
{
to

Code:
		 int8	in_luclinface, // and beard
		 int8	in_aa_title,
		 float	in_fixed_z,
		 int16	in_d_meele_texture1,
		 int16	in_d_meele_texture2,
		 int8	in_see_invis,
		 int8	in_see_invis_undead
		 )
{
At the end of the constructor change:
Code:
	pStandingPetOrder = SPO_Follow;
	
	// Bind wound
	bindwound_timer = new Timer(10000);
	bindwound_timer->Disable();
	bindwound_target = 0;
to

Code:
	pStandingPetOrder = SPO_Follow;

	see_invis = in_see_invis;
	see_invis_undead = in_see_invis_undead;
	
	// Bind wound
	bindwound_timer = new Timer(10000);
	bindwound_timer->Disable();
	bindwound_target = 0;
-----------------------------------------
Reply With Quote
  #4  
Old 01-20-2004, 08:50 PM
devn00b's Avatar
devn00b
Demi-God
 
Join Date: Jan 2002
Posts: 15,658
Default

btw body type (existing colum in the db) flags wether a mob is undead or not.
__________________
(Former)Senior EQEMu Developer
GuildWars Co-Founder / World Builder.
World Builder and Co-Founder Zek [PVP/Guild Wars/City Takeovers]
Member of the "I hate devn00b" Club
Most Senior EQEMu Member.

Current Work: EverQuest 2 Emulator. Zeklabs Server
Reply With Quote
  #5  
Old 01-20-2004, 10:46 PM
Mongrel
Hill Giant
 
Join Date: Jul 2003
Location: Germany
Posts: 232
Default

D'oh! Sorry.

I removed the undead flag from the code above. (Sorry Trump!)

If you already added the undead column to your DB, use the following query to remove it:

Code:
ALTER TABLE npc_types DROP COLUMN undead;
Reply With Quote
  #6  
Old 01-20-2004, 10:48 PM
Mongrel
Hill Giant
 
Join Date: Jul 2003
Location: Germany
Posts: 232
Default

And don't tell me that there already existed a column for see invis as well. Gonna jump off the next building then.
Reply With Quote
  #7  
Old 01-21-2004, 12:01 AM
Trumpcard
Demi-God
 
Join Date: Jan 2002
Location: Charlotte, NC
Posts: 2,614
Default

This is going to be a hard one to put in without diff/patch files, just because of the sheer number of changes necessary...
__________________
Quitters never win, and winners never quit, but those who never win and never quit are idiots.
Reply With Quote
  #8  
Old 01-21-2004, 01:28 AM
Mongrel
Hill Giant
 
Join Date: Jul 2003
Location: Germany
Posts: 232
Default

Wanna send me your code then? I tested it with Shawn cvs and since I already know where to put the changes, it only took me 5 mins.
Reply With Quote
  #9  
Old 01-21-2004, 01:37 AM
Wiz
Dragon
 
Join Date: Feb 2002
Posts: 583
Default

I just reference bodytype for undead/animal.
Reply With Quote
  #10  
Old 01-21-2004, 02:18 AM
Trumpcard
Demi-God
 
Join Date: Jan 2002
Location: Charlotte, NC
Posts: 2,614
Default

I just pushed out the latest CVS code.

Pull it off sourceforge and merge it there, and send it to me.. I'll do my best to merge it (assuming nothing major gets merged between now and then)
__________________
Quitters never win, and winners never quit, but those who never win and never quit are idiots.
Reply With Quote
  #11  
Old 01-21-2004, 03:25 AM
Mongrel
Hill Giant
 
Join Date: Jul 2003
Location: Germany
Posts: 232
Default

sent you a PM
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 04:38 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3