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

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Closed Thread
 
Thread Tools Display Modes
  #1  
Old 08-29-2007, 11:58 PM
cbodmer
Fire Beetle
 
Join Date: Oct 2006
Posts: 24
Default LDoN Open Button Support

Background:
With LDoN a special type of treasure chest was introduced, which players could "open" by clicking on the Open pushbutton. Most everyone should be familiar with this type of object.

Technically, chests are nothing other than a special type of NPC, having a spawnpoint and loot like any other mob. Opening a chest is instantly killing this mob, causing it to play its death animation (ie chest cracking open).

I've gone ahead and implemented an initial version of this functionality. It's still vs 1030, but it should be no problem to apply to a later version, since it's mostly one line additions. Since I only have a Titanium client to test with, I've only updated the Titanium Client opcode list so this will NOT work out of the box for any other clients.

Patches:
common/classes.h
Code:
--- ../EQEmu-0.7.0-1030/common/classes.h	2006-05-13 04:35:58.000000000 +0200
+++ ../EQEmu/common/classes.h	2007-08-30 10:36:40.000000000 +0200
@@ -58,6 +58,7 @@
 #define ADVENTURERECRUITER 60
 #define ADVENTUREMERCHANT 61
 #define CORPSE_CLASS 62	//only seen on Danvi's Corpse in Akheva so far..
+#define LDON_TREASURE 62 // LDON Treasure Chests, Barrels, etc.
 #define TRIBUTE_MASTER	63
 #define GUILD_TRIBUTE_MASTER	64	//not sure
 #define warrior_1 1
common/emu_oplist.h
Code:
--- ../EQEmu-0.7.0-1030/common/emu_oplist.h	2007-08-05 23:13:12.000000000 +0200
+++ ../EQEmu/common/emu_oplist.h	2007-08-30 00:30:46.000000000 +0200
@@ -355,6 +355,7 @@
 N(OP_ReclaimCrystals),
 N(OP_Report),
 N(OP_SenseHeading),
+N(OP_LDoNOpen),
 N(OP_DynamicWall),
 N(OP_RequestTitles),
 N(OP_PurchaseLeadershipAA),
common/opcode_dispatch.h
Code:
--- ../EQEmu-0.7.0-1030/common/opcode_dispatch.h	2007-07-22 22:54:32.000000000 +0200
+++ ../EQEmu/common/opcode_dispatch.h	2007-08-30 00:28:06.000000000 +0200
@@ -129,6 +129,7 @@
 INz(OP_FeignDeath);	//?
 INz(OP_Sneak);		//?
 INz(OP_Hide);		//?
+INz(OP_LDoNOpen);
 INv(OP_ChannelMessage, ChannelMessage_Struct);
 IN(OP_WearChange, WearChange_Struct);
 IN(OP_DeleteSpawn, EntityId_Struct);	//client->server follows OP_SaveOnZoneReq
People with access to other clients should try and see if they can find the "Open" Opcode for their client and update the config files accordingly.

utils/patch_Titanium.conf
Code:
--- ../EQEmu-0.7.0-1030/utils/patch_Titanium.conf	2007-08-05 23:13:12.000000000 +0200
+++ ../patch_Titanium.conf	2007-08-30 13:34:44.000000000 +0200
@@ -398,6 +398,7 @@
 OP_Sneak=0x74e1			
 OP_Fishing=0x0b36
 OP_InstillDoubt=0x389e		#intimidation
+OP_LDoNOpen=0x083b	# CB: open LDoN chest 08/30/07
 
 #Task packets
 OP_CompletedTasks=0x76a2			# ShowEQ 10/27/05
zone/aggro.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/aggro.cpp	2007-07-17 03:03:48.000000000 +0200
+++ ../EQEmu/zone/aggro.cpp	2007-08-30 11:26:44.000000000 +0200
@@ -455,7 +455,10 @@
 	// solar: the format here is a matrix of mob type vs mob type.
 	// redundant ones are omitted and the reverse is tried if it falls through.
 
-	
+	// cb: LDoN Treasure chests dont fight
+	if(this->GetClass() == LDON_TREASURE && this->GetBodyType() == BT_Boxes)
+		return(false);
+
 	// first figure out if we're pets.  we always look at the master's flags.
 	// no need to compare pets to anything
 	mob1 = our_owner ? our_owner : this;
The follow patch looks huge; all it really does is prevent players from getting
EXP for their chest "kills". I did some code reformatting, that is why there's so many changes.

zone/attack.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/attack.cpp	2007-08-11 08:14:57.000000000 +0200
+++ ../EQEmu/zone/attack.cpp	2007-08-30 11:47:45.000000000 +0200
@@ -1102,11 +1102,13 @@
 
 			char tmp[20];
 			database.GetVariable("ServerType", tmp, 9);
-			if(atoi(tmp)==1 && other != NULL && other->IsClient()){
+			if(atoi(tmp)==1 && other != NULL && other->IsClient())
+			{
 				char tmp2[10] = {0};
 				database.GetVariable("PvPreward", tmp, 9);
 				int reward = atoi(tmp);
-				if(reward==3){
+				if(reward==3)
+				{
 					database.GetVariable("PvPitem", tmp2, 9);
 					int pvpitem = atoi(tmp2);
 					if(pvpitem>0 && pvpitem<200000)
@@ -1118,11 +1120,15 @@
 					new_corpse->SetPKItem(1);
 				else
 					new_corpse->SetPKItem(0);
-				if(other->CastToClient()->isgrouped) {
+				if(other->CastToClient()->isgrouped) 
+				{
 					Group* group = entity_list.GetGroupByClient(other->CastToClient());
-					if(group != 0) {
-						for(int i=0;i<6;i++) {
-							if(group->members[i] != NULL) {
+					if(group != 0) 
+					{
+						for(int i=0;i<6;i++) 
+						{
+							if(group->members[i] != NULL) 
+							{
 								new_corpse->AllowMobLoot(group->members[i],i);
 							}
 						}
@@ -1490,7 +1496,6 @@
 
 	safe_delete(app);
 	
-	
 	Mob *give_exp = hate_list.GetDamageTop(this);
 	if(give_exp == NULL)
 		give_exp = killer;
@@ -1501,30 +1506,36 @@
 	if(give_exp && give_exp->IsClient())
 		give_exp_client = give_exp->CastToClient();
 	
-    if (give_exp_client && !IsCorpse() && MerchantType == 0)
+	if(!(this->GetClass() == LDON_TREASURE && this->GetBodyType() == BT_Boxes))
 	{
-		Group *kg = entity_list.GetGroupByClient(give_exp_client);
-		if (give_exp_client->IsGrouped() && kg != NULL)
+		// cb: if we're not a LDON treasure chest, we give XP
+	
+	  if (give_exp_client && !IsCorpse() && MerchantType == 0)
 		{
-			if(give_exp_client->GetAdventureID()>0){
-				AdventureInfo AF = database.GetAdventureInfo(give_exp_client->GetAdventureID());
-				if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_MASSKILL)
-					give_exp_client->SendAdventureUpdate();
-				else if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_NAMED && (AF.Objetive==GetNPCTypeID() || AF.ObjetiveValue==GetNPCTypeID()))
-					give_exp_client->SendAdventureFinish(1, AF.points,true);
+			Group *kg = entity_list.GetGroupByClient(give_exp_client);
+			if (give_exp_client->IsGrouped() && kg != NULL)
+			{
+				if(give_exp_client->GetAdventureID()>0){
+					AdventureInfo AF = database.GetAdventureInfo(give_exp_client->GetAdventureID());
+					if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_MASSKILL)
+						give_exp_client->SendAdventureUpdate();
+					else if(zone->GetZoneID() == AF.zonedungeonid && AF.type==ADVENTURE_NAMED && (AF.Objetive==GetNPCTypeID() || AF.ObjetiveValue==GetNPCTypeID()))
+						give_exp_client->SendAdventureFinish(1, AF.points,true);
+				}
+				kg->SplitExp((EXP_FORMULA), this);
+			}
+			else
+	    {
+	     	int conlevel = give_exp->GetLevelCon(GetLevel());
+	      if (conlevel != CON_GREEN)
+	      {
+				    give_exp_client->AddEXP((EXP_FORMULA), conlevel); // Pyro: Comment this if NPC death crashes zone
+	      }
 			}
-			kg->SplitExp((EXP_FORMULA), this);
-		}
-		else
-        {
-        	int conlevel = give_exp->GetLevelCon(GetLevel());
-            if (conlevel != CON_GREEN)
-            {
-			    give_exp_client->AddEXP((EXP_FORMULA), conlevel); // Pyro: Comment this if NPC death crashes zone
-            }
 		}
 	}
 	
+	
 	//do faction hits even if we are a merchant, so long as a player killed us
 	if(give_exp_client)
 		hate_list.DoFactionHits(GetNPCFactionID());
zone/client_packet.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/client_packet.h	2007-07-21 22:39:54.000000000 +0200
+++ ../EQEmu/zone/client_packet.h	2007-08-30 00:41:01.000000000 +0200
@@ -57,6 +57,7 @@
 	void Handle_OP_Camp(const EQApplicationPacket *app);
 	void Handle_OP_Logout(const EQApplicationPacket *app);
 	void Handle_OP_SenseHeading(const EQApplicationPacket *app);
+	void Handle_OP_LDoNOpen(const EQApplicationPacket *app);
 	void Handle_OP_FeignDeath(const EQApplicationPacket *app);
 	void Handle_OP_Sneak(const EQApplicationPacket *app);
 	void Handle_OP_Hide(const EQApplicationPacket *app);
zone/client_packet.cpp
Code:
--- ../EQEmu-0.7.0-1030/zone/client_packet.cpp	2007-08-05 23:13:12.000000000 +0200
+++ ../EQEmu/zone/client_packet.cpp	2007-08-30 11:27:13.000000000 +0200
@@ -157,6 +157,7 @@
 	ConnectedOpcodes[OP_Camp] = &Client::Handle_OP_Camp;
 	ConnectedOpcodes[OP_Logout] = &Client::Handle_OP_Logout;
 //	ConnectedOpcodes[OP_SenseHeading] = &Client::Handle_OP_SenseHeading;
+  ConnectedOpcodes[OP_LDoNOpen] = &Client::Handle_OP_LDoNOpen;
 	ConnectedOpcodes[OP_FeignDeath] = &Client::Handle_OP_FeignDeath;
 	ConnectedOpcodes[OP_Sneak] = &Client::Handle_OP_Sneak;
 	ConnectedOpcodes[OP_Hide] = &Client::Handle_OP_Hide;
@@ -2312,6 +2313,18 @@
 	return;
 }
 
+void Client::Handle_OP_LDoNOpen(const EQApplicationPacket *app)
+{
+	Mob * target = GetTarget();
+	if(target)
+	{
+		if(target->IsMob() && target->GetClass()==LDON_TREASURE && target->GetBodyType()==BT_Boxes)
+			target->Damage((Mob *)this, target->GetMaxHP()*2, SPELL_UNKNOWN, HAND_TO_HAND, false);
+		else
+		  cout << "Illegal target: OP_LDoNOpen expects mob class " << LDON_TREASURE << ", bodytype " << BT_Boxes << endl;
+	}
+}
+
 void Client::Handle_OP_Dye(const EQApplicationPacket *app)
 {
 	if(app->size!=sizeof(DyeStruct))
To test it, create a mob with any race/level, class=62 (LDON Chest) and bodytype=33 (BT_Boxes). I've included the bodytype criteria in order to make sure that there's very little chance of there being actual mobs with both class=62 and bodytype=33 in your databases.

Enjoy,
-Chris
  #2  
Old 08-30-2007, 02:37 AM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

Nice, ima go ahead and deal with these submissions on forum tonight I think and I'll look at this too.
  #3  
Old 08-30-2007, 05:12 AM
Teppen
Banned
 
Join Date: Jan 2002
Posts: 80
Default

IIRC, I think those LDON chests were also (or maybe it was random) but seemed to have traps on chests. I remember doing a LDON once and we were all medding up and the warrior saw a chest and said oh look a chest lets open it, and before the rogue could say WAIT!!! poof the warrior triggered the chest and got a nasty spell casted on him from not removing the trap first. It was horrible, we were just in our lower 20's and the spell that was casted on the warrior took a (might have bee higher..) level 49 cleric spell to disappear. lol. Cant remembe what spell it was but reduced all this stats to 1's or something like that.

Anyway, would there be away to put traps on these chests?

Good job btw, always look forward to new features like this.
  #4  
Old 08-30-2007, 05:49 AM
CrabClaw's Avatar
CrabClaw
Hill Giant
 
Join Date: Jun 2006
Location: Plane of Knowledge
Posts: 191
Default

Yes! Awsome

My whole guild used to do tons of LDoNs back in the day, it was our specialty actually instead of the usual big-time raiding.

The dreaded 'everyone-clear-out-the-instance-and-let-the-rogue-pick-it' chests! Poor guys....they were heroes if they got it off though.

The nasty little boxes would do a couple things, one cast a nasty AoE poison DoT that would eventually kill you regardless of level, make you uber-drunk, or blow up, and long term AoE fear (Which is why we waited till the end of the run to deal with them....). Not your choice, and the effects were uber-nasty, but made for some fun stories.

The chests were around trapped around 90% of the time (ballpark figure).

We usually cleared everyone out at the end and let the rogue handle them cause' the AoE effects filled most of the instance. They were though a great source of some neat instance specific drops, gems, coin and Augmentations. They had generous loot tables.

You just had to 'de-trap and pray' most of the time though.

Last edited by CrabClaw; 08-30-2007 at 01:52 PM..
  #5  
Old 08-30-2007, 08:26 AM
cbodmer
Fire Beetle
 
Join Date: Oct 2006
Posts: 24
Default

I'll see how traps could be done. I like the idea.
-Chris
  #6  
Old 08-30-2007, 11:08 AM
John Adams
Demi-God
 
Join Date: Jul 2006
Posts: 1,552
Default

Thank you, CB. My dreams of seeing LDoNs become a reality again are coming true.
  #7  
Old 08-31-2007, 02:28 PM
Striat
Sarnak
 
Join Date: Aug 2006
Posts: 60
Default

Nice addition. It will be very useful in the near future when conditions are implemented to restrict what is required to open a chest. But, it definitely is a nice start. Been missing this feature for a while.
  #8  
Old 08-31-2007, 02:51 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

This along with a plethora of other things on this forum will go in tonight most likely.

..just have to finish making sure it all works.
  #9  
Old 09-01-2007, 04:22 AM
gernblan
Discordant
 
Join Date: Aug 2006
Posts: 394
Default

Quote:
Originally Posted by cbodmer View Post
I'll see how traps could be done. I like the idea.
-Chris
I would think that putting quests on the npcid of the particular chest with a random EVENT_DEATH trap might emulate them.

With a script, can also do proximity stuff to chests.... or whatever else.

Anyway, it may be more flexible to do it this way than to hardcode something.

Just a thought.
__________________
--
Keelyeh
Owner, ServerOp and Developer
Jest 4 Server
Linux (Jest3 runs on Fedora, our Dev servers usually run on Ubuntu and/or Gentoo), OC-12 Connection = Hella Fast
  #10  
Old 09-02-2007, 05:10 AM
cbodmer
Fire Beetle
 
Join Date: Oct 2006
Posts: 24
Default Mods

ps: Mods, can you please edit my first post, remove all it says there and write something like "Obsolete - checked further down". Thanks.
__________________
Head Admin, Legacy of The Rathe server
http://eq.ismg.ch
  #11  
Old 09-02-2007, 05:49 AM
Angelox
AX Classic Developer
 
Join Date: May 2006
Location: filler
Posts: 2,049
Default

Thread closed, See new " Update to LDoN Open Button Support"
Closed Thread


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 09:56 AM.


 

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